311 lines
No EOL
8.3 KiB
ArmAsm
311 lines
No EOL
8.3 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_SRR0 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
|
|
|
|
mtsprg1 r12
|
|
mfcr r12
|
|
mtsprg2 sp
|
|
|
|
// move stack pointer to the exception stack
|
|
lis sp, _exception_stack@ha
|
|
addi sp, sp, _exception_stack@l
|
|
|
|
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_SRR0(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
|
|
|
|
// _decrementer_exception_wrapper
|
|
// called when the decrementer exception occurs (i.e. when it reaches 0)
|
|
.global _decrementer_exception_wrapper
|
|
.extern _test_decrementer
|
|
.extern VAP_KERN_BASE
|
|
_decrementer_exception_wrapper:
|
|
// temporarily save r12
|
|
mtsprg2 r12
|
|
mfmsr r12
|
|
ori r12, r12, ((1 << 5) | (1 << 4)) // enable instruction relocation and data relocation
|
|
mtmsr r12
|
|
mfsprg2 r12
|
|
isync
|
|
|
|
CTX_SAVE
|
|
|
|
lis r12, _decrementer_exception_definition@ha
|
|
addi r12, r12, _decrementer_exception_definition@l
|
|
mtsrr0 r12
|
|
mfmsr r12
|
|
mtsrr1 r12
|
|
|
|
rfi
|
|
|
|
// end of exceptions
|
|
.global VAP_VECTOR_END
|
|
VAP_VECTOR_END:
|
|
|
|
// exception stack
|
|
.global _vap_exception_stack
|
|
.org 0x8000 // grows down
|
|
_exception_stack:
|
|
|
|
.global _decrementer_exception_definition
|
|
_decrementer_exception_definition:
|
|
// disable interrupts, enable instruction relocation and data relocation
|
|
// but this time both here and in srr1
|
|
mfsrr1 r12
|
|
ori r12, r12, ((1 << 5) | (1 << 4)) // enable instruction relocation and data relocation
|
|
andi. r12, r12, ~(1 << 15)@l // disable interrupts
|
|
mtsrr1 r12
|
|
isync
|
|
|
|
// copy sp to r3
|
|
mr r3, sp
|
|
// load the address
|
|
lis r12, scheduler_callback@ha
|
|
addi r12, r12, scheduler_callback@l
|
|
mtsrr0 r12
|
|
|
|
rfi
|
|
|
|
.global _vap_return_from_exception
|
|
_vap_return_from_exception:
|
|
|
|
// disable interrupts
|
|
mfmsr r12
|
|
rlwinm r21, r12, 0, 17, 15
|
|
mtmsr r12
|
|
isync
|
|
|
|
// load r3 into sp
|
|
mr sp, r3
|
|
sync
|
|
isync
|
|
|
|
// restore context
|
|
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)
|
|
mtcr r12
|
|
|
|
lwz r12, ISTATE_OFFSET_SRR0(sp)
|
|
mtsrr0 r12
|
|
|
|
lwz r12, ISTATE_OFFSET_SRR1(sp)
|
|
mtsrr1 r12
|
|
|
|
lwz r12, ISTATE_OFFSET_LR(sp)
|
|
mtlr r12
|
|
|
|
lwz r12, ISTATE_OFFSET_CTR(sp)
|
|
mtctr r12
|
|
|
|
lwz r12, ISTATE_OFFSET_XER(sp)
|
|
mtxer r12
|
|
|
|
lwz r12, ISTATE_OFFSET_R12(sp)
|
|
lwz sp, ISTATE_OFFSET_SP(sp)
|
|
|
|
// return to task
|
|
rfi
|
|
|
|
// helper function to create an istate from the current state
|
|
.global _vap_create_istate
|
|
_vap_create_istate:
|
|
// r3 = pointer to istate (should have enough room allocated)
|
|
|
|
stw r0, ISTATE_OFFSET_R0(r3)
|
|
stw r2, ISTATE_OFFSET_R2(r3)
|
|
stw r3, ISTATE_OFFSET_R3(r3)
|
|
stw r4, ISTATE_OFFSET_R4(r3)
|
|
stw r5, ISTATE_OFFSET_R5(r3)
|
|
stw r6, ISTATE_OFFSET_R6(r3)
|
|
stw r7, ISTATE_OFFSET_R7(r3)
|
|
stw r8, ISTATE_OFFSET_R8(r3)
|
|
stw r9, ISTATE_OFFSET_R9(r3)
|
|
stw r10, ISTATE_OFFSET_R10(r3)
|
|
stw r11, ISTATE_OFFSET_R11(r3)
|
|
stw r13, ISTATE_OFFSET_R13(r3)
|
|
stw r14, ISTATE_OFFSET_R14(r3)
|
|
stw r15, ISTATE_OFFSET_R15(r3)
|
|
stw r16, ISTATE_OFFSET_R16(r3)
|
|
stw r17, ISTATE_OFFSET_R17(r3)
|
|
stw r18, ISTATE_OFFSET_R18(r3)
|
|
stw r19, ISTATE_OFFSET_R19(r3)
|
|
stw r20, ISTATE_OFFSET_R20(r3)
|
|
stw r21, ISTATE_OFFSET_R21(r3)
|
|
stw r22, ISTATE_OFFSET_R22(r3)
|
|
stw r23, ISTATE_OFFSET_R23(r3)
|
|
stw r24, ISTATE_OFFSET_R24(r3)
|
|
stw r25, ISTATE_OFFSET_R25(r3)
|
|
stw r26, ISTATE_OFFSET_R26(r3)
|
|
stw r27, ISTATE_OFFSET_R27(r3)
|
|
stw r28, ISTATE_OFFSET_R28(r3)
|
|
stw r29, ISTATE_OFFSET_R29(r3)
|
|
stw r30, ISTATE_OFFSET_R30(r3)
|
|
stw r31, ISTATE_OFFSET_R31(r3)
|
|
|
|
stw r12, ISTATE_OFFSET_CR(r3)
|
|
|
|
mfsrr0 r12
|
|
stw r12, ISTATE_OFFSET_SRR0(r3)
|
|
|
|
mfmsr r12 // we want msr instead of srr1, so that interrupts will return here with this msr
|
|
stw r12, ISTATE_OFFSET_SRR1(r3)
|
|
|
|
mflr r12
|
|
stw r12, ISTATE_OFFSET_LR(r3)
|
|
|
|
mfctr r12
|
|
stw r12, ISTATE_OFFSET_CTR(r3)
|
|
|
|
mfxer r12
|
|
stw r12, ISTATE_OFFSET_XER(r3)
|
|
|
|
stw r12, ISTATE_OFFSET_R12(r3)
|
|
|
|
stw sp, ISTATE_OFFSET_SP(r3)
|
|
|
|
blr |