vap/assembly/ppc32/exception.S

230 lines
No EOL
6.1 KiB
ArmAsm

#include "regnames.h"
.extern _decrementer_exception_fn
#define ISTATE_OFFSET_SP_FRAME 0x00
#define ISTATE_OFFSET_LR_FRAME 0x04
#define ISTATE_OFFSET_R0 0x08
#define ISTATE_OFFSET_R2 0x0c
#define ISTATE_OFFSET_R3 0x10
#define ISTATE_OFFSET_R4 0x14
#define ISTATE_OFFSET_R5 0x18
#define ISTATE_OFFSET_R6 0x1c
#define ISTATE_OFFSET_R7 0x20
#define ISTATE_OFFSET_R8 0x24
#define ISTATE_OFFSET_R9 0x28
#define ISTATE_OFFSET_R10 0x2c
#define ISTATE_OFFSET_R11 0x30
#define ISTATE_OFFSET_R13 0x34
#define ISTATE_OFFSET_R14 0x38
#define ISTATE_OFFSET_R15 0x3c
#define ISTATE_OFFSET_R16 0x40
#define ISTATE_OFFSET_R17 0x44
#define ISTATE_OFFSET_R18 0x48
#define ISTATE_OFFSET_R19 0x4c
#define ISTATE_OFFSET_R20 0x50
#define ISTATE_OFFSET_R21 0x54
#define ISTATE_OFFSET_R22 0x58
#define ISTATE_OFFSET_R23 0x5c
#define ISTATE_OFFSET_R24 0x60
#define ISTATE_OFFSET_R25 0x64
#define ISTATE_OFFSET_R26 0x68
#define ISTATE_OFFSET_R27 0x6c
#define ISTATE_OFFSET_R28 0x70
#define ISTATE_OFFSET_R29 0x74
#define ISTATE_OFFSET_R30 0x78
#define ISTATE_OFFSET_R31 0x7c
#define ISTATE_OFFSET_CR 0x80
#define ISTATE_OFFSET_PC 0x84
#define ISTATE_OFFSET_SRR1 0x88
#define ISTATE_OFFSET_LR 0x8c
#define ISTATE_OFFSET_CTR 0x90
#define ISTATE_OFFSET_XER 0x94
#define ISTATE_OFFSET_DAR 0x98
#define ISTATE_OFFSET_R12 0x9c
#define ISTATE_OFFSET_SP 0xa0
#define ISTATE_SIZE 0xa4
#define ALIGN_UP(s, a) (((s) + ((a) - 1)) & ~((a) - 1))
.section V_TEXT_GENESIS, "ax"
.macro CTX_SAVE
// honestly i'm going insane looking at powerpc assembly documentation
// so a lot of this will be based heavily on helenos's exception.S
// also their code is much nicer to look at than apple's hw_exception.s
// https://github.com/HelenOS/helenos/blob/master/kernel/arch/ppc32/src/exception.S
// i do not claim ownership of this
mtspr 1,r12
mfcr r12
mtspr 2,sp
subi sp, sp, ALIGN_UP(ISTATE_SIZE, 16)
stw r0, ISTATE_OFFSET_R0(sp)
stw r2, ISTATE_OFFSET_R2(sp)
stw r3, ISTATE_OFFSET_R3(sp)
stw r4, ISTATE_OFFSET_R4(sp)
stw r5, ISTATE_OFFSET_R5(sp)
stw r6, ISTATE_OFFSET_R6(sp)
stw r7, ISTATE_OFFSET_R7(sp)
stw r8, ISTATE_OFFSET_R8(sp)
stw r9, ISTATE_OFFSET_R9(sp)
stw r10, ISTATE_OFFSET_R10(sp)
stw r11, ISTATE_OFFSET_R11(sp)
stw r13, ISTATE_OFFSET_R13(sp)
stw r14, ISTATE_OFFSET_R14(sp)
stw r15, ISTATE_OFFSET_R15(sp)
stw r16, ISTATE_OFFSET_R16(sp)
stw r17, ISTATE_OFFSET_R17(sp)
stw r18, ISTATE_OFFSET_R18(sp)
stw r19, ISTATE_OFFSET_R19(sp)
stw r20, ISTATE_OFFSET_R20(sp)
stw r21, ISTATE_OFFSET_R21(sp)
stw r22, ISTATE_OFFSET_R22(sp)
stw r23, ISTATE_OFFSET_R23(sp)
stw r24, ISTATE_OFFSET_R24(sp)
stw r25, ISTATE_OFFSET_R25(sp)
stw r26, ISTATE_OFFSET_R26(sp)
stw r27, ISTATE_OFFSET_R27(sp)
stw r28, ISTATE_OFFSET_R28(sp)
stw r29, ISTATE_OFFSET_R29(sp)
stw r30, ISTATE_OFFSET_R30(sp)
stw r31, ISTATE_OFFSET_R31(sp)
stw r12, ISTATE_OFFSET_CR(sp)
mfsrr0 r12
stw r12, ISTATE_OFFSET_PC(sp)
mfsrr1 r12
stw r12, ISTATE_OFFSET_SRR1(sp)
mflr r12
stw r12, ISTATE_OFFSET_LR(sp)
mfctr r12
stw r12, ISTATE_OFFSET_CTR(sp)
mfxer r12
stw r12, ISTATE_OFFSET_XER(sp)
mfdar r12
stw r12, ISTATE_OFFSET_DAR(sp)
mfsprg1 r12
stw r12, ISTATE_OFFSET_R12(sp)
mfsprg2 r12
stw r12, ISTATE_OFFSET_SP(sp)
li r12, 0
stw r12, ISTATE_OFFSET_LR_FRAME(sp)
stw r12, ISTATE_OFFSET_SP_FRAME(sp)
.endm
// assumes that the stack pointer is already set to the correct value (it should be saved after using CTX_SAVE, and restored before using CTX_LOAD)
.macro CTX_LOAD
lwz r0, ISTATE_OFFSET_R0(sp)
lwz r2, ISTATE_OFFSET_R2(sp)
lwz r3, ISTATE_OFFSET_R3(sp)
lwz r4, ISTATE_OFFSET_R4(sp)
lwz r5, ISTATE_OFFSET_R5(sp)
lwz r6, ISTATE_OFFSET_R6(sp)
lwz r7, ISTATE_OFFSET_R7(sp)
lwz r8, ISTATE_OFFSET_R8(sp)
lwz r9, ISTATE_OFFSET_R9(sp)
lwz r10, ISTATE_OFFSET_R10(sp)
lwz r11, ISTATE_OFFSET_R11(sp)
lwz r13, ISTATE_OFFSET_R13(sp)
lwz r14, ISTATE_OFFSET_R14(sp)
lwz r15, ISTATE_OFFSET_R15(sp)
lwz r16, ISTATE_OFFSET_R16(sp)
lwz r17, ISTATE_OFFSET_R17(sp)
lwz r18, ISTATE_OFFSET_R18(sp)
lwz r19, ISTATE_OFFSET_R19(sp)
lwz r20, ISTATE_OFFSET_R20(sp)
lwz r21, ISTATE_OFFSET_R21(sp)
lwz r22, ISTATE_OFFSET_R22(sp)
lwz r23, ISTATE_OFFSET_R23(sp)
lwz r24, ISTATE_OFFSET_R24(sp)
lwz r25, ISTATE_OFFSET_R25(sp)
lwz r26, ISTATE_OFFSET_R26(sp)
lwz r27, ISTATE_OFFSET_R27(sp)
lwz r28, ISTATE_OFFSET_R28(sp)
lwz r29, ISTATE_OFFSET_R29(sp)
lwz r30, ISTATE_OFFSET_R30(sp)
lwz r31, ISTATE_OFFSET_R31(sp)
lwz r12, ISTATE_OFFSET_CR(sp)
li r12, 0
lwz r12, ISTATE_OFFSET_LR_FRAME(sp) // do we need to do this?
lwz r12, ISTATE_OFFSET_SP_FRAME(sp)
lwz r12, ISTATE_OFFSET_SP(sp)
mtsprg 2,r12
lwz r12, ISTATE_OFFSET_R12(sp)
mtsprg 1,r12
lwz r12, ISTATE_OFFSET_DAR(sp)
mtdar r12
lwz r12, ISTATE_OFFSET_XER(sp)
mtxer r12
lwz r12, ISTATE_OFFSET_CTR(sp)
mtctr r12
lwz r12, ISTATE_OFFSET_LR(sp)
mtlr r12
lwz r12, ISTATE_OFFSET_SRR1(sp)
mtsrr1 r12
lwz r12, ISTATE_OFFSET_PC(sp)
mtsrr0 r12
mfspr 2,sp
mtcr r12
mfspr 1,r12
.endm
#define ABSOLUTE(x) ((x) - 0x100)
// _decrementer_exception_wrapper
// called when the decrementer exception occurs (i.e. when it reaches 0)
.org ABSOLUTE(0x900)
.global _decrementer_exception_wrapper
_decrementer_exception_wrapper:
rfi
CTX_SAVE
// save the current stack pointer
mtspr 2,sp
// move the stack pointer to our stack (0x8000)
addis sp, sp, 0x8000@h
// load the address of the decrementer exception handler
lis r12, _decrementer_exception_fn@h
addi r12, r12, _decrementer_exception_fn@l
// call the decrementer exception handler
mtctr r12
bctrl
// restore the stack pointer
mfspr 2,sp
// restore the context
CTX_LOAD
// return
rfi
.org ABSOLUTE(0x8000)