powermac-rom/NanoKernel/NKExceptions.s
2018-07-24 19:43:17 +08:00

476 lines
12 KiB
ArmAsm

; AUTO-GENERATED SYMBOL LIST
########################################################################
ExceptionAfterRetry
mtsprg 3, r24
lwz r9, KDP.Enables(r1)
rlwinm r23, r17, (32-1), 27, 31
rlwnm. r9, r9, r8, 0, 0 ; BGE taken if exception disabled
bcl BO_IF, bitFlag15, major_0x02980_0x100
lwz r6, KDP.CurCBPtr(r1)
_bset r7, r16, 27
neg r23, r23
mtcrf 0x3f, r7
add r19, r19, r23
insrwi r7, r8, 8, 0 ; ec code -> high byte of flags
slwi r8, r8, 2 ; increment counter
add r8, r8, r1
lwz r9, KDP.NKInfo.ExceptionCauseCounts(r8)
addi r9, r9, 1
stw r9, KDP.NKInfo.ExceptionCauseCounts(r8)
; Move regs from KDP to ContextBlock
lwz r8, KDP.r7(r1)
stw r8, CB.r7(r6)
lwz r8, KDP.r8(r1)
stw r8, CB.r8(r6)
lwz r8, KDP.r9(r1)
stw r8, CB.r9(r6)
lwz r8, KDP.r10(r1)
stw r8, CB.r10(r6)
lwz r8, KDP.r11(r1)
stw r8, CB.r11(r6)
lwz r8, KDP.r12(r1)
stw r8, CB.r12(r6)
lwz r8, KDP.r13(r1)
stw r8, CB.r13(r6)
bge RunSystemContext ; Alt Context has left exception disabled => Sys Context
;fall through ; exception enabled => run userspace handler
########################################################################
RunExceptionHandler
stw r10, CB.ExceptionOriginAddr(r6) ; Save r10/SRR0, r12/LR, r3, r4
stw r12, CB.ExceptionOriginLR(r6)
stw r3, CB.ExceptionOriginR3(r6)
stw r4, CB.ExceptionOriginR4(r6)
lwz r8, KDP.Enables(r1) ; Save Enables & Flags
stw r7, CB.ExceptionOriginFlags(r6)
stw r8, CB.ExceptionOriginEnables(r6)
; Set up the Exception Handler context
li r8, 0 ; r8/Enables = 0 (handler must not throw exception)
lwz r10, CB.ExceptionHandler(r6) ; r10/SRR0 = handler addr
lwz r4, CB.ExceptionHandlerR4(r6) ; r4 = arbitrary second argument
lwz r3, KDP.ECBPtrLogical(r1) ; r3 = ContextBlock ptr
bc BO_IF, bitFlagEmu, @sys
lwz r3, KDP.NCBCacheLA0(r1)
@sys
lwz r12, KDP.EmuKCallTblPtrLogical(r1) ; r12/LR = address of KCallReturnFromException trap
bcl BO_IF, bitFlagLowSaves, PreferRegistersFromKDPSavingContextBlock ; ???
rlwinm r7, r7, 0, 29, 15 ; unset flags 16-28
stw r8, KDP.Enables(r1)
rlwimi r11, r7, 0, 20, 23 ; threfore unset MSR[FE0/SE/BE/FE1]
b IntReturn
########################################################################
major_0x02980_0x100
lwz r0, KDP.r0(r1)
lwz r2, KDP.r2(r1)
lwz r3, KDP.r3(r1)
lwz r4, KDP.r4(r1)
lwz r5, KDP.r5(r1)
blr
PreferRegistersFromKDPSavingContextBlock
stw r17, CB.PropagateR17(r6)
stw r20, CB.PropagateR20(r6)
stw r21, CB.PropagateR21(r6)
stw r19, CB.PropagateR19(r6)
stw r18, CB.PropagateR18(r6)
lmw r14, KDP.r14(r1)
blr
########################################################################
_alignToCacheBlock
KCallReturnFromExceptionFastPath
lwz r11, KDP.NKInfo.NanoKernelCallCounts(r1)
mr r10, r12
addi r11, r11, 1
stw r11, KDP.NKInfo.NanoKernelCallCounts(r1)
mfsrr1 r11
rlwimi r7, r7, 27, 26, 26 ; ?re-enable single stepping
KCallReturnFromException
cmplwi cr1, r3, 1 ; exception handler return value
blt cr1, @dispose
mtcrf 0x3f, r7
beq cr1, @propagate
;force to system context ; Handler returned >= 1
subi r8, r3, 32
lwz r9, KDP.NKInfo.ExceptionForcedCount(r1)
cmplwi r8, 256-32
addi r9, r9, 1
stw r9, KDP.NKInfo.ExceptionForcedCount(r1)
insrwi r7, r3, 8, 0
blt RunSystemContext ; Handler returned 1-255: force that exception number to System
li r8, ecTrapInstr
b Exception ; Handler returned >= 256: fail!
@dispose ; Handler returned 0: return to the code that threw the exception
lwz r8, CB.ExceptionOriginFlags(r6)
lwz r10, CB.ExceptionOriginAddr(r6)
rlwimi r7, r8, 0, 0xFF00FFFF ; restore most Flags to pre-exception state
lwz r8, CB.ExceptionOriginEnables(r6)
rlwimi r11, r7, 0, 20, 23 ; MSR[FE0/SE/BE/FE1] <- Flags
stw r8, KDP.Enables(r1)
andi. r8, r11, MsrFE0 + MsrFE1 ; check: are floating-pt exceptions enabled?
lwz r12, CB.ExceptionOriginLR(r6) ; restore LR/r3/r4
lwz r3, CB.ExceptionOriginR3(r6)
lwz r4, CB.ExceptionOriginR4(r6)
bnel EnableFPU ; if FP exceptions are enabled, make sure the FPU is enabled
addi r9, r6, CB.ExceptionOriginFlags ; never gets used... points to exception part of ContextBlock?
b IntReturn
@propagate ; Handler returned 1: propagate exception
lwz r9, KDP.NKInfo.ExceptionPropagateCount(r1)
lwz r8, CB.ExceptionOriginFlags(r6)
addi r9, r9, 1
stw r9, KDP.NKInfo.ExceptionPropagateCount(r1)
lwz r10, CB.ExceptionOriginAddr(r6)
rlwimi r7, r8, 0, 0xFF00FFFF ; restore most Flags to pre-exception state
lwz r8, CB.ExceptionOriginEnables(r6)
mtcrf 0x0f, r7
rlwimi r11, r7, 0, 20, 23 ; MSR[FE0/SE/BE/FE1] <- Flags
stw r8, KDP.Enables(r1)
lwz r12, CB.ExceptionOriginLR(r6) ; restore LR/r3/r4
lwz r3, CB.ExceptionOriginR3(r6)
lwz r4, CB.ExceptionOriginR4(r6)
bc BO_IF_NOT, bitFlagLowSaves, RunSystemContext
stmw r14, KDP.r14(r1)
lwz r17, CB.PropagateR17(r6)
lwz r20, CB.PropagateR20(r6)
lwz r21, CB.PropagateR21(r6)
lwz r19, CB.PropagateR19(r6)
lwz r18, CB.PropagateR18(r6)
b RunSystemContext
########################################################################
; BEFORE
; PowerPC exception vector saved r1/LR in SPRG1/2 and
; jumped where directed by the VecTbl pointed to by
; SPRG3. That function bl'ed here.
;
; AFTER
; Reg Contains Original saved in
; ---------------------------------------------
; r0 (itself)
; r1 KDP SPRG1
; r2 (itself)
; r3 (itself)
; r4 (itself)
; r5 (itself)
; r6 ContextBlock EWA
; r7 Flags ContextBlock
; r8 KDP ContextBlock
; r9 (scratch CB ptr) ContextBlock
; r10 SRR0 ContextBlock
; r11 SRR1 ContextBlock
; r12 LR ContextBlock
; r13 CR ContextBlock
LoadInterruptRegisters
mfsprg r1, 0
stw r6, KDP.r6(r1)
mfsprg r6, 1
stw r6, KDP.r1(r1)
lwz r6, KDP.CurCBPtr(r1)
stw r7, CB.r7(r6)
stw r8, CB.r8(r6)
stw r9, CB.r9(r6)
stw r10, CB.r10(r6)
stw r11, CB.r11(r6)
stw r12, CB.r12(r6)
stw r13, CB.r13(r6)
mfsrr0 r10
mfcr r13
lwz r7, KDP.Flags(r1)
mfsprg r12, 2
mfsrr1 r11
blr
########################################################################
Exception
lwz r9, KDP.Enables(r1)
mtcrf 0x3f, r7
rlwnm. r9, r9, r8, 0, 0 ; BLT taken if exception enabled
insrwi r7, r8, 8, 0 ; Exception code to hi byte of Flags
slwi r8, r8, 2 ; Increment counter, easy enough
add r8, r8, r1
lwz r9, KDP.NKInfo.ExceptionCauseCounts(r8)
addi r9, r9, 1
stw r9, KDP.NKInfo.ExceptionCauseCounts(r8)
blt RunExceptionHandler ; exception enabled => run userspace handler
;fall through ; Alt Context has left exception disabled => Sys Context
########################################################################
RunSystemContext
lwz r9, KDP.ECBPtr(r1) ; System ("Emulator") ContextBlock
addi r8, r1, KDP.VecTblSystem ; System VecTbl
mtsprg 3, r8
bcl BO_IF, bitFlagEmu, SystemCrash ; System Context already running!
; Fallthru (new CB in r9, old CB in r6)
########################################################################
SwitchContext ; OldCB *r6, NewCB *r9
; Run the System or Alternate Context
lwz r8, KDP.Enables(r1)
stw r7, CB.Flags(r6)
stw r8, CB.Enables(r6)
bc BO_IF_NOT, bitFlagLowSaves, @not_low_saves
stw r17, CB.LowSave17(r6)
stw r20, CB.LowSave20(r6)
stw r21, CB.LowSave21(r6)
stw r19, CB.LowSave19(r6)
stw r18, CB.LowSave18(r6)
lmw r14, KDP.r14(r1)
@not_low_saves
mfxer r8
stw r13, CB.CR(r6)
stw r8, CB.XER(r6)
stw r12, CB.LR(r6)
mfctr r8
stw r10, CB.SRR0(r6)
stw r8, CB.CTR(r6)
bc BO_IF_NOT, bitFlagHasMQ, @no_mq
lwz r8, CB.MQ(r9)
mfspr r12, mq
mtspr mq, r8
stw r12, CB.MQ(r6)
@no_mq
lwz r8, KDP.r1(r1)
stw r0, CB.r0(r6)
stw r8, 0x010c(r6)
stw r2, 0x0114(r6)
stw r3, 0x011c(r6)
stw r4, 0x0124(r6)
lwz r8, 0x0018(r1)
stw r5, 0x012c(r6)
stw r8, 0x0134(r6)
_band. r8, r11, bitMsrFP
stw r14, 0x0174(r6)
stw r15, 0x017c(r6)
stw r16, 0x0184(r6)
stw r17, 0x018c(r6)
stw r18, 0x0194(r6)
stw r19, 0x019c(r6)
stw r20, 0x01a4(r6)
stw r21, 0x01ac(r6)
stw r22, 0x01b4(r6)
stw r23, 0x01bc(r6)
stw r24, 0x01c4(r6)
stw r25, 0x01cc(r6)
stw r26, 0x01d4(r6)
stw r27, 0x01dc(r6)
stw r28, 0x01e4(r6)
stw r29, 0x01ec(r6)
stw r30, 0x01f4(r6)
stw r31, 0x01fc(r6)
bnel DisableFPU
lwz r8, KDP.OtherContextDEC(r1)
mfdec r31
cmpwi r8, 0
stw r31, KDP.OtherContextDEC(r1)
mtdec r8
blel ResetDEC ; to r8
lwz r8, CB.Flags(r9) ; r8 is the new Flags variable
stw r9, KDP.CurCBPtr(r1)
xoris r7, r7, 1 << (15 - bitFlagEmu) ; flip Emulator flag
rlwimi r11, r8, 0, 20, 23 ; "enact" MSR[FE0/SE/BE/FE1]
mr r6, r9 ; change the magic ContextBlock register
rlwimi r7, r8, 0, 0x0000FFFF ; change bottom half of flags only
andi. r8, r11, MsrFE0 + MsrFE1 ; FP exceptions enabled in new context?
lwz r8, CB.Enables(r6)
lwz r13, CB.CR(r6)
stw r8, KDP.Enables(r1)
lwz r8, CB.XER(r6)
lwz r12, CB.LR(r6)
mtxer r8
lwz r8, CB.CTR(r6)
lwz r10, CB.SRR0(r6)
mtctr r8
bnel ReloadFPU ; FP exceptions enabled, so load FPU
stwcx. r0, 0, r1
lwz r8, CB.r1(r6)
lwz r0, CB.r0(r6)
stw r8, KDP.r1(r1)
lwz r2, 0x0114(r6)
lwz r3, 0x011c(r6)
lwz r4, 0x0124(r6)
lwz r8, 0x0134(r6)
lwz r5, 0x012c(r6)
stw r8, 0x0018(r1)
lwz r14, 0x0174(r6)
lwz r15, 0x017c(r6)
lwz r16, 0x0184(r6)
lwz r17, 0x018c(r6)
lwz r18, 0x0194(r6)
lwz r19, 0x019c(r6)
lwz r20, 0x01a4(r6)
lwz r21, 0x01ac(r6)
lwz r22, 0x01b4(r6)
lwz r23, 0x01bc(r6)
lwz r24, 0x01c4(r6)
lwz r25, 0x01cc(r6)
lwz r26, 0x01d4(r6)
lwz r27, 0x01dc(r6)
lwz r28, 0x01e4(r6)
lwz r29, 0x01ec(r6)
lwz r30, 0x01f4(r6)
lwz r31, 0x01fc(r6)
########################################################################
IntReturn
andi. r8, r7, FlagTrace | FlagLowSaves
bnel @do_trace
stw r7, KDP.Flags(r1) ; Save kernel flags for next interrupt
mtlr r12 ; Restore user SPRs from kernel GPRs
mtsrr0 r10
mtsrr1 r11
mtcr r13
lwz r10, CB.r10(r6) ; Restore user GPRs from ContextBlock
lwz r11, CB.r11(r6)
lwz r12, CB.r12(r6)
lwz r13, CB.r13(r6)
lwz r7, CB.r7(r6)
lwz r8, CB.r8(r6)
lwz r9, CB.r9(r6)
lwz r6, KDP.r6(r1) ; Restore last two registers from EWA
lwz r1, KDP.r1(r1)
rfi ; Return from interrupt
@do_trace
mtcrf 0x3f, r7
bc BO_IF_NOT, bitFlagLowSaves, @no_low_saves
_bclr r7, r7, bitFlagLowSaves ; LowSaves set with flag 31 -> unset and do some emulation
bc BO_IF, bitFlag31, @last_minute_memretry
_bclr r7, r7, bitFlagTrace ; But if flag 31 is unset, disable tracing and go home
b @return
@no_low_saves
bc BO_IF_NOT, bitFlagTrace, @return
_bclr r7, r7, bitFlagTrace ; Trace flag set with no LowSaves -> unset that flag, and do Trace Exception
stw r7, KDP.Flags(r1)
li r8, ecInstTrace
b Exception
@return
blr
@last_minute_memretry
stw r7, KDP.Flags(r1)
stw r0, 0x0000(r1)
stw r2, 0x0008(r1)
stw r3, 0x000c(r1)
stw r4, 0x0010(r1)
stw r5, 0x0014(r1)
lwz r8, 0x013c(r6)
stw r8, 0x001c(r1)
lwz r8, 0x0144(r6)
stw r8, 0x0020(r1)
lwz r8, 0x014c(r6)
stw r8, 0x0024(r1)
lwz r8, 0x0154(r6)
stw r8, 0x0028(r1)
lwz r8, 0x015c(r6)
stw r8, 0x002c(r1)
lwz r8, 0x0164(r6)
stw r8, 0x0030(r1)
lwz r8, 0x016c(r6)
stw r8, 0x0034(r1)
stmw r14, KDP.r14(r1)
lwz r17, CB.LowSave17(r9) ; LowSave means "MemRetry in ContextBlock"
lwz r20, CB.LowSave20(r9)
lwz r21, CB.LowSave21(r9)
lwz r19, CB.LowSave19(r9)
lwz r18, CB.LowSave18(r9)
_bclr r16, r7, bitFlagLowSaves
lwz r25, KDP.MRBase(r1) ; MRUnknown is indexed by the first arg of MROptab?
extrwi. r22, r17, 4, 27 ;
add r19, r19, r22 ; Correct r19 (EA) by adding byteCount from r17
rlwimi r25, r17, 7, 25, 30 ; The top of MRUnknown is... mysterious!
lhz r26, MRUnknown-MRBase(r25) ; leaving this incorrect as a reminder!
insrwi r25, r19, 3, 28 ; Set Memtab alignment modulus
stw r16, KDP.Flags(r1)
rlwimi r26, r26, 8, 8, 15 ; First byte of MRUnknown is for cr3/cr4
insrwi r25, r17, 4, 24 ; byteCount and load/store from second arg of MROptab?
mtcrf 0x10, r26 ; Set CR3
lha r22, MRMemtab-MRBase(r25) ; Jump to MRMemtab...
addi r23, r1, KDP.VecTblMemRetry
add r22, r22, r25
mfsprg r24, 3
mtlr r22
mtsprg 3, r23
mfmsr r14
_bset r15, r14, bitMsrDR
mtmsr r15
rlwimi r25, r26, 2, 22, 29 ; Second byte of MRUnknown is
bnelr
b MRDoSecondary
########################################################################
ResetDEC ; to r8
lis r31, 0x7FFF
mtdec r31
mtdec r8
blr