📄 vfpsubarch.s
字号:
;;; vfpsubarch.s
;;; sub-architecture support for:
;;; the VFP9, VFP10, VFP11 family of co-processors
;;; the VFP10 rev0 co-processor
;;; Copyright (C) ARM Limited, 2002. All rights reserved.
AREA |.text|, CODE, READONLY
CODE32
;;; int _VFP_ExceptionState_Size(void)
;;; returns the size of the buffer used by
;;; _VFP_Save_ExceptionState and _VFP_Restore_ExceptionState
_VFP_ExceptionState_Size PROC
MOV r0, #12
BX lr
ENDP
;;; void _VFP_Save_ExceptionState(void *)
;;; r0 points to a buffer reserved for the result
_VFP_Save_ExceptionState PROC
FMRX r1, FPEXC
FMRX r2, FPINST
;;; The FPINST2 register does not exist on VFP10rev0, so we test FP2V
TST r1, #(1 << 28) ;; check FP2V: FPINST2 is valid
FMRXNE r3, FPINST2
STMIA r0, {r1, r2, r3}
BX lr
ENDP
;;; void _VFP_Restore_ExceptionState(void *)
;;; r0 points to a buffer initialized by _VFP_Save_ExceptionState
_VFP_Restore_ExceptionState PROC
LDMIA r0, {r1, r2, r3}
;;; FPEXC must be restored first: This ensures the EX bit is set if
;;; this function is interrupted while there is state in the exception
;;; registers.
FMXR FPEXC, r1
FMXR FPINST, r2
;;; The FPINST2 register does not exist on VFP10rev0, so we test FP2V
TST r1, #(1 << 28) ;; check FP2V: FPINST2 is valid
FMXRNE FPINST2, r3
BX lr
ENDP
;;; bool _VFP_IsComputeException(unsigned int)
;;; r0 contains the bounced instruction, and is ignored.
;;; on return r0 is:
;;; 0 for a bounce caused by an illegal instruction
;;; 1 for any other bounce
_VFP_Is_Compute_Exception PROC
FMRX r0, FPEXC
;;; return 1 for a pending computational bounce, EX bit set
;;; return 0 for an illegal instruction bounce, EX bit clear
MOV r0, r0, LSR #31 ;; return EX, bit 31
BX lr
ENDP
;;; bool _VFP_Collect_Trap_Description(
;;; _VFP_Computation_Description *desc, unsigned int instr)
;;; r0 points to some memory reserved for the result
;;; r1 contains the bounced instruction, and is ignored.
;;; on return r0 is:
;;; 0 for an imprecise bounce, return to bounced instruction
;;; 1 for a precise bounce, return to next instruction
_VFP_Collect_Trap_Description PROC
FMRX r12, FPEXC
;;; collect faulting instruction description in r2
FMRX r2, FPINST
BIC r2, r2, #0x00000e00 ;; clear top cp_num bits [11..9]
BIC r2, r2, #0xff000000 ;; clear cond & CDP bits [31..24]
;;; check for VFP10 rev0
;;; VFP10 rev0 FPSID value is 0x410000A0
;;; VFP10 rev1 FPSID value is 0x410101A0
;;; bits [23..16] give the architecture version
;;; bits [15..8] give the part number
FMRX r1, FPSID
LDR r3, =0x410000A0 ;; ID code for VFP10 rev0
CMP r1, r3
;;; VFP10 rev0 vector length is out-by-one for some instructions
BEQ fixup_vfp10r0_vlen
vfp10r0_vlen_standard
;;; get the remaining vector length from FPEXC VECITR bits [10..8]
;;; this is in ((vector length - 1) % 8) format, as in the FPSCR
ADD r1, r12, #(1 << 8) ;; add one for the faulting iteration
AND r1, r1, #(7 << 8) ;; mask out bits [10..8]
vfp10r0_vlen_fixed
;;; vlen in r1, starting at bit 8
ORR r2, r2, r1, LSL #16 ;; move to bits [26..24], and add to op
TST r12, #(1 << 28) ;; check FP2V: FPINST2 is valid
BNE collect_op2
;;; write out computation description
;;; no second operation, so count is 1
MOV r1, #1
MOV r3, #0 ;; clear reserved words
STMIA r0!, {r1, r3} ;; write count, flags
STMIA r0!, {r2, r3} ;; write first entry
;;; clear exception flag
;;; EX must be clear before attempting to read the FPSCR
BIC r12, r12, #(1 << 31) ;; clear EX bit 31
FMXR FPEXC, r12
;;; check inexact enable, IXE, bit 12 of FPSCR
FMRX r0, FPSCR
MOV r0, r0, LSR #12
AND r0, r0, #1
;;; return 0 for imprecise bounce, IXE = 0,
;;; re-execute bounced instruction
;;; return 1 for precise bounce, IXE = 1,
;;; do not re-execute bounced instruction
BX lr
collect_op2
;;; r0 points to the computation description
;;; r2 contains op[0]
;;; r12 is a copy of FPEXC
;;; FP2V is set
;;; collect pending instruction in FPINST2
FMRX r3, FPINST2
BIC r3, r3, #0x00000e00 ;; clear top cp_num bits [11..9]
;; bits [31..28] contain the cond field
;; bits [27..24] are always 0b1110
;; bit 4 is always zero
BIC r3, r3, #0xff000000 ;; clear bits [31..24]
;;; clear exception flag
;;; EX must be clear before attempting to read the FPSCR
;;; also the FP2V bit is sticky and must be cleared on bounce
BIC r12, r12, #((1 << 31)|(1 << 28)) ;; clear EX and FP2V
FMXR FPEXC, r12
;;; use vector length in FPSCR LEN field bits [18..16]
;;; this is in ((vector length - 1) % 8) format, as required for op
FMRX r1, FPSCR
AND r1, r1, #(7 << 16) ;; mask out bits [18..16]
ORR r3, r3, r1, LSL #8 ;; move to bits [26..24], and add to op
;;; write out computation description
;;; op count is 2
MOV r1, #2
MOV r12, #0 ;; clear reserved words
STMIA r0!, {r1, r12} ;; count, flags
STMIA r0!, {r2, r12} ;; 1st entry
STMIA r0!, {r3, r12} ;; 2nd entry
;;; return 0 for imprecise bounce
MOV r0, #0
BX lr
fixup_vfp10r0_vlen
;;; r0 points to the computation description
;;; r2 contains the instruction bits of op[0]
;;; r12 is a copy of FPEXC
;;; The VFP10rev0 returns the pre-incremented vector-length for
;;; FMULD, FSQRT and FDIV instructions.
;;; The op decode bits are:
;;; 31 23 15 7 0
;;; 0b 0000 0000 pXqr ---- XXXX XXX- NsX0 XXXX
;;; with Fn in bits [19..16] and
;;; the precision (0 is single, 1 is double) in bit 8
P_BIT EQU (1 << 23)
Q_BIT EQU (1 << 21)
R_BIT EQU (1 << 20)
FN_BIT3 EQU (1 << 19)
FN_BIT2 EQU (1 << 18)
FN_BIT1 EQU (1 << 17)
FN_BIT0 EQU (1 << 16)
PRECISION_BIT EQU (1 << 8)
N_BIT EQU (1 << 7)
S_BIT EQU (1 << 6)
;;; Attempt to match op to one of these instructions:
;;; FDIV has pqrs == 1000
;;; FMULD has pqrs == 0100, and bit 8 is set
;;; FSQRT has pqrs == 1111, Fn == 0001 and N is set
;;; Vector length is ignored for all the extended instructions
;;; with Fn >= 2, (compares and conversions)
MVN r1, r2
TST r2, #P_BIT
BNE p_set
;; pqrs == 0xxx
TST r1, #Q_BIT ;; no match if NE
;; if EQ, then pqrs == 01xx
TSTEQ r2, #R_BIT ;; no match if NE
;; if EQ, then pqrs == 010x
TSTEQ r2, #S_BIT ;; no match if NE
;; if EQ, then pqrs == 0100, we have an FMUL
TSTEQ r1, #PRECISION_BIT ;; no match if NE
;; if EQ, then we have an FMULD
BNE vfp10r0_vlen_standard
B vlen_needs_fix
p_set
;; pqrs == 1xxx
TST r2, #S_BIT
BNE s_set
;; pqrs == 1xx0
TST r2, #(Q_BIT | R_BIT) ;; no match if NE
;; if EQ, then pqrs == 1000, we have an FDIV
BNE vfp10r0_vlen_standard
B vlen_needs_fix
s_set
;; pqrs == 1xx1
TST r1, #(Q_BIT | R_BIT | FN_BIT0) ;; no match if NE
;; if EQ, then pqrs == 1111, Fn == xxx1
TSTEQ r2, #(FN_BIT3 | FN_BIT2 | FN_BIT1) ;; no match if NE
;; if EQ, then pqrs == 1111, Fn == 0001
TSTEQ r1, #N_BIT
;; if EQ, then we have an FSQRT
BNE vfp10r0_vlen_standard
;;; fall-through
vlen_needs_fix
;;; Get the remaining vector length from FPEXC VECITR bits [10..8]
;;; Do NOT add one for the faulting iteration
AND r1, r12, #(7 << 8) ;; mask out bits [10..8]
B vfp10r0_vlen_fixed
ENDP
EXPORT _VFP_ExceptionState_Size
EXPORT _VFP_Save_ExceptionState
EXPORT _VFP_Restore_ExceptionState
EXPORT _VFP_Is_Compute_Exception
EXPORT _VFP_Collect_Trap_Description
END
;;; end of file vfpsubarch.s
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -