/* m88k.s -- assembly code for the Motorola 88000 architecture * * An m88k context array is laid out like this: * * saved sp register ------------------------------| * magic word for checking integrity | * unused stack space | * saved registers, including r1 (return addr) <--- saved sp points here * older stack data * * The stack must always remain 8-byte aligned. * We assume that the caller will ensure this. * * R26-29 are saved for the benefit of the Green Hills compiler; * they don't appear to be needed by GCC. */ #define MAGIC 61407 /* an unlikely integer */ /* The next two definitions must be a multiple of 8 */ #define RSIZE 72 /* space needed for 18 saved registers */ #define ASIZE 16 /* space needed for 4-argument buffer */ file "m88k.s" data align 4 curr_ctx: /* saves addr of current context array */ word dummy_ctx /* initialized with dummy context */ dummy_ctx: /* dummy initial context */ word dummy_stack /* pointer to stack */ word MAGIC /* magic word to pass the sanity check */ /* dummy_stack: */ bss dummy_stack,RSIZE,8 /* room to save the registers */ text align 4 /* mpd_build_context(code,context,stksize,arg1,arg2,arg3,arg4) * * args passed in: r2 r3 r4 r5 r6 r7 r8 * * code entry point of the code to be executed in the context * context buffer for holding the context array * stksize size of this buffer * arg1..arg4 four int-sized arguments to be passed to the code * * All we need to do is set up a context that will execute the startup * code, below, when activated for the first time. */ global _mpd_build_context _mpd_build_context: or r10,r0,MAGIC st r10,r3,4 /* save magic word */ addu r9,r3,r4 /* end of buffer */ subu r9,r9,ASIZE /* allow room for argument buffer */ subu r9,r9,RSIZE /* r9 = new stack pointer */ st r9,r3,0 /* save in context array */ st r2,r9,4 /* save code address in r14 slot */ st r5,r9,8 /* save first arg in r15 slot */ st r6,r9,12 /* save second arg in r16 slot */ st r7,r9,16 /* save third arg in r17 slot */ st r8,r9,20 /* save fourth arg in r18 slot */ st r30,r9,52 /* inherit current frame pointer as a base */ or.u r10,r0,hi16(startup) or r10,r10,lo16(startup) st r10,r9,0 /* save startup address in r1 slot */ jmp r1 /* return */ or r0,r0,r0 /* safe instr following a branch */ startup: or r2,r0,r15 /* load arg registers for first-time call */ or r3,r0,r16 or r4,r0,r17 or r5,r0,r18 or.u r1,r0,hi16(under) /* detect underflow if code returns */ or r1,r1,lo16(under) jmp r14 /* jump to entry point */ or r0,r0,r0 /* safe instr following a branch */ /* mpd_chg_context(newctx) -- switch to the specified context */ global _mpd_chg_context _mpd_chg_context: subu r31,r31,RSIZE /* make room on stack for saving registers */ or.u r3,r0,hi16(curr_ctx) or r3,r3,lo16(curr_ctx) ld r4,r3,0 /* r4 = addr of current context array */ cmp r5,r31,r4 bb1 ls,r5,over /* abort if stack is overflowing */ ld r5,r4,4 cmp r5,r5,MAGIC bb1 ne,r5,bad /* abort if earlier overflow clobbered magic */ ld r5,r2,4 cmp r5,r5,MAGIC bb1 ne,r5,bad /* abort if new context isn't intact */ st r31,r4,0 /* save old SP, then registers */ st r1,r31,0 st r14,r31,4 st r15,r31,8 st r16,r31,12 st r17,r31,16 st r18,r31,20 st r19,r31,24 st r20,r31,28 st r21,r31,32 st r22,r31,36 st r23,r31,40 st r24,r31,44 st r25,r31,48 st r30,r31,52 st r29,r31,56 st r28,r31,60 st r27,r31,64 st r26,r31,68 ld r31,r2,0 /* load new SP, then registers */ ld r1,r31,0 ld r14,r31,4 ld r15,r31,8 ld r16,r31,12 ld r17,r31,16 ld r18,r31,20 ld r19,r31,24 ld r20,r31,28 ld r21,r31,32 ld r22,r31,36 ld r23,r31,40 ld r24,r31,44 ld r25,r31,48 ld r30,r31,52 ld r29,r31,56 ld r28,r31,60 ld r27,r31,64 ld r26,r31,68 addu r31,r31,RSIZE /* adjust SP to remove register area */ st r2,r3,0 /* save addr of (new) current context */ jmp r1 /* return into new context */ or r0,r0,r0 /* safe instr following a branch */ /* mpd_check_stk() -- check that the stack is not overflowing */ global _mpd_check_stk _mpd_check_stk: or.u r13,r0,hi16(curr_ctx) ld r10,r13,lo16(curr_ctx) /* load addr of curr context array */ cmp r11,r31,r10 /* compare stack pointer with it */ bb1 ls,r11,over /* check that we haven't grown beyond it */ or r0,r0,r0 /* nop -- can't have jmp right after bb1 */ jmp r1 /* return */ or r0,r0,r0 /* safe instr following a branch */ /* stack problem handlers (these calls do not return) */ over: bsr _mpd_stk_overflow or r0,r0,r0 /* safe instr following a branch */ under: bsr _mpd_stk_underflow or r0,r0,r0 /* safe instr following a branch */ bad: bsr _mpd_stk_corrupted or r0,r0,r0 /* safe instr following a branch */