1/* m88k.s -- assembly support. */ 2 3/* 4 * QuickThreads -- Threads-building toolkit. 5 * Copyright (c) 1993 by David Keppel 6 * 7 * Permission to use, copy, modify and distribute this software and 8 * its documentation for any purpose and without fee is hereby 9 * granted, provided that the above copyright notice and this notice 10 * appear in all copies. This software is provided as a 11 * proof-of-concept and for demonstration purposes; there is no 12 * representation about the suitability of this software for any 13 * purpose. 14 */ 15 16/* Callee-save r14..r25, r31(sp), r30(fp). r1 === return pc. 17 * Argument registers r2..r9, return value r2..r3. 18 * 19 * On startup, restore regs so retpc === call to a function to start. 20 * 21 * We're going to call a function (r2) from within the context switch 22 * routine. Call it on the new thread's stack on behalf of the old 23 * thread. 24 */ 25 26 .globl _qt_block 27 .globl _qt_blocki 28 .globl _qt_abort 29 .globl _qt_start 30 .globl _qt_vstart 31 32 /* 33 ** r2: ptr to function to call once curr is suspended 34 ** and control is on r5's stack. 35 ** r3: 1'th arg to *r2. 36 ** r4: 2'th arg to *r2. 37 ** r5: sp of thread to suspend. 38 ** 39 ** The helper routine returns a value that is passed on as the 40 ** return value from the blocking routine. Since we don't 41 ** touch r2 between the helper's return and the end of 42 ** function, we get this behavior for free. 43 ** 44 ** Same entry for integer-only and floating-point, since there 45 ** are no separate integer and floating-point registers. 46 ** 47 ** Each procedure call sets aside a ``home region'' of 8 regs 48 ** for r2-r9 for varargs. For context switches we don't use 49 ** the ``home region'' for varargs so use it to save regs. 50 ** Allocate 64 bytes of save space -- use 32 bytes of register 51 ** save area passed in to us plus 32 bytes we allcated, use 52 ** the other 32 bytes for save area for a save area to call 53 ** the helper function. 54 */ 55_qt_block: 56_qt_blocki: 57 sub r31, r31,64 /* Allocate reg save space. */ 58 st r1, r31,8+32 /* Save callee-save registers. */ 59 st r14, r31,12+32 60 st.d r15, r31,16+32 61 st.d r17, r31,24+32 62 st.d r19, r31,32+32 63 st.d r21, r31,40+32 64 st.d r23, r31,48+32 65 st r25, r31,56+32 66 st r30, r31,60+32 67 68_qt_abort: 69 addu r14, r31,0 /* Remember old sp. */ 70 addu r31, r5,0 /* Set new sp. */ 71 jsr.n r2 /* Call helper. */ 72 addu r2, r14,0 /* Pass old sp as an arg0 to helper. */ 73 74 ld r1, r31,8+32 /* Restore callee-save registers. */ 75 ld r14, r31,12+32 76 ld.d r15, r31,16+32 77 ld.d r17, r31,24+32 78 ld.d r19, r31,32+32 79 ld.d r21, r31,40+32 80 ld.d r23, r31,48+32 81 ld r25, r31,56+32 82 ld r30, r31,60+32 83 84 jmp.n r1 /* Return to new thread's caller. */ 85 addu r31, r31,64 /* Free register save space. */ 86 87 88 /* 89 ** Non-varargs thread startup. 90 ** See `m88k.h' for register use conventions. 91 */ 92_qt_start: 93 addu r2, r14,0 /* Set user arg `pu'. */ 94 addu r3, r15,0 /* ... user function pt. */ 95 jsr.n r17 /* Call `only'. */ 96 addu r4, r16,0 /* ... user function userf. */ 97 98 bsr _qt_error /* `only' erroniously returned. */ 99 100 101 /* 102 ** Varargs thread startup. 103 ** See `m88k.h' for register use conventions. 104 ** 105 ** Call the `startup' function with just argument `pt'. 106 ** Then call `vuserf' with 8 register args plus any 107 ** stack args. 108 ** Then call `cleanup' with `pt' and the return value 109 ** from `vuserf'. 110 */ 111_qt_vstart: 112 addu r18, r30,0 /* Remember arg7 to `vuserf'. */ 113 addu r30, r0,0 /* Null-terminate call chain. */ 114 115 jsr.n r17 /* Call `startup'. */ 116 addu r2, r15,0 /* `pt' is arg0 to `startup'. */ 117 118 addu r2, r19,0 /* Set arg0. */ 119 addu r3, r20,0 /* Set arg1. */ 120 addu r4, r21,0 /* Set arg2. */ 121 addu r5, r22,0 /* Set arg3. */ 122 addu r6, r23,0 /* Set arg4. */ 123 addu r7, r24,0 /* Set arg5. */ 124 addu r8, r25,0 /* Set arg6. */ 125 jsr.n r16 /* Call `vuserf'. */ 126 addu r9, r18,0 /* Set arg7. */ 127 128 addu r3, r2,0 /* Ret. value is arg1 to `cleanup'. */ 129 jsr.n r14 /* Call `cleanup'. */ 130 addu r2, r15,0 /* `pt' is arg0 to `cleanup'. */ 131 132 bsr _qt_error /* `cleanup' erroniously returned. */ 133