| /* m88k.s -- assembly support. */ | |
| /* | |
| * QuickThreads -- Threads-building toolkit. | |
| * Copyright (c) 1993 by David Keppel | |
| * | |
| * Permission to use, copy, modify and distribute this software and | |
| * its documentation for any purpose and without fee is hereby | |
| * granted, provided that the above copyright notice and this notice | |
| * appear in all copies. This software is provided as a | |
| * proof-of-concept and for demonstration purposes; there is no | |
| * representation about the suitability of this software for any | |
| * purpose. | |
| */ | |
| /* Callee-save r14..r25, r31(sp), r30(fp). r1 === return pc. | |
| * Argument registers r2..r9, return value r2..r3. | |
| * | |
| * On startup, restore regs so retpc === call to a function to start. | |
| * | |
| * We're going to call a function (r2) from within the context switch | |
| * routine. Call it on the new thread's stack on behalf of the old | |
| * thread. | |
| */ | |
| .globl _qt_block | |
| .globl _qt_blocki | |
| .globl _qt_abort | |
| .globl _qt_start | |
| .globl _qt_vstart | |
| /* | |
| ** r2: ptr to function to call once curr is suspended | |
| ** and control is on r5's stack. | |
| ** r3: 1'th arg to *r2. | |
| ** r4: 2'th arg to *r2. | |
| ** r5: sp of thread to suspend. | |
| ** | |
| ** The helper routine returns a value that is passed on as the | |
| ** return value from the blocking routine. Since we don't | |
| ** touch r2 between the helper's return and the end of | |
| ** function, we get this behavior for free. | |
| ** | |
| ** Same entry for integer-only and floating-point, since there | |
| ** are no separate integer and floating-point registers. | |
| ** | |
| ** Each procedure call sets aside a ``home region'' of 8 regs | |
| ** for r2-r9 for varargs. For context switches we don't use | |
| ** the ``home region'' for varargs so use it to save regs. | |
| ** Allocate 64 bytes of save space -- use 32 bytes of register | |
| ** save area passed in to us plus 32 bytes we allcated, use | |
| ** the other 32 bytes for save area for a save area to call | |
| ** the helper function. | |
| */ | |
| _qt_block: | |
| _qt_blocki: | |
| sub r31, r31,64 /* Allocate reg save space. */ | |
| st r1, r31,8+32 /* Save callee-save registers. */ | |
| st r14, r31,12+32 | |
| st.d r15, r31,16+32 | |
| st.d r17, r31,24+32 | |
| st.d r19, r31,32+32 | |
| st.d r21, r31,40+32 | |
| st.d r23, r31,48+32 | |
| st r25, r31,56+32 | |
| st r30, r31,60+32 | |
| _qt_abort: | |
| addu r14, r31,0 /* Remember old sp. */ | |
| addu r31, r5,0 /* Set new sp. */ | |
| jsr.n r2 /* Call helper. */ | |
| addu r2, r14,0 /* Pass old sp as an arg0 to helper. */ | |
| ld r1, r31,8+32 /* Restore callee-save registers. */ | |
| ld r14, r31,12+32 | |
| ld.d r15, r31,16+32 | |
| ld.d r17, r31,24+32 | |
| ld.d r19, r31,32+32 | |
| ld.d r21, r31,40+32 | |
| ld.d r23, r31,48+32 | |
| ld r25, r31,56+32 | |
| ld r30, r31,60+32 | |
| jmp.n r1 /* Return to new thread's caller. */ | |
| addu r31, r31,64 /* Free register save space. */ | |
| /* | |
| ** Non-varargs thread startup. | |
| ** See `m88k.h' for register use conventions. | |
| */ | |
| _qt_start: | |
| addu r2, r14,0 /* Set user arg `pu'. */ | |
| addu r3, r15,0 /* ... user function pt. */ | |
| jsr.n r17 /* Call `only'. */ | |
| addu r4, r16,0 /* ... user function userf. */ | |
| bsr _qt_error /* `only' erroniously returned. */ | |
| /* | |
| ** Varargs thread startup. | |
| ** See `m88k.h' for register use conventions. | |
| ** | |
| ** Call the `startup' function with just argument `pt'. | |
| ** Then call `vuserf' with 8 register args plus any | |
| ** stack args. | |
| ** Then call `cleanup' with `pt' and the return value | |
| ** from `vuserf'. | |
| */ | |
| _qt_vstart: | |
| addu r18, r30,0 /* Remember arg7 to `vuserf'. */ | |
| addu r30, r0,0 /* Null-terminate call chain. */ | |
| jsr.n r17 /* Call `startup'. */ | |
| addu r2, r15,0 /* `pt' is arg0 to `startup'. */ | |
| addu r2, r19,0 /* Set arg0. */ | |
| addu r3, r20,0 /* Set arg1. */ | |
| addu r4, r21,0 /* Set arg2. */ | |
| addu r5, r22,0 /* Set arg3. */ | |
| addu r6, r23,0 /* Set arg4. */ | |
| addu r7, r24,0 /* Set arg5. */ | |
| addu r8, r25,0 /* Set arg6. */ | |
| jsr.n r16 /* Call `vuserf'. */ | |
| addu r9, r18,0 /* Set arg7. */ | |
| addu r3, r2,0 /* Ret. value is arg1 to `cleanup'. */ | |
| jsr.n r14 /* Call `cleanup'. */ | |
| addu r2, r15,0 /* `pt' is arg0 to `cleanup'. */ | |
| bsr _qt_error /* `cleanup' erroniously returned. */ |