📄 tlundef.s
字号:
SUB R2,R2,#0xC0000000
CMP R2,#0x30000000
BHS Unknown_ARM_Handler ; R14 -> ReturnFromHandler
CpInstructionBounce
; Jump to the correct handler via coprocessor handler address table.
; R0 already holds the instruction parameter, and R1 points to the
; register dump. The call will preserve the values in R4-R7.
ADR R2,TLUndef_CpTable
AND R3,R0,#0x00000F00 ;Isolate CP number
LDR R3,[R2,R3,LSR #8-2] ;Index table by CP no.
ADD R2, R2, R3
BX R2
ThumbStateBounce
; Get the Thumb instruction that bounced. As for ArmStateBounce above.
; Thumb2 means we can have 32-bit instructiond including co-processor
; instructions. Bits 15:11 of hw1 are > 0x1c if instruction is 32 bit.
LDRH R0,[R6,#-2]
if V6_ENDIAN_SWAP
REV16 r0, r0
endif
if ARCH_HAS_THUMB2
MOV R2, R0, LSR #11
CMP R2, #0x1c ; Check for 32-bit instruction
BLE Unknown_Thumb_Handler ; R14 -> ReturnFromHandler
LDRH R2,[R6,#0] ; Load second halfword
if V6_ENDIAN_SWAP
REV16 r2, r2
endif
ORR R0, R2, R0, LSL #16 ; Construct whole instruction in R0
ORR R6, R6, #1 ; Use low bit of return address to
; remember it was a 32 bit instruction
MOV R2,R0,LSL #4
SUB R2,R2,#0xC0000000 ; Same check as above for ARM
CMP R2,#0x30000000 ; co-processor instruction.
BLO CpInstructionBounce
endif
B Unknown_Thumb_Handler ; R14 -> ReturnFromHandler
; The coprocessor handler address table.
IMPORT Unknown_Coproc_Handler
IMPORT VFP_Undef_Handler
TLUndef_CpTable
DCD Unknown_Coproc_Handler - TLUndef_CpTable ; CP 0
DCD Unknown_Coproc_Handler - TLUndef_CpTable ; CP 1
DCD Unknown_Coproc_Handler - TLUndef_CpTable ; CP 2
DCD Unknown_Coproc_Handler - TLUndef_CpTable ; CP 3
DCD Unknown_Coproc_Handler - TLUndef_CpTable ; CP 4
DCD Unknown_Coproc_Handler - TLUndef_CpTable ; CP 5
DCD Unknown_Coproc_Handler - TLUndef_CpTable ; CP 6
DCD Unknown_Coproc_Handler - TLUndef_CpTable ; CP 7
DCD Unknown_Coproc_Handler - TLUndef_CpTable ; CP 8
DCD Unknown_Coproc_Handler - TLUndef_CpTable ; CP 9
DCD VFP_Undef_Handler - TLUndef_CpTable ; CP 10
DCD VFP_Undef_Handler - TLUndef_CpTable ; CP 11
DCD Unknown_Coproc_Handler - TLUndef_CpTable ; CP 12
DCD Unknown_Coproc_Handler - TLUndef_CpTable ; CP 13
DCD Unknown_Coproc_Handler - TLUndef_CpTable ; CP 14
DCD Unknown_Coproc_Handler - TLUndef_CpTable ; CP 15
ReturnFromHandler
; At this point:
; R0 = the value returned by the second-level handler:
; 0 to return to the bounced instruction,
; 1 to return to the following instruction.
; R1 contains NULL, or R1 -> user-level exception control block
; R4 -> final 2 words of register dump (just above banked registers)
; R5 = the Mode_mask bits of SPSR_undef
; R6 = R14_undef value
; R7 = SPSR_undef value
; Correct the return address,
; if R0 indicates we should return to the bounced instruction.
TEQ R0,#0
if ARCH_HAS_THUMB2
ADDNE R6, R6, #1 ; if it was a 32-bit Thumb instruction and 1 was
BICNE R6, R6, #1 ; returned move return address 2 bytes forward
endif
SUBEQ R6,R6,#2 ; back 2 for Thumb
TSTEQ R7, #Thumb_bit
SUBEQ R6,R6,#2 ; back 4 for ARM
; Now start returning to the original program. First prepare the new
; flag values in R7 for SPSR_undef, ready for the return.
LDR R0,[R4,#4]
AND R0,R0,#Flags_mask
BIC R7,R7,#Flags_mask
ORR R7,R7,R0
; Value returned in R1 is 0 for a return to the application
TEQ R1,#0
BEQ StandardReturn
; Return via user-level exception handler
; R1 points to the relevant control buffer,
; with the first entry the target handler code location.
; Replace with the true return address and add the saved CPSR and R14.
LDR R8,[R4,#-4]
LDR R2,[R1]
STMIA R1,{R6,R7,R8}
; Replace the R14 in the register dump with a pointer to the
; control data area.
STR R1,[R4,#-4]
; Prepare R6,R7 for exit to handler code.
; All handlers are entered in ARM state.
MOV R6,R2
BIC R7,R7,#(Java_bit|Flags_mask)
BIC R7,R7,#Thumb_bit
if ARCH_V6_OR_LATER
; All handlers are entered in the same endianness as this handler.
if {ENDIAN} = "big" :LAND: :LNOT: :DEF: ENDIAN_BE_32
ORR R7,R7,#Endian_bit
else
BIC R7,R7,#Endian_bit
endif
endif
; fall through to standard return mechanism
StandardReturn
; Restore R14_svc and SPSR_svc.
; We do this _before_ the register restore code below, in case the Undef
; trap was taken in Supervisor Mode, and the handler has modified R14.
; If R13_svc was saved then this was the current R13 and (so long as
; the handler has not modified it) restoring it should have no effect.
LDR R14,[R4,#-16*4]
MSR SPSR_cxsf,R14
LDR R14,[R4,#-17*4]
; Now restore the banked registers: this is precisely like storing
; them in the first place, except that we already have suitable R4, R5
; and R7 values loaded.
MRS R1,CPSR
TEQ R5,#Mode_Usr32
LDMEQDB R4,{R8-R14}^ ; User mode case
BEQ BankedLoadDone
BIC R2,R1,#Mode_mask
ORR R2,R2,R5 ; Non-user mode case
MSR CPSR_c,R2
LDMDB R4,{R8-R14}
MSR CPSR_c,R1
BankedLoadDone
; We will switch back to Undef mode to return, so that we can use
; R14_und and SPSR_und. R14_svc and SPSR_svc may be live on return,
; and must not be corrupted.
; At this point:
; R1 = the current CPSR
; R4 -> final 2 words of register dump (just above banked registers)
; R6 = the address to return to
; R7 = value prepared for SPSR_undef
; R8-R14 have been restored
LDR R2,[R4,#-15*4] ; saved R0
; Switch to Undef mode.
ORR R0,R1,#8
ASSERT (Mode_Svc :OR: 8) = Mode_Undef
MSR CPSR_c,R0
; Prepare R14_und and SPSR_und for the return.
; Push the saved value of R0 on the Undef stack.
MOV R14,R6
MSR SPSR_csxf,R7
STR R2,[R13,#-4]!
; Switch back to Supervisor mode.
MSR CPSR_c,R1
; Restore R13, pop saved registers R1-R7,
; and kill Supervisor stack space.
SUB R13,R4,#14*4 ; R13 -> R1 in register dump
LDMIA R13!,{R1-R7}
ADD R13,R13,#9*4
; Now R1-R14 have been restored.
; Switch back to Undef mode, pop R0,
; and return by writing to the PC with a SPSR->CPSR transfer.
MSR CPSR_c,R0
LDR R0,[R13],#4
MOVS PC,R14
END ; Of file tlundef.s
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -