Commit febc8da4 authored by Jeffrey Lee's avatar Jeffrey Lee
Browse files

Add support for Cortex-A7 & Cortex-A15 FPUs. Add short vector mode emulation for Cortex-A7, A9, A15

Detail:
  Makefile - Simplify decision about whether to include support code. More hardware needs it than not, so have a list of machine types which don't need it rather than a list of machine types which do.
  hdr/VFPSupport - Add definitions for new VFPSupport_Features reason code
  hdr/shared - Add some comments for extra clarity
  s/Instructions - Add support for emulating VFPv3 'VMOV immediate' instruction
  s/Module - Update hardware detection & support handlers to deal with Cortex-A7, Cortex-A9 and Cortex-A15, all of which report different subarchitectures and differ in method of reporting exceptions despite the fact they basically all have the same requirements as far as support code is concerned (support code only required if we want short vector emulation). Implement the new VFPSupport_Features reason code, which returns information about whether short vectors are supported.
  s/SupportCode - Extend support code to cope with Cortex-A7, A9, A15 & VMOV imm emulation.
  Test/features,ffb - Simple test of VFPSupport_Features SWI
  Test/test7,ffb - Test for VFPv3 'VMOV immediate' handling in scalar & vector mode (HW scalar implementation tested against SW vector implementation)
Admin:
  Tested on ARM1176JZF-S, Cortex-A7, Cortex-A8, Cortex-A9
  Cortex-A15 supported tested 'in theory' by forcing appropriate support code to be installed on Cortex-A9


