Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /* SPDX-License-Identifier: GPL-2.0-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *  linux/arch/arm/vfp/vfphw.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  Copyright (C) 2004 ARM Limited.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *  Written by Deep Blue Solutions Limited.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * This code is called from the kernel's undefined instruction trap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * r9 holds the return address for successful handling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * lr holds the return address for unrecognised instructions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * r10 points at the start of the private FP workspace in the thread structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * sp points to a struct pt_regs (as defined in include/asm/proc/ptrace.h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/linkage.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <asm/thread_info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <asm/vfpmacros.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/kern_levels.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <asm/assembler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <asm/asm-offsets.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	.macro	DBGSTR, str
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	stmfd	sp!, {r0-r3, ip, lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	ldr	r0, =1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	bl	printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	ldmfd	sp!, {r0-r3, ip, lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	.pushsection .rodata, "a"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 1:	.ascii	KERN_DEBUG "VFP: \str\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	.byte	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	.previous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	.endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	.macro  DBGSTR1, str, arg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	stmfd	sp!, {r0-r3, ip, lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	mov	r1, \arg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	ldr	r0, =1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	bl	printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	ldmfd	sp!, {r0-r3, ip, lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	.pushsection .rodata, "a"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 1:	.ascii	KERN_DEBUG "VFP: \str\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	.byte	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	.previous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	.endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	.macro  DBGSTR3, str, arg1, arg2, arg3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	stmfd	sp!, {r0-r3, ip, lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	mov	r3, \arg3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	mov	r2, \arg2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	mov	r1, \arg1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	ldr	r0, =1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	bl	printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	ldmfd	sp!, {r0-r3, ip, lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	.pushsection .rodata, "a"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 1:	.ascii	KERN_DEBUG "VFP: \str\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	.byte	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	.previous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	.endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) @ VFP hardware support entry point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) @
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) @  r0  = instruction opcode (32-bit ARM or two 16-bit Thumb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) @  r2  = PC value to resume execution after successful emulation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) @  r9  = normal "successful" return address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) @  r10 = vfp_state union
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) @  r11 = CPU number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) @  lr  = unrecognised instruction return address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) @  IRQs enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) ENTRY(vfp_support_entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	DBGSTR3	"instr %08x pc %08x state %p", r0, r2, r10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	.fpu	vfpv2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	VFPFMRX	r1, FPEXC		@ Is the VFP enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	DBGSTR1	"fpexc %08x", r1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	tst	r1, #FPEXC_EN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	bne	look_for_VFP_exceptions	@ VFP is already enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	DBGSTR1 "enable %x", r10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	ldr	r3, vfp_current_hw_state_address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	orr	r1, r1, #FPEXC_EN	@ user FPEXC has the enable bit set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	ldr	r4, [r3, r11, lsl #2]	@ vfp_current_hw_state pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	bic	r5, r1, #FPEXC_EX	@ make sure exceptions are disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	cmp	r4, r10			@ this thread owns the hw context?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) #ifndef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	@ For UP, checking that this thread owns the hw context is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	@ sufficient to determine that the hardware state is valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	beq	vfp_hw_state_valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	@ On UP, we lazily save the VFP context.  As a different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	@ thread wants ownership of the VFP hardware, save the old
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	@ state if there was a previous (valid) owner.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	VFPFMXR	FPEXC, r5		@ enable VFP, disable any pending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 					@ exceptions, so we can get at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 					@ rest of it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	DBGSTR1	"save old state %p", r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	cmp	r4, #0			@ if the vfp_current_hw_state is NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	beq	vfp_reload_hw		@ then the hw state needs reloading
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	VFPFSTMIA r4, r5		@ save the working registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	VFPFMRX	r5, FPSCR		@ current status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #ifndef CONFIG_CPU_FEROCEON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	tst	r1, #FPEXC_EX		@ is there additional state to save?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	beq	1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	VFPFMRX	r6, FPINST		@ FPINST (only if FPEXC.EX is set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	tst	r1, #FPEXC_FP2V		@ is there an FPINST2 to read?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	beq	1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	VFPFMRX	r8, FPINST2		@ FPINST2 if needed (and present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	stmia	r4, {r1, r5, r6, r8}	@ save FPEXC, FPSCR, FPINST, FPINST2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) vfp_reload_hw:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	@ For SMP, if this thread does not own the hw context, then we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	@ need to reload it.  No need to save the old state as on SMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	@ we always save the state when we switch away from a thread.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	bne	vfp_reload_hw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	@ This thread has ownership of the current hardware context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	@ However, it may have been migrated to another CPU, in which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	@ case the saved state is newer than the hardware context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	@ Check this by looking at the CPU number which the state was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	@ last loaded onto.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	ldr	ip, [r10, #VFP_CPU]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	teq	ip, r11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	beq	vfp_hw_state_valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) vfp_reload_hw:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	@ We're loading this threads state into the VFP hardware. Update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	@ the CPU number which contains the most up to date VFP context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	str	r11, [r10, #VFP_CPU]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	VFPFMXR	FPEXC, r5		@ enable VFP, disable any pending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 					@ exceptions, so we can get at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 					@ rest of it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	DBGSTR1	"load state %p", r10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	str	r10, [r3, r11, lsl #2]	@ update the vfp_current_hw_state pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 					@ Load the saved state back into the VFP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	VFPFLDMIA r10, r5		@ reload the working registers while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 					@ FPEXC is in a safe state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	ldmia	r10, {r1, r5, r6, r8}	@ load FPEXC, FPSCR, FPINST, FPINST2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #ifndef CONFIG_CPU_FEROCEON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	tst	r1, #FPEXC_EX		@ is there additional state to restore?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	beq	1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	VFPFMXR	FPINST, r6		@ restore FPINST (only if FPEXC.EX is set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	tst	r1, #FPEXC_FP2V		@ is there an FPINST2 to write?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	beq	1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	VFPFMXR	FPINST2, r8		@ FPINST2 if needed (and present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	VFPFMXR	FPSCR, r5		@ restore status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) @ The context stored in the VFP hardware is up to date with this thread
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) vfp_hw_state_valid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	tst	r1, #FPEXC_EX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	bne	process_exception	@ might as well handle the pending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 					@ exception before retrying branch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 					@ out before setting an FPEXC that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 					@ stops us reading stuff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	VFPFMXR	FPEXC, r1		@ Restore FPEXC last
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	sub	r2, r2, #4		@ Retry current instruction - if Thumb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	str	r2, [sp, #S_PC]		@ mode it's two 16-bit instructions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 					@ else it's one 32-bit instruction, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 					@ always subtract 4 from the following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 					@ instruction address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	dec_preempt_count_ti r10, r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	ret	r9			@ we think we have handled things
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) look_for_VFP_exceptions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	@ Check for synchronous or asynchronous exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	tst	r1, #FPEXC_EX | FPEXC_DEX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	bne	process_exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	@ On some implementations of the VFP subarch 1, setting FPSCR.IXE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	@ causes all the CDP instructions to be bounced synchronously without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	@ setting the FPEXC.EX bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	VFPFMRX	r5, FPSCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	tst	r5, #FPSCR_IXE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	bne	process_exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	tst	r5, #FPSCR_LENGTH_MASK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	beq	skip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	orr	r1, r1, #FPEXC_DEX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	b	process_exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) skip:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	@ Fall into hand on to next handler - appropriate coproc instr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	@ not recognised by VFP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	DBGSTR	"not VFP"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	dec_preempt_count_ti r10, r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	ret	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) process_exception:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	DBGSTR	"bounce"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	mov	r2, sp			@ nothing stacked - regdump is at TOS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	mov	lr, r9			@ setup for a return to the user code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	@ Now call the C code to package up the bounce to the support code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	@   r0 holds the trigger instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	@   r1 holds the FPEXC value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	@   r2 pointer to register dump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	b	VFP_bounce		@ we have handled this - the support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 					@ code will raise an exception if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 					@ required. If not, the user code will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 					@ retry the faulted instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) ENDPROC(vfp_support_entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) ENTRY(vfp_save_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	@ Save the current VFP state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	@ r0 - save location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	@ r1 - FPEXC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	DBGSTR1	"save VFP state %p", r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	VFPFSTMIA r0, r2		@ save the working registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	VFPFMRX	r2, FPSCR		@ current status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	tst	r1, #FPEXC_EX		@ is there additional state to save?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	beq	1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	VFPFMRX	r3, FPINST		@ FPINST (only if FPEXC.EX is set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	tst	r1, #FPEXC_FP2V		@ is there an FPINST2 to read?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	beq	1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	VFPFMRX	r12, FPINST2		@ FPINST2 if needed (and present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	stmia	r0, {r1, r2, r3, r12}	@ save FPEXC, FPSCR, FPINST, FPINST2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	ret	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) ENDPROC(vfp_save_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	.align
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) vfp_current_hw_state_address:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	.word	vfp_current_hw_state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	.macro	tbl_branch, base, tmp, shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) #ifdef CONFIG_THUMB2_KERNEL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	adr	\tmp, 1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	add	\tmp, \tmp, \base, lsl \shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	ret	\tmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	add	pc, pc, \base, lsl \shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	mov	r0, r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	.endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) ENTRY(vfp_get_float)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	tbl_branch r0, r3, #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	.fpu	vfpv2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 1:	vmov	r0, s\dr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	ret	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	.org	1b + 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	.endr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	.irp	dr,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 1:	vmov	r0, s\dr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	ret	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	.org	1b + 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	.endr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) ENDPROC(vfp_get_float)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ENTRY(vfp_put_float)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	tbl_branch r1, r3, #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	.fpu	vfpv2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 1:	vmov	s\dr, r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	ret	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	.org	1b + 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	.endr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	.irp	dr,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 1:	vmov	s\dr, r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	ret	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	.org	1b + 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	.endr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) ENDPROC(vfp_put_float)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) ENTRY(vfp_get_double)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	tbl_branch r0, r3, #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	.fpu	vfpv2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 1:	vmov	r0, r1, d\dr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	ret	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	.org	1b + 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	.endr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) #ifdef CONFIG_VFPv3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	@ d16 - d31 registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	.fpu	vfpv3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	.irp	dr,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 1:	vmov	r0, r1, d\dr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	ret	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	.org	1b + 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	.endr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	@ virtual register 16 (or 32 if VFPv3) for compare with zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	mov	r0, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	mov	r1, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	ret	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) ENDPROC(vfp_get_double)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) ENTRY(vfp_put_double)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	tbl_branch r2, r3, #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	.fpu	vfpv2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 1:	vmov	d\dr, r0, r1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	ret	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	.org	1b + 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	.endr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) #ifdef CONFIG_VFPv3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	.fpu	vfpv3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	@ d16 - d31 registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	.irp	dr,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 1:	vmov	d\dr, r0, r1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	ret	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	.org	1b + 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	.endr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) ENDPROC(vfp_put_double)