/* m68k.s -- sun2/sun3/NeXT assembly language code * * (This should work also for other MC68000 machines if they use the same * calling sequences and register conventions.) * * A context array is laid out like this: * * saved registers * magic word for checking integrity * unused stack space * saved pc <--- saved sp points here * valid stack data (if any) * address of error handler (in case of erroneous return) * arguments from mpd_build_context call * * Registers are always saved at the base of the array. a0/a1/d0/d1 aren't * saved because C doesn't expect them to survive over function calls. * The set does include sp, so we don't need to handle it separately. */ #define MAGIC 618033989 /* any unlikely long integer */ #define RMASK 0xFCFC /* register save mask (d2-d7, a2-a6, sp) */ #define RSIZE 48 /* size of register save area */ /* mpd_build_context(code,buf,bufsize,a1,a2,a3,a4) -- create a new context. * * code entry point of the code to be executed in the context * buf buffer for holding the context array * bufsize size of the buffer * a1 - a4 four int-sized arguments to be passed to the code */ .globl _mpd_build_context _mpd_build_context: movl a6,sp@- /* save caller's frame pointer */ movl sp@(12),a1 /* a1 = pointer to context array */ movl a1,a6 addl sp@(16),a6 /* a6 = pointer to end of context's stack */ movl sp@(32),a6@- /* push arg4 */ movl sp@(28),a6@- /* push arg3 */ movl sp@(24),a6@- /* push arg2 */ movl sp@(20),a6@- /* push arg1 */ movl #under,a6@- /* push error addr in case context returns */ movl sp@(8),a6@- /* push address for starting execution */ movl sp,a0 /* save pointer to stack we were called on */ movl a6,sp /* set user stack pointer */ moveml #RMASK,a1@ /* save registers in user context block */ addl #RSIZE,a1 movl #MAGIC,a1@ /* store magic word for integrity checking */ movl a0,sp /* restore our stack pointer */ movl sp@+,a6 /* restore caller's frame pointer */ rts /* return */ /* mpd_chg_context(newstk,oldstk) -- switch context to the specified stack */ .globl _mpd_chg_context _mpd_chg_context: movl sp@(8),a0 /* load address of current context stack */ tstl a0 /* skip save if so requested */ jeq first moveml #RMASK,a0@ /* save registers (including sp) */ addl #RSIZE,a0 cmpl a0,sp /* check that stack isn't overflowing */ jcs over cmpl #MAGIC,a0@ /* catch earlier overflow (maybe) */ jne over first: movl sp@(4),a0 /* load address of new context */ lea a0@(RSIZE),a1 cmpl #MAGIC,a1@ /* make sure new stack looks okay */ jne bad moveml a0@,#RMASK /* load new context (including sp) */ rts /* return into new context */ /* mpd_check_stk(context) -- check that the stack is not overflowing */ .globl _mpd_check_stk _mpd_check_stk: movl sp@(4),a0 addl #RSIZE,a0 cmpl a0,sp jcs over rts /* stack problem handlers (these calls do not return) */ over: jbsr _mpd_stk_overflow under: jbsr _mpd_stk_underflow bad: jbsr _mpd_stk_corrupted