Version 0.10. Tagged as 'VFPSupport-0_10'
parent 2d17aa73
......@@ -30,9 +30,11 @@
# Use machine type to determine whether support code is needed
# Can also be overridden on command line by specifying SUPPORTCODE
DEFSUPPORTCODE = FALSE
ifneq (,$(findstring ${MACHINE},All All32 ARM11ZF RPi))
# Assuming we're targeting a machine capable of VFP, Cortex-A8 is currently the
# only machine type which doesn't need any support code at all
DEFSUPPORTCODE = TRUE
ifneq (,$(findstring ${MACHINE},CortexA8))
DEFSUPPORTCODE = FALSE
endif
SUPPORTCODE ?= ${DEFSUPPORTCODE}
......
File added
......@@ -11,13 +11,13 @@
GBLS Module_HelpVersion
GBLS Module_ComponentName
GBLS Module_ComponentPath
Module_MajorVersion SETS "0.09"
Module_Version SETA 9
Module_MajorVersion SETS "0.10"
Module_Version SETA 10
Module_MinorVersion SETS ""
Module_Date SETS "03 Feb 2015"
Module_ApplicationDate SETS "03-Feb-15"
Module_Date SETS "08 Feb 2015"
Module_ApplicationDate SETS "08-Feb-15"
Module_ComponentName SETS "VFPSupport"
Module_ComponentPath SETS "mixed/RiscOS/Sources/HWSupport/VFPSupport"
Module_FullVersion SETS "0.09"
Module_HelpVersion SETS "0.09 (03 Feb 2015)"
Module_FullVersion SETS "0.10"
Module_HelpVersion SETS "0.10 (08 Feb 2015)"
END
/* (0.09)
/* (0.10)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.09
#define Module_MajorVersion_CMHG 0.10
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 03 Feb 2015
#define Module_Date_CMHG 08 Feb 2015
#define Module_MajorVersion "0.09"
#define Module_Version 9
#define Module_MajorVersion "0.10"
#define Module_Version 10
#define Module_MinorVersion ""
#define Module_Date "03 Feb 2015"
#define Module_Date "08 Feb 2015"
#define Module_ApplicationDate "03-Feb-15"
#define Module_ApplicationDate "08-Feb-15"
#define Module_ComponentName "VFPSupport"
#define Module_ComponentPath "mixed/RiscOS/Sources/HWSupport/VFPSupport"
#define Module_FullVersion "0.09"
#define Module_HelpVersion "0.09 (03 Feb 2015)"
#define Module_LibraryVersionInfo "0:9"
#define Module_FullVersion "0.10"
#define Module_HelpVersion "0.10 (08 Feb 2015)"
#define Module_LibraryVersionInfo "0:10"
......@@ -85,6 +85,11 @@ VFPSupport_Field_RegDump * 5
VFPSupport_Features_SystemRegs * 0
VFPSupport_Features_VFPExceptions * 1
VFPSupport_Features_Misc * 2
; Misc feature flags
VFPSupport_MiscFeature_VFPVectors_HW * 1 :SHL: 0 ; VFP short vectors are supported by hardware
VFPSupport_MiscFeature_VFPVectors_SW * 1 :SHL: 1 ; VFP short vectors are supported by software
; Flags for ExceptionDump
......
......@@ -34,15 +34,15 @@ OldOpt SETA {OPT}
; Layout of the exception processing workspace
^ 0
XCRelocOffset # 4 ; C relocation offset - must be at the start
RoundingMode # 1
RoundingMode # 1 ; FPSCR rounding mode field
XFlags # 1 ; Extra flags about the exception
ExceptionFlags # 1
ExceptionEnable # 1
ExceptionFlags # 1 ; FPSCR cumulative exception flags
ExceptionEnable # 1 ; FPSCR trapped exception enable flags
Reg_D # 4 ; Operand and result register numbers (*2 for D regs)
Reg_N # 4
Reg_M # 4
TheInstruction # 4 ; Instruction word being manipulated. Just use context FPINST?
TheFPEXC # 4 ; FPEXC being manipulated. Just use context FPEXC?
TheInstruction # 4 ; Instruction word being manipulated
TheFPEXC # 4 ; FPEXC being manipulated
TheContext # 4 ; Pointer to context being manipulated
Workspace # 4 ; Module workspace pointer
UserRegisters # 64 ; R0-R15 for the caller's mode (assuming not FIQ)
......
......@@ -456,14 +456,44 @@ VCVT_S32_FP_$prec TRACE
StoreReg_S ,,xa,ip
B AdvanceToNext_Scalar
; These are VFPv3 instructions
VMOV_imm_$prec TRACE
; Get dest register number
BL GetOneReg_$prec
; Decode the floating point constant
; Encoded as:
; ---- ---- ---- abcd ---- ---- ---- efgh
; Single precision:
; aBbb bbbc defg h000 0000 0000 0000 0000
; Double precision:
; aBbb bbbb bbcd efgh 0000 0000 0000 0000 (0000...)
EOR x2, xins, #&4<<16
AND x0, xins, #&7<<16
AND x1, xins, #&F
ORR x0, x1, x0, LSR #12 ; bcdefgh
MOV x2, x2, LSL #12
MOV x0, x0, LSL #25
AND x2, x2, #&C<<28
[ "$prec" = "D"
MOV x1, x0, ASR #7 ; bbbbbbbbcdefgh00000...
ASSERT xclo != x1
ASSERT xclo != x2
MOV xclo, #0
ORR xchi, x2, x1, LSR #2 ; Prepend aB
|
MOV x0, x0, ASR #4 ; bbbbbcdefgh00000...
ORR xc, x2, x0, LSR #2 ; Prepend aB
]
VMOV_imm_loop_$prec
StoreReg_$prec , D, xc, ip
ADR lr, VMOV_imm_loop_$prec
B AdvanceToNext
; Unimplemented VFPv3 instructions
[ debugx
VCVTB_VCVTT_$prec TRACE
B VFPSupportCode_Undefined
VCVT_FP_FIXED_$prec TRACE
B VFPSupportCode_Undefined
VMOV_imm_$prec TRACE
B VFPSupportCode_Undefined
]
IMPORT float$bits._add
......
......@@ -81,18 +81,16 @@ ActiveContext # 4 ; Context that's actually active
LazyContext # 4 ; Context awaiting lazy activation (==ActiveContext if none)
NumVFPRegs # 1 ; Number of doubleword regs available on this hardware
ARMVersion # 1 ; ARM architecture version from MIDR. <7=ARMv5, 7=ARMv6, &F=ARMv6/ARMv7
VFPVersion # 1 ; VFP subarchitecture field from FPSID
VFPSubarch # 1 ; VFP subarchitecture field from FPSID
CPEnabledFlag # 1 ; 255 if CP access is enabled, 0 if disabled
OldHandler # 4 ; Original undefined instruction handler
UndefinedHandler # 4 ; Undefined instruction handler code
LazyHandler # 8*4 ; Code to call the lazy handler
[ SupportCode
SupportHandler # 7*4 ; Code to call the support code
VFPSupportCodePtr # 4 ; Pointer to arch-specific support code implementation
]
ChangeContext # 4 ; Address of SWI_ChangeContext
CurrentRoutine # 4 ; OldHandler, LazyHandler, or SupportHandler
[ SupportCode
VFPSupportCodePtr # 4 ; Pointer to arch-specific support code implementation
SupportHandler # 12*4 ; Code to call the support code
SupportHandlerPtr # 4 ; SupportHandler if arch needs support code, else OldHandler
CRelocOffset # 4 ; C relocation offset
BadClasses # 4 ; Instruction class flags which indicate it's not a valid VFP instruction
......@@ -105,6 +103,13 @@ ExceptionDump # :INDEX:Context_RegDump+MaxDRegs*8
WSSize * :INDEX: @
; VFPSubarch values
Subarch_VFPv1_IMP * 0 ; VFPv1 arch with implementation defined subarch
Subarch_VFPv2_v1Sub * 1 ; VFPv2 arch with v1 common subarch (ARM1176JZF-S)
Subarch_VFPv3_v2Sub * 2 ; >=VFPv3 arch with v2 common subarch (Cortex-A7)
Subarch_VFPv3_NoSub * 3 ; >=VFPv3 arch with no subarch (Cortex-A8, Cortex-A9)
Subarch_VFPv3_v3Sub * 4 ; >=VFPv3 arch with v3 common subarch (Cortex-A15)
; Undefined instruction handler code - gets copied into workspace
UndefinedHandlerTemplate
......@@ -112,7 +117,8 @@ UndefinedHandlerTemplate
RelocOffset * UndefinedHandlerTemplate-:INDEX:UndefinedHandler
LDR pc, RelocOffset+:INDEX:CurrentRoutine ; Branch to address in CurrentRoutine
SUB lr, lr, #4 ; LazyHandler starts here
; LazyHandler starts here
SUB lr, lr, #4
STMDB r13!,{r0-r1,wp,lr}
ADR wp, RelocOffset ; Get wp
MOV r1, #0
......@@ -125,18 +131,45 @@ UndefinedHandlerTemplateEnd
ASSERT LazyHandler-UndefinedHandler+?LazyHandler = UndefinedHandlerTemplateEnd-UndefinedHandlerTemplate
[ SupportCode
RelocOffsetSup * SupportHandlerTemplate-:INDEX:SupportHandler
SupportHandlerTemplate
Push "r12"
myVMRS ,r12,FPEXC
TST r12, #FPEXC_EX+FPEXC_DEX
ADRNE r12, RelocOffset ; Get wp
LDRNE pc, RelocOffset+:INDEX:VFPSupportCodePtr ; Call the support code
ADRNE r12, RelocOffsetSup ; Get wp
LDRNE pc, RelocOffsetSup+:INDEX:VFPSupportCodePtr ; Call the support code
Pull "r12"
LDR pc, RelocOffset+:INDEX:OldHandler ; Not a VFP exception, pass on to next handler
LDR pc, RelocOffsetSup+:INDEX:OldHandler ; Not a VFP exception, pass on to next handler
SupportHandlerTemplateEnd
ASSERT UndefinedHandlerTemplateEnd = SupportHandlerTemplate
ASSERT SupportHandlerTemplateEnd-SupportHandlerTemplate = ?SupportHandler
ASSERT SupportHandlerTemplateEnd-SupportHandlerTemplate <= ?SupportHandler
RelocOffsetSV * SupportHandlerTemplateSV-:INDEX:SupportHandler
SupportHandlerTemplateSV
; Alternative support handler template for hardware which doesn't
; generate exceptions via EX/DEX, and for which we want to support short
; vectors.
; This means that it's down to us to decide whether any individual
; instruction generates exceptions or not.
; Pattern to match is:
; cccc 1110 ---- ---- ---- 101- ---0 ----
Push "r11,r12"
LDR r11, [r14, #-4] ; N.B. assuming not Thumb mode!
CMP r11, #&F0000000 ; Reject unconditional instructions
LDRHS pc, RelocOffsetSV+:INDEX:OldHandler
AND r12, r11, #&0F000000
AND r11, r11, #&00000E10
TEQ r12, #&0E000000
TEQEQ r11, #&00000A00
ADREQ r12, RelocOffsetSV
LDREQ pc, RelocOffsetSV+:INDEX:VFPSupportCodePtr
Pull "r11,r12"
LDR pc, RelocOffsetSV+:INDEX:OldHandler
SupportHandlerTemplateSVEnd
ASSERT SupportHandlerTemplateSVEnd-SupportHandlerTemplateSV <= ?SupportHandler
]
; Module code
......@@ -285,9 +318,28 @@ GotFPSID
CMP r0, #&7
BLT CheckFPSIDv5
BEQ CheckFPSIDv6
; v7 version. Must be VFPv3 or above to be valid, but we currently don't allow anything other than vanilla VFPv3 with null subarchitecture due to lack of appropriate support code
; v7 version. There are a few different subarchitectures which we support.
AND r3, r4, #&7F0000
CMP r3, #&30000
CMP r3, #Subarch_VFPv3_v2Sub<<16
CMPNE r3, #Subarch_VFPv3_NoSub<<16
CMPNE r3, #Subarch_VFPv3_v3Sub<<16
BNE BadVFP
; Note that for v2 & v3 subarch we currently have no support for
; asynchronous exceptions (no hardware to test with). Probe to see if
; FPEXC.EX is implemented so that we can discard any such hardware.
;
; Also note that current v2/v3 implementations only throw exceptions for
; attempts to use VFP short vectors (which are no longer supported in
; hardware). This means we don't need to switch support for them based
; around SupportCode - so on these machines SupportCode becomes a
; switch for whether we want to provide software emulation of vectors
; or not.
MOV r7, #FPEXC_EX
myVMSR ,FPEXC,r7
myVMRS ,r7,FPEXC
TST r7, #FPEXC_EX
MOVNE r7, #0
myVMSR NE,FPEXC,r7
BNE BadVFP
B GoodVFP
......@@ -295,9 +347,9 @@ CheckFPSIDv5
CheckFPSIDv6
; v5/v6 version. Should be VFPv1 or VFPv2.
[ SupportCode
; We only have fully support code for VFPv2 with subarchitecture v1
; We only have full support code for VFPv2 with subarchitecture v1
AND r3, r4, #&F0000
CMP r3, #&10000
CMP r3, #Subarch_VFPv2_v1Sub<<16
BNE BadVFP
; Currently only support implementations that use FSTMX/FLDMX standard format 1 (i.e. we can just use VLDM/VSTM)
TST r4, #3:SHL:21
......@@ -334,7 +386,7 @@ GoodVFP
; r3 = FPSID subarchitecture field
; r4 = FPSID
; Read MVFR0/1 if they're available
CMP r3, #&2<<16
CMP r3, #Subarch_VFPv2_v1Sub<<16
BGE HasMVFR ; Subarchitecture 2+ is required to have them
; In subarchitecture 1 and below, the registers are optional.
; E.g. VFP9-S doesn't have them but VFP11 does, even though they're both subarchitecture 1/VFPv2.
......@@ -360,7 +412,7 @@ HasMVFR
; Store our results
; TODO - Calculate fake MVFR0/MVFR1 values where necessary
MOV r3, r3, LSR #16
STRB r3, VFPVersion
STRB r3, VFPSubarch
STR r4, SoftFPSID
STR r5, SoftMVFR0
STR r6, SoftMVFR1
......@@ -378,9 +430,9 @@ HasMVFR
MOV r0, #CLASS_NOT_VFP
CMP r3, #32
ORRLT r0, r0, #CLASS_D32
LDRB r3, VFPVersion
CMP r3, #2
ORRLE r0, r0, #CLASS_VFP3
LDRB r3, VFPSubarch
CMP r3, #Subarch_VFPv3_v2Sub
ORRLT r0, r0, #CLASS_VFP3
TST r5, #&F0
ORREQ r0, r0, #CLASS_S
TST r5, #&F00
......@@ -399,38 +451,78 @@ HasMVFR
MSR CPSR_c, R1
Pull "pc"
InstallHandler
InstallHandler ROUT
Entry
; Copy the handler code over
; Initialise UndefinedHandler + LazyHandler + ChangeContext
ADR r0, UndefinedHandlerTemplate
ADR r1, UndefinedHandler
ASSERT UndefinedHandlerTemplateEnd-UndefinedHandlerTemplate = 9*4
[ SupportCode
MOV r2, r1
LDMIA r0!, {r3-r11}
STMIA r2!, {r3-r11}
ASSERT SupportHandlerTemplate = UndefinedHandlerTemplateEnd
ASSERT ?SupportHandler = 7*4
LDMIA r0, {r3-r9}
ASSERT VFPSupportCodePtr = SupportHandler+?SupportHandler
ASSERT ChangeContext = VFPSupportCodePtr+4
; Use correct support code depending on subarchitecture
; Note - sub architecture V2 support is incomplete (no handling of VV,
; TFV bits)
LDRB r10, VFPVersion
CMP r10, #1
ADREQL r10, VFPSupportCode_SubArchV1
ADRNEL r10, VFPSupportCode_SubArchV2
ADR r11, SWI_ChangeContext
STMIA r2!, {r3-r11}
|
LDMIA r0, {r2-r10}
LDMIA r0!, {r2-r10}
ASSERT ChangeContext = UndefinedHandler+(UndefinedHandlerTemplateEnd-UndefinedHandlerTemplate)
ADR r11, SWI_ChangeContext
STMIA r1, {r2-r11}
ADD r2, r1, #UndefinedHandlerTemplateEnd-UndefinedHandlerTemplate
ADR r2, ChangeContext
[ SupportCode
; Work out what support code (if any) is needed.
; Possible situations are:
; * ARM11/VFP11: Support code required to give the hardware help with difficult instructions. Indicated by Subarch_VFPv2_v1Sub.
; * Cortex-A8: Support code not required. Indicated by Subarch_VFPv3_NoSub & no response to FPEXC EX & DEX bits
; * Cortex-A9: Support code required for short vector support. Indicated by Subarch_VFPv3_NoSub, no response to FPEXC EX, but response to DEX (+ MVFR0 indicates no short vector support)
; * Cortex-A7: Support code required for short vector support. Indicated by Subarch_VFPv3_v2Sub, no response to FPEXC EX, but response to DEX (+ MVFR0 indicates no short vector support)
; * Cortex-A15: Support code required for short vector support. Also requires special abort handler due to lack of DEX. Indicated by Subarch_VFPv3_v3Sub, no response to FPEXC EX & DEX bits (+ MVRF0 indicates no short vector support)
; So logic to follow is:
; * If EX or DEX supported, pick based around SubArch version
; * If MVFR0 indicates no short vector support, use special abort handler
; When testing for support, avoid setting both EX and DEX at once, as that's an invalid combination
MOV r10, #0 ; r10 is used as our 'support handler installed' flag
MOV r11, #FPEXC_EX
myVMSR ,FPEXC,r11
myVMRS ,r11,FPEXC
TST r11, #FPEXC_EX
BNE %FT20
MOV r11, #FPEXC_DEX
myVMSR ,FPEXC,r11
myVMRS ,r11,FPEXC
TST r11, #FPEXC_DEX
BNE %FT20
; No exceptions generated by hardware. But do we need short vector support?
LDR r11, SoftMVFR0
TST r11, #&F<<24
BNE %FT80 ; (no support code needed at all)
; Short vector support required
ADRL r10, VFPSupportCode_SV
ADR r0, SupportHandlerTemplateSV
B %FT50
20
; Hardware generates exceptions via EX/DEX. Use subarchitecture to decide which support code is required.
LDRB r11, VFPSubarch
myVMSR ,FPEXC,r10 ; Reset clobbered reg
CMP r11, #Subarch_VFPv2_v1Sub
ADREQL r10, VFPSupportCode_SubArchV1
CMP r11, #Subarch_VFPv3_v2Sub
CMPNE r11, #Subarch_VFPv3_NoSub
CMPNE r11, #Subarch_VFPv3_v3Sub
ADREQL r10, VFPSupportCode_SubArchV2
; If we've failed to find the right support code then something is wrong
TEQ r10, #0
ADREQL r0, ErrorBlock_VFPSupport_BadHW
BEQ ReturnError_Stacked
ADR r0, SupportHandlerTemplate
50
; Initialise VFPSupportCodePtr & SupportHandler using r10 & r0
STR r10, VFPSupportCodePtr
ADR r2, SupportHandler
; Copy all 12 words even if actual handler is shorter
ASSERT ?SupportHandler = 12*4
LDMIA r0!, {r3-r8}
STMIA r2!, {r3-r8}
LDMIA r0!, {r3-r8}
STMIA r2!, {r3-r8}
; Assume ranged IMB from r1 to r2 will cover both handlers
ASSERT SupportHandler > LazyHandler
80
]
ORR r0, r0, #1
MOV r0, #1
SWI XOS_SynchroniseCodeAreas
; Install the handler. Interrupts disabled to ensure we don't get caught before we set up CurrentRoutine.
MRS r4, CPSR
......@@ -444,8 +536,7 @@ InstallHandler
; Set up SupportHandlerPtr as appropriate
; Either a pointer to SupportHandler (if support code required) or
; OldHandler (no support code required)
LDRB r1, VFPVersion
CMP r1, #3
CMP r10, #0
LDREQ r1, OldHandler
ADRNE r1, SupportHandler
STR r1, SupportHandlerPtr
......@@ -812,19 +903,16 @@ SWI_FastAPI
ADR r2, SWI_CreateContext
ADR r3, SWI_DestroyContext
ADR r4, SWI_ChangeContext
CLRV
MOV pc, lr
SWI_ActiveContext
; out: R0 = currently active context ID (or ID of context pending lazy activation)
LDR r0, LazyContext
CLRV
MOV pc, lr
SWI_Version
; out: R0 = Module version number * 100
MOV r0, #Module_Version
CLRV
MOV pc, lr
SWI_Features
......@@ -835,6 +923,7 @@ SWI_Features
FeaturesJumpTable
B Feature_SystemRegs
B Feature_VFPExceptions
B Feature_Misc
EndOfFeaturesJumpTable
UnknownFeature
......@@ -850,7 +939,6 @@ Feature_SystemRegs
ASSERT SoftMVFR1=SoftMVFR0+4
ADR r0, SoftFPSID
LDMIA r0, {r0-r2}
CLRV
MOV pc, lr
Feature_VFPExceptions
......@@ -859,12 +947,34 @@ Feature_VFPExceptions
[ SupportCode
LDR r0, SupportHandlerPtr
LDR r10, OldHandler
EORS r0, r0, r10
MOVNE r0, #FPSCR_ENABLE_FLAGS ; Support code installed, all exceptions available
EORS r0, r0, r10 ; Is support code installed? (n.b. check should be redundant if we've correctly identified hardware on startup)
LDRNE r0, SoftMVFR0
ANDNES r0, r0, #&F000 ; Does hardware throw trapped exceptions to support code?
MOVNE r0, #FPSCR_ENABLE_FLAGS ; All exceptions available
|
MOV r0, #0
]
CLRV
MOV pc, lr
Feature_Misc ROUT
; in: R0 = 2
; out: R0 = misc flags:
; bit 0: VFP short vectors supported by hardware
; bit 1: VFP short vectors supported by software (slow!)
LDR r0, SoftMVFR0
ANDS r0, r0, #&F<<24
MOVNE r0, #VFPSupport_MiscFeature_VFPVectors_HW
[ SupportCode
BNE %FT10
; Our support code implementation is able to provide full emulation of
; vector mode
LDR r0, SupportHandlerPtr
LDR r10, OldHandler
EORS r0, r0, r10
MOVNE r0, #VFPSupport_MiscFeature_VFPVectors_SW
10
]
; Insert new flags here
MOV pc, lr
SWI_ExceptionDump
......
......@@ -26,9 +26,9 @@
; POSSIBILITY OF SUCH DAMAGE.
;
; VFPv2 support code
; VFP support code
;
; This is a software implementation of a subset of the VFPv2 instruction set,
; This is a software implementation of a subset of the VFPv3 instruction set,
; in order to allow floating point exceptions to be generated, and to help
; the hardware deal with some situations it can't cope with itself
......@@ -68,6 +68,11 @@ xregs RN r9 ; VFP register dump ptr
xwp RN r10 ; Exception workspace ptr - must be SL for access by C
xctx RN r11 ; VFP context (TheContext)
; Extra FP work register which aliases x0 & x1
xc RN r4
xclo RN r4
xchi RN r5
; Debugging macro to print out the label name each time it's passed
MACRO
$label TRACE
......@@ -88,7 +93,10 @@ M_little * 5 ; Bit 5
; entered with:
;
; (a) the VFP coprocessor enabled (or believed to be enabled)
; (b) FPSCR.EX set (VFPv2 exception occurred)
; (b)
; (i) FPSCR.EX or FPSCR.DEX set (standard SupportHandler)
; or
; (ii) we might need to emulate a short vector operation (SupportHandlerSV)
;
; Entry:
; UND mode, IRQs disabled
......@@ -152,7 +160,7 @@ M_little * 5 ; Bit 5
STR r4, [xwp, #XCRelocOffset]
LDR x0, [xctx, #Context_FPSCR]
AND x1, x0, #FPSCR_RMODE_MASK
AND x2, x0, #FPSCR_ENABLE_FLAGS
AND x2, x0, #FPSCR_ENABLE_FLAGS ; n.b. always zero if trapped exceptions not supported by HW
MOV x1, x1, LSR #FPSCR_RMODE_SHIFT ; x1 = RoundingMode
ASSERT XFlags = RoundingMode+1
[ (MaxDRegs > 16) :LAND: CheckD16
......@@ -212,22 +220,26 @@ VFPSupportCode_SubArchV1 ROUT
BEQ VFPSupportCode_NextInstruction
; IXE in effect
Debug x, "Is IXE synchronous exception"
VFPSupportCode_Synchronous
LDR r0, [xwp, #UserRegisters+15*4]
LDR xins, [r0, #-4]
ORR xflags, xflags, #XFlag_Synchronous
STRB xflags, [xwp, #XFlags] ; Set XFlags appropriately
Debug x, "Is IXE synchronous exception"
;
; Check that this really is a VFP CDP instruction we're looking at. Even
; though this is a synchronous exception, there are a number of
; situations in which the hardware can get it wrong and trigger an
; exception for an instruction which is meant to be handled by someone
; else. It's also possible for exceptions to be triggered for VFP
; instructions which shouldn't be capable of generating exceptions
; (VSTMIA), and for invalid VFP instructions (e.g. requiring VFP3, D32,
; etc.). If we handle one of these cases incorrectly we might get stuck
; in an abort loop where the same instructions bounces to the support
; code again and again. See test3 and test6 for plenty of examples.
; situations in which the (ARM11/VFP11) hardware can get it wrong and
; trigger an exception for an instruction which is meant to be handled
; by someone else. It's also possible for exceptions to be triggered
; for VFP instructions which shouldn't be capable of generating
; exceptions (VSTMIA), and for invalid VFP instructions (e.g. requiring
; VFP3, D32, etc.). If we handle one of these cases incorrectly we
; might get stuck in an abort loop where the same instructions bounces
; to the support code again and again. See test3 and test6 for plenty
; of examples.
;
; This means that our processing flow for inexact exceptions needs to
; be as follows:
......@@ -268,9 +280,14 @@ VFPSupportCode_SubArchV1 ROUT
STRB xflags, [xwp, #XFlags]
B VFPSupportCode_Done
VFPSupportCode_SV ROUT
; Support code for when we just want to emulate short vectors
Pull "r11" ; Pop r11 for compatibility with standard prologue
; Fall through...
VFPSupportCode_SubArchV2 ROUT
VFPSupportCodePrologue
[ {FALSE}
; TODO - Deal with synchronous exceptions for SubArchV2
; Examine the instruction in FPINST
......@@ -291,6 +308,12 @@ VFPSupportCode_SubArchV2 ROUT
; skip checking it here in order to simplify things when dealing with
; synchronous exceptions
LDR xins, [xctx, #Context_FPINST]
|
; Partial SubArchV2/V3 implementation for Cortex-A7, A9, A15
; All we need to do is branch to our synchronous exception handling code
B VFPSupportCode_Synchronous
]
VFPSupportCode_NextInstruction
Debug x, "Processing instruction", xins
STR xins, [xwp, #TheInstruction]
......@@ -645,7 +668,7 @@ showvfpregs DCB "*ShowVFPRegs c", 0
; In: xins = instruction word
; xwp = exception workspace
; xflags = XFlags
; Out: DNM or DM registers fill in
; Out: DNM, DM or D registers fill in
; r0-r2 corrupt
GetThreeRegs_S
GetRegNo_S N,r1
......@@ -659,6 +682,23 @@ GetTwoRegs_S
Debug x, "Sd, Sm =", r0, r2
MOV pc, lr
GetOneReg_S
GetRegNo_S D,r0
; Zero Reg_M to prevent AdvanceToNext doing too much excess work
MOV r1, #0
STR r0, [xwp, #Reg_D]
STR r1, [xwp, #Reg_M]
Debug x, "Sd =", r0
MOV pc, lr
GetOneReg_D
GetRegNo_D D,r0
MOV r1, #0
STR r0, [xwp, #Reg_D]