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 @@ ...@@ -30,9 +30,11 @@
# Use machine type to determine whether support code is needed # Use machine type to determine whether support code is needed
# Can also be overridden on command line by specifying SUPPORTCODE # Can also be overridden on command line by specifying SUPPORTCODE
DEFSUPPORTCODE = FALSE # Assuming we're targeting a machine capable of VFP, Cortex-A8 is currently the
ifneq (,$(findstring ${MACHINE},All All32 ARM11ZF RPi)) # only machine type which doesn't need any support code at all
DEFSUPPORTCODE = TRUE DEFSUPPORTCODE = TRUE
ifneq (,$(findstring ${MACHINE},CortexA8))
DEFSUPPORTCODE = FALSE
endif endif
SUPPORTCODE ?= ${DEFSUPPORTCODE} SUPPORTCODE ?= ${DEFSUPPORTCODE}
......
File added
...@@ -11,13 +11,13 @@ ...@@ -11,13 +11,13 @@
GBLS Module_HelpVersion GBLS Module_HelpVersion
GBLS Module_ComponentName GBLS Module_ComponentName
GBLS Module_ComponentPath GBLS Module_ComponentPath
Module_MajorVersion SETS "0.09" Module_MajorVersion SETS "0.10"
Module_Version SETA 9 Module_Version SETA 10
Module_MinorVersion SETS "" Module_MinorVersion SETS ""
Module_Date SETS "03 Feb 2015" Module_Date SETS "08 Feb 2015"
Module_ApplicationDate SETS "03-Feb-15" Module_ApplicationDate SETS "08-Feb-15"
Module_ComponentName SETS "VFPSupport" Module_ComponentName SETS "VFPSupport"
Module_ComponentPath SETS "mixed/RiscOS/Sources/HWSupport/VFPSupport" Module_ComponentPath SETS "mixed/RiscOS/Sources/HWSupport/VFPSupport"
Module_FullVersion SETS "0.09" Module_FullVersion SETS "0.10"
Module_HelpVersion SETS "0.09 (03 Feb 2015)" Module_HelpVersion SETS "0.10 (08 Feb 2015)"
END END
/* (0.09) /* (0.10)
* *
* This file is automatically maintained by srccommit, do not edit manually. * This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1. * 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_MinorVersion_CMHG
#define Module_Date_CMHG 03 Feb 2015 #define Module_Date_CMHG 08 Feb 2015
#define Module_MajorVersion "0.09" #define Module_MajorVersion "0.10"
#define Module_Version 9 #define Module_Version 10
#define Module_MinorVersion "" #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_ComponentName "VFPSupport"
#define Module_ComponentPath "mixed/RiscOS/Sources/HWSupport/VFPSupport" #define Module_ComponentPath "mixed/RiscOS/Sources/HWSupport/VFPSupport"
#define Module_FullVersion "0.09" #define Module_FullVersion "0.10"
#define Module_HelpVersion "0.09 (03 Feb 2015)" #define Module_HelpVersion "0.10 (08 Feb 2015)"
#define Module_LibraryVersionInfo "0:9" #define Module_LibraryVersionInfo "0:10"
...@@ -85,6 +85,11 @@ VFPSupport_Field_RegDump * 5 ...@@ -85,6 +85,11 @@ VFPSupport_Field_RegDump * 5
VFPSupport_Features_SystemRegs * 0 VFPSupport_Features_SystemRegs * 0
VFPSupport_Features_VFPExceptions * 1 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 ; Flags for ExceptionDump
......
...@@ -34,15 +34,15 @@ OldOpt SETA {OPT} ...@@ -34,15 +34,15 @@ OldOpt SETA {OPT}
; Layout of the exception processing workspace ; Layout of the exception processing workspace
^ 0 ^ 0
XCRelocOffset # 4 ; C relocation offset - must be at the start 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 XFlags # 1 ; Extra flags about the exception
ExceptionFlags # 1 ExceptionFlags # 1 ; FPSCR cumulative exception flags
ExceptionEnable # 1 ExceptionEnable # 1 ; FPSCR trapped exception enable flags
Reg_D # 4 ; Operand and result register numbers (*2 for D regs) Reg_D # 4 ; Operand and result register numbers (*2 for D regs)
Reg_N # 4 Reg_N # 4
Reg_M # 4 Reg_M # 4
TheInstruction # 4 ; Instruction word being manipulated. Just use context FPINST? TheInstruction # 4 ; Instruction word being manipulated
TheFPEXC # 4 ; FPEXC being manipulated. Just use context FPEXC? TheFPEXC # 4 ; FPEXC being manipulated
TheContext # 4 ; Pointer to context being manipulated TheContext # 4 ; Pointer to context being manipulated
Workspace # 4 ; Module workspace pointer Workspace # 4 ; Module workspace pointer
UserRegisters # 64 ; R0-R15 for the caller's mode (assuming not FIQ) UserRegisters # 64 ; R0-R15 for the caller's mode (assuming not FIQ)
......
...@@ -456,14 +456,44 @@ VCVT_S32_FP_$prec TRACE ...@@ -456,14 +456,44 @@ VCVT_S32_FP_$prec TRACE
StoreReg_S ,,xa,ip StoreReg_S ,,xa,ip
B AdvanceToNext_Scalar 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 [ debugx
VCVTB_VCVTT_$prec TRACE VCVTB_VCVTT_$prec TRACE
B VFPSupportCode_Undefined B VFPSupportCode_Undefined
VCVT_FP_FIXED_$prec TRACE VCVT_FP_FIXED_$prec TRACE
B VFPSupportCode_Undefined B VFPSupportCode_Undefined
VMOV_imm_$prec TRACE
B VFPSupportCode_Undefined
] ]
IMPORT float$bits._add IMPORT float$bits._add
......
...@@ -81,18 +81,16 @@ ActiveContext # 4 ; Context that's actually active ...@@ -81,18 +81,16 @@ ActiveContext # 4 ; Context that's actually active
LazyContext # 4 ; Context awaiting lazy activation (==ActiveContext if none) LazyContext # 4 ; Context awaiting lazy activation (==ActiveContext if none)
NumVFPRegs # 1 ; Number of doubleword regs available on this hardware NumVFPRegs # 1 ; Number of doubleword regs available on this hardware
ARMVersion # 1 ; ARM architecture version from MIDR. <7=ARMv5, 7=ARMv6, &F=ARMv6/ARMv7 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 CPEnabledFlag # 1 ; 255 if CP access is enabled, 0 if disabled
OldHandler # 4 ; Original undefined instruction handler OldHandler # 4 ; Original undefined instruction handler
UndefinedHandler # 4 ; Undefined instruction handler code UndefinedHandler # 4 ; Undefined instruction handler code
LazyHandler # 8*4 ; Code to call the lazy handler 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 ChangeContext # 4 ; Address of SWI_ChangeContext
CurrentRoutine # 4 ; OldHandler, LazyHandler, or SupportHandler CurrentRoutine # 4 ; OldHandler, LazyHandler, or SupportHandler
[ SupportCode [ 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 SupportHandlerPtr # 4 ; SupportHandler if arch needs support code, else OldHandler
CRelocOffset # 4 ; C relocation offset CRelocOffset # 4 ; C relocation offset
BadClasses # 4 ; Instruction class flags which indicate it's not a valid VFP instruction BadClasses # 4 ; Instruction class flags which indicate it's not a valid VFP instruction
...@@ -105,6 +103,13 @@ ExceptionDump # :INDEX:Context_RegDump+MaxDRegs*8 ...@@ -105,6 +103,13 @@ ExceptionDump # :INDEX:Context_RegDump+MaxDRegs*8
WSSize * :INDEX: @ 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 ; Undefined instruction handler code - gets copied into workspace
UndefinedHandlerTemplate UndefinedHandlerTemplate
...@@ -112,7 +117,8 @@ UndefinedHandlerTemplate ...@@ -112,7 +117,8 @@ UndefinedHandlerTemplate
RelocOffset * UndefinedHandlerTemplate-:INDEX:UndefinedHandler RelocOffset * UndefinedHandlerTemplate-:INDEX:UndefinedHandler
LDR pc, RelocOffset+:INDEX:CurrentRoutine ; Branch to address in CurrentRoutine 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} STMDB r13!,{r0-r1,wp,lr}
ADR wp, RelocOffset ; Get wp ADR wp, RelocOffset ; Get wp
MOV r1, #0 MOV r1, #0
...@@ -125,18 +131,45 @@ UndefinedHandlerTemplateEnd ...@@ -125,18 +131,45 @@ UndefinedHandlerTemplateEnd
ASSERT LazyHandler-UndefinedHandler+?LazyHandler = UndefinedHandlerTemplateEnd-UndefinedHandlerTemplate ASSERT LazyHandler-UndefinedHandler+?LazyHandler = UndefinedHandlerTemplateEnd-UndefinedHandlerTemplate
[ SupportCode [ SupportCode
RelocOffsetSup * SupportHandlerTemplate-:INDEX:SupportHandler
SupportHandlerTemplate SupportHandlerTemplate
Push "r12" Push "r12"
myVMRS ,r12,FPEXC myVMRS ,r12,FPEXC
TST r12, #FPEXC_EX+FPEXC_DEX TST r12, #FPEXC_EX+FPEXC_DEX
ADRNE r12, RelocOffset ; Get wp ADRNE r12, RelocOffsetSup ; Get wp
LDRNE pc, RelocOffset+:INDEX:VFPSupportCodePtr ; Call the support code LDRNE pc, RelocOffsetSup+:INDEX:VFPSupportCodePtr ; Call the support code
Pull "r12" 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 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 ; Module code
...@@ -285,9 +318,28 @@ GotFPSID ...@@ -285,9 +318,28 @@ GotFPSID
CMP r0, #&7 CMP r0, #&7
BLT CheckFPSIDv5 BLT CheckFPSIDv5
BEQ CheckFPSIDv6 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 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 BNE BadVFP
B GoodVFP B GoodVFP
...@@ -295,9 +347,9 @@ CheckFPSIDv5 ...@@ -295,9 +347,9 @@ CheckFPSIDv5
CheckFPSIDv6 CheckFPSIDv6
; v5/v6 version. Should be VFPv1 or VFPv2. ; v5/v6 version. Should be VFPv1 or VFPv2.
[ SupportCode [ 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 AND r3, r4, #&F0000
CMP r3, #&10000 CMP r3, #Subarch_VFPv2_v1Sub<<16
BNE BadVFP BNE BadVFP
; Currently only support implementations that use FSTMX/FLDMX standard format 1 (i.e. we can just use VLDM/VSTM) ; Currently only support implementations that use FSTMX/FLDMX standard format 1 (i.e. we can just use VLDM/VSTM)
TST r4, #3:SHL:21 TST r4, #3:SHL:21
...@@ -334,7 +386,7 @@ GoodVFP ...@@ -334,7 +386,7 @@ GoodVFP
; r3 = FPSID subarchitecture field ; r3 = FPSID subarchitecture field
; r4 = FPSID ; r4 = FPSID
; Read MVFR0/1 if they're available ; 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 BGE HasMVFR ; Subarchitecture 2+ is required to have them
; In subarchitecture 1 and below, the registers are optional. ; 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. ; E.g. VFP9-S doesn't have them but VFP11 does, even though they're both subarchitecture 1/VFPv2.
...@@ -360,7 +412,7 @@ HasMVFR ...@@ -360,7 +412,7 @@ HasMVFR
; Store our results ; Store our results
; TODO - Calculate fake MVFR0/MVFR1 values where necessary ; TODO - Calculate fake MVFR0/MVFR1 values where necessary
MOV r3, r3, LSR #16 MOV r3, r3, LSR #16
STRB r3, VFPVersion STRB r3, VFPSubarch
STR r4, SoftFPSID STR r4, SoftFPSID
STR r5, SoftMVFR0 STR r5, SoftMVFR0
STR r6, SoftMVFR1 STR r6, SoftMVFR1
...@@ -378,9 +430,9 @@ HasMVFR ...@@ -378,9 +430,9 @@ HasMVFR
MOV r0, #CLASS_NOT_VFP MOV r0, #CLASS_NOT_VFP
CMP r3, #32 CMP r3, #32
ORRLT r0, r0, #CLASS_D32 ORRLT r0, r0, #CLASS_D32
LDRB r3, VFPVersion LDRB r3, VFPSubarch
CMP r3, #2 CMP r3, #Subarch_VFPv3_v2Sub
ORRLE r0, r0, #CLASS_VFP3 ORRLT r0, r0, #CLASS_VFP3
TST r5, #&F0 TST r5, #&F0
ORREQ r0, r0, #CLASS_S ORREQ r0, r0, #CLASS_S
TST r5, #&F00 TST r5, #&F00
...@@ -399,38 +451,78 @@ HasMVFR ...@@ -399,38 +451,78 @@ HasMVFR
MSR CPSR_c, R1 MSR CPSR_c, R1
Pull "pc" Pull "pc"
InstallHandler InstallHandler ROUT
Entry Entry
; Copy the handler code over ; Initialise UndefinedHandler + LazyHandler + ChangeContext
ADR r0, UndefinedHandlerTemplate ADR r0, UndefinedHandlerTemplate
ADR r1, UndefinedHandler ADR r1, UndefinedHandler
ASSERT UndefinedHandlerTemplateEnd-UndefinedHandlerTemplate = 9*4 ASSERT UndefinedHandlerTemplateEnd-UndefinedHandlerTemplate = 9*4
[ SupportCode LDMIA r0!, {r2-r10}
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}
ASSERT ChangeContext = UndefinedHandler+(UndefinedHandlerTemplateEnd-UndefinedHandlerTemplate) ASSERT ChangeContext = UndefinedHandler+(UndefinedHandlerTemplateEnd-UndefinedHandlerTemplate)
ADR r11, SWI_ChangeContext ADR r11, SWI_ChangeContext
STMIA r1, {r2-r11} 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 SWI XOS_SynchroniseCodeAreas
; Install the handler. Interrupts disabled to ensure we don't get caught before we set up CurrentRoutine. ; Install the handler. Interrupts disabled to ensure we don't get caught before we set up CurrentRoutine.
MRS r4, CPSR MRS r4, CPSR
...@@ -444,8 +536,7 @@ InstallHandler ...@@ -444,8 +536,7 @@ InstallHandler
; Set up SupportHandlerPtr as appropriate ; Set up SupportHandlerPtr as appropriate
; Either a pointer to SupportHandler (if support code required) or ; Either a pointer to SupportHandler (if support code required) or
; OldHandler (no support code required) ; OldHandler (no support code required)
LDRB r1, VFPVersion CMP r10, #0
CMP r1, #3
LDREQ r1, OldHandler LDREQ r1, OldHandler
ADRNE r1, SupportHandler ADRNE r1, SupportHandler
STR r1, SupportHandlerPtr STR r1, SupportHandlerPtr
...@@ -812,19 +903,16 @@ SWI_FastAPI ...@@ -812,19 +903,16 @@ SWI_FastAPI
ADR r2, SWI_CreateContext ADR r2, SWI_CreateContext
ADR r3, SWI_DestroyContext ADR r3, SWI_DestroyContext
ADR r4, SWI_ChangeContext ADR r4, SWI_ChangeContext
CLRV
MOV pc, lr MOV pc, lr
SWI_ActiveContext SWI_ActiveContext
; out: R0 = currently active context ID (or ID of context pending lazy activation) ; out: R0 = currently active context ID (or ID of context pending lazy activation)
LDR r0, LazyContext LDR r0, LazyContext
CLRV
MOV pc, lr MOV pc, lr
SWI_Version SWI_Version
; out: R0 = Module version number * 100 ; out: R0 = Module version number * 100
MOV r0, #Module_Version MOV r0, #Module_Version
CLRV
MOV pc, lr MOV pc, lr
SWI_Features SWI_Features
...@@ -835,6 +923,7 @@ SWI_Features ...@@ -835,6 +923,7 @@ SWI_Features
FeaturesJumpTable FeaturesJumpTable
B Feature_SystemRegs B Feature_SystemRegs
B Feature_VFPExceptions B Feature_VFPExceptions
B Feature_Misc
EndOfFeaturesJumpTable EndOfFeaturesJumpTable
UnknownFeature UnknownFeature
...@@ -850,7 +939,6 @@ Feature_SystemRegs ...@@ -850,7 +939,6 @@ Feature_SystemRegs
ASSERT SoftMVFR1=SoftMVFR0+4 ASSERT SoftMVFR1=SoftMVFR0+4
ADR r0, SoftFPSID ADR r0, SoftFPSID
LDMIA r0, {r0-r2} LDMIA r0, {r0-r2}
CLRV
MOV pc, lr MOV pc, lr
Feature_VFPExceptions Feature_VFPExceptions
...@@ -859,12 +947,34 @@ Feature_VFPExceptions ...@@ -859,12 +947,34 @@ Feature_VFPExceptions
[ SupportCode [ SupportCode
LDR r0, SupportHandlerPtr LDR r0, SupportHandlerPtr
LDR r10, OldHandler LDR r10, OldHandler
EORS r0, r0, r10 EORS r0, r0, r10 ; Is support code installed? (n.b. check should be redundant if we've correctly identified hardware on startup)
MOVNE r0, #FPSCR_ENABLE_FLAGS ; Support code installed, all exceptions available 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 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