James Hogan | 027f891 | 2012-09-21 17:40:06 +0100 | [diff] [blame] | 1 | /* |
| 2 | * tbisoft.S |
| 3 | * |
| 4 | * Copyright (C) 2001, 2002, 2007, 2012 Imagination Technologies. |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it under |
| 7 | * the terms of the GNU General Public License version 2 as published by the |
| 8 | * Free Software Foundation. |
| 9 | * |
| 10 | * Support for soft threads and soft context switches |
| 11 | */ |
| 12 | |
| 13 | .file "tbisoft.S" |
| 14 | |
| 15 | #include <asm/tbx.h> |
| 16 | |
| 17 | #ifdef METAC_1_0 |
| 18 | /* Ax.4 is saved in TBICTX */ |
| 19 | #define A0_4 ,A0.4 |
| 20 | #define D0_5 ,D0.5 |
| 21 | #else |
| 22 | /* Ax.4 is NOT saved in TBICTX */ |
| 23 | #define A0_4 |
| 24 | #define D0_5 |
| 25 | #endif |
| 26 | |
| 27 | /* Size of the TBICTX structure */ |
| 28 | #define TBICTX_BYTES ((TBICTX_AX_REGS*8)+TBICTX_AX) |
| 29 | |
| 30 | .text |
| 31 | .balign 4 |
| 32 | .global ___TBISwitchTail |
| 33 | .type ___TBISwitchTail,function |
| 34 | ___TBISwitchTail: |
| 35 | B $LSwitchTail |
| 36 | .size ___TBISwitchTail,.-___TBISwitchTail |
| 37 | |
| 38 | /* |
| 39 | * TBIRES __TBIJumpX( TBIX64 ArgsA, PTBICTX *rpSaveCtx, int TrigsMask, |
| 40 | * void (*fnMain)(), void *pStack ); |
| 41 | * |
| 42 | * This is a combination of __TBISwitch and __TBIJump with the context of |
| 43 | * the calling thread being saved in the rpSaveCtx location with a drop-thru |
| 44 | * effect into the __TBIJump logic. ArgsB passes via __TBIJump to the |
| 45 | * routine eventually invoked will reflect the rpSaveCtx value specified. |
| 46 | */ |
| 47 | .text |
| 48 | .balign 4 |
| 49 | .global ___TBIJumpX |
| 50 | .type ___TBIJumpX,function |
| 51 | ___TBIJumpX: |
| 52 | CMP D1RtP,#-1 |
| 53 | B $LSwitchStart |
| 54 | .size ___TBIJumpX,.-___TBIJumpX |
| 55 | |
| 56 | /* |
| 57 | * TBIRES __TBISwitch( TBIRES Switch, PTBICTX *rpSaveCtx ) |
| 58 | * |
Adam Buchbinder | cacd2c4 | 2016-03-04 11:20:54 -0800 | [diff] [blame] | 59 | * Software synchronous context switch between soft threads, save only the |
James Hogan | 027f891 | 2012-09-21 17:40:06 +0100 | [diff] [blame] | 60 | * registers which are actually valid on call entry. |
| 61 | * |
| 62 | * A0FrP, D0RtP, D0.5, D0.6, D0.7 - Saved on stack |
| 63 | * A1GbP is global to all soft threads so not virtualised |
| 64 | * A0StP is then saved as the base of the TBICTX of the thread |
| 65 | * |
| 66 | */ |
| 67 | .text |
| 68 | .balign 4 |
| 69 | .global ___TBISwitch |
| 70 | .type ___TBISwitch,function |
| 71 | ___TBISwitch: |
| 72 | XORS D0Re0,D0Re0,D0Re0 /* Set ZERO flag */ |
| 73 | $LSwitchStart: |
| 74 | MOV D0FrT,A0FrP /* Boing entry sequence */ |
| 75 | ADD A0FrP,A0StP,#0 |
| 76 | SETL [A0StP+#8++],D0FrT,D1RtP |
| 77 | /* |
| 78 | * Save current frame state - we save all regs because we don't want |
Adam Buchbinder | cacd2c4 | 2016-03-04 11:20:54 -0800 | [diff] [blame] | 79 | * uninitialised crap in the TBICTX structure that the asynchronous resumption |
James Hogan | 027f891 | 2012-09-21 17:40:06 +0100 | [diff] [blame] | 80 | * of a thread will restore. |
| 81 | */ |
| 82 | MOVT D1Re0,#HI($LSwitchExit) /* ASync resume point here */ |
| 83 | ADD D1Re0,D1Re0,#LO($LSwitchExit) |
| 84 | SETD [D1Ar3],A0StP /* Record pCtx of this thread */ |
| 85 | MOVT D0Re0,#TBICTX_SOFT_BIT /* Only soft thread state */ |
| 86 | SETL [A0StP++],D0Re0,D1Re0 /* Push header fields */ |
| 87 | ADD D0FrT,A0StP,#TBICTX_AX-TBICTX_DX /* Address AX save area */ |
| 88 | MOV D0Re0,#0 /* Setup 0:0 result for ASync */ |
| 89 | MOV D1Re0,#0 /* resume of the thread */ |
| 90 | MSETL [A0StP],D0Re0,D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7 |
| 91 | SETL [A0StP++],D0Re0,D1Re0 /* Zero CurrRPT, CurrBPOBITS, */ |
| 92 | SETL [A0StP++],D0Re0,D1Re0 /* Zero CurrMODE, CurrDIVTIME */ |
| 93 | ADD A0StP,A0StP,#(TBICTX_AX_REGS*8) /* Reserve AX save space */ |
| 94 | MSETL [D0FrT],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX regs */ |
| 95 | BNZ ___TBIJump |
| 96 | /* |
| 97 | * NextThread MUST be in TBICTX_SOFT_BIT state! |
| 98 | */ |
| 99 | $LSwitchTail: |
| 100 | MOV D0Re0,D0Ar2 /* Result from args */ |
| 101 | MOV D1Re0,D1Ar1 |
| 102 | ADD D1RtP,D1Ar1,#TBICTX_AX |
| 103 | MGETL A0StP,A0FrP,[D1RtP] /* Get frame values */ |
| 104 | $LSwitchCmn: |
| 105 | ADD A0.2,D1Ar1,#TBICTX_DX+(8*5) |
| 106 | MGETL D0.5,D0.6,D0.7,[A0.2] /* Get caller-saved DX regs */ |
| 107 | $LSwitchExit: |
| 108 | GETL D0FrT,D1RtP,[A0FrP++] /* Restore state from frame */ |
| 109 | SUB A0StP,A0FrP,#8 /* Unwind stack */ |
| 110 | MOV A0FrP,D0FrT /* Last memory read completes */ |
| 111 | MOV PC,D1RtP /* Return to caller */ |
| 112 | .size ___TBISwitch,.-___TBISwitch |
| 113 | |
| 114 | /* |
| 115 | * void __TBISyncResume( TBIRES State, int TrigMask ); |
| 116 | * |
| 117 | * This routine causes the TBICTX structure specified in State.Sig.pCtx to |
| 118 | * be restored. This implies that execution will not return to the caller. |
| 119 | * The State.Sig.TrigMask field will be ored into TXMASKI during the |
Adam Buchbinder | cacd2c4 | 2016-03-04 11:20:54 -0800 | [diff] [blame] | 120 | * context switch such that any immediately occurring interrupts occur in |
James Hogan | 027f891 | 2012-09-21 17:40:06 +0100 | [diff] [blame] | 121 | * the context of the newly specified task. The State.Sig.SaveMask parameter |
| 122 | * is ignored. |
| 123 | */ |
| 124 | .text |
| 125 | .balign 4 |
| 126 | .global ___TBISyncResume |
| 127 | .type ___TBISyncResume,function |
| 128 | ___TBISyncResume: |
| 129 | MOV D0Re0,D0Ar2 /* Result from args */ |
| 130 | MOV D1Re0,D1Ar1 |
| 131 | XOR D1Ar5,D1Ar5,D1Ar5 /* D1Ar5 = 0 */ |
| 132 | ADD D1RtP,D1Ar1,#TBICTX_AX |
| 133 | SWAP D1Ar5,TXMASKI /* D1Ar5 <-> TXMASKI */ |
| 134 | MGETL A0StP,A0FrP,[D1RtP] /* Get frame values */ |
| 135 | OR TXMASKI,D1Ar5,D1Ar3 /* New TXMASKI */ |
| 136 | B $LSwitchCmn |
| 137 | .size ___TBISyncResume,.-___TBISyncResume |
| 138 | |
| 139 | /* |
| 140 | * void __TBIJump( TBIX64 ArgsA, TBIX32 ArgsB, int TrigsMask, |
| 141 | * void (*fnMain)(), void *pStack ); |
| 142 | * |
| 143 | * Jump directly to a new routine on an arbitrary stack with arbitrary args |
| 144 | * oring bits back into TXMASKI on route. |
| 145 | */ |
| 146 | .text |
| 147 | .balign 4 |
| 148 | .global ___TBIJump |
| 149 | .type ___TBIJump,function |
| 150 | ___TBIJump: |
| 151 | XOR D0Re0,D0Re0,D0Re0 /* D0Re0 = 0 */ |
| 152 | MOV A0StP,D0Ar6 /* Stack = Frame */ |
| 153 | SWAP D0Re0,TXMASKI /* D0Re0 <-> TXMASKI */ |
| 154 | MOV A0FrP,D0Ar6 |
| 155 | MOVT A1LbP,#HI(__exit) |
| 156 | ADD A1LbP,A1LbP,#LO(__exit) |
| 157 | MOV D1RtP,A1LbP /* D1RtP = __exit */ |
| 158 | OR TXMASKI,D0Re0,D0Ar4 /* New TXMASKI */ |
| 159 | MOV PC,D1Ar5 /* Jump to fnMain */ |
| 160 | .size ___TBIJump,.-___TBIJump |
| 161 | |
| 162 | /* |
| 163 | * PTBICTX __TBISwitchInit( void *pStack, int (*fnMain)(), |
| 164 | * .... 4 extra 32-bit args .... ); |
| 165 | * |
| 166 | * Generate a new soft thread context ready for it's first outing. |
| 167 | * |
| 168 | * D1Ar1 - Region of memory to be used as the new soft thread stack |
| 169 | * D0Ar2 - Main line routine for new soft thread |
| 170 | * D1Ar3, D0Ar4, D1Ar5, D0Ar6 - arguments to be passed on stack |
| 171 | * The routine returns the initial PTBICTX value for the new thread |
| 172 | */ |
| 173 | .text |
| 174 | .balign 4 |
| 175 | .global ___TBISwitchInit |
| 176 | .type ___TBISwitchInit,function |
| 177 | ___TBISwitchInit: |
| 178 | MOV D0FrT,A0FrP /* Need save return point */ |
| 179 | ADD A0FrP,A0StP,#0 |
| 180 | SETL [A0StP++],D0FrT,D1RtP /* Save return to caller */ |
| 181 | MOVT A1LbP,#HI(__exit) |
| 182 | ADD A1LbP,A1LbP,#LO(__exit) |
| 183 | MOV D1RtP,A1LbP /* Get address of __exit */ |
| 184 | ADD D1Ar1,D1Ar1,#7 /* Align stack to 64-bits */ |
| 185 | ANDMB D1Ar1,D1Ar1,#0xfff8 /* by rounding base up */ |
| 186 | MOV A0.2,D1Ar1 /* A0.2 is new stack */ |
| 187 | MOV D0FrT,D1Ar1 /* Initial puesdo-frame pointer */ |
| 188 | SETL [A0.2++],D0FrT,D1RtP /* Save return to __exit */ |
| 189 | MOV D1RtP,D0Ar2 |
| 190 | SETL [A0.2++],D0FrT,D1RtP /* Save return to fnMain */ |
| 191 | ADD D0FrT,D0FrT,#8 /* Advance puesdo-frame pointer */ |
| 192 | MSETL [A0.2],D0Ar6,D0Ar4 /* Save extra initial args */ |
| 193 | MOVT D1RtP,#HI(___TBIStart) /* Start up code for new stack */ |
| 194 | ADD D1RtP,D1RtP,#LO(___TBIStart) |
| 195 | SETL [A0.2++],D0FrT,D1RtP /* Save return to ___TBIStart */ |
| 196 | ADD D0FrT,D0FrT,#(8*3) /* Advance puesdo-frame pointer */ |
| 197 | MOV D0Re0,A0.2 /* Return pCtx for new thread */ |
| 198 | MOV D1Re0,#0 /* pCtx:0 is default Arg1:Arg2 */ |
| 199 | /* |
| 200 | * Generate initial TBICTX state |
| 201 | */ |
| 202 | MOVT D1Ar1,#HI($LSwitchExit) /* Async restore code */ |
| 203 | ADD D1Ar1,D1Ar1,#LO($LSwitchExit) |
| 204 | MOVT D0Ar2,#TBICTX_SOFT_BIT /* Only soft thread state */ |
| 205 | ADD D0Ar6,A0.2,#TBICTX_BYTES /* New A0StP */ |
| 206 | MOV D1Ar5,A1GbP /* Same A1GbP */ |
| 207 | MOV D0Ar4,D0FrT /* Initial A0FrP */ |
| 208 | MOV D1Ar3,A1LbP /* Same A1LbP */ |
| 209 | SETL [A0.2++],D0Ar2,D1Ar1 /* Set header fields */ |
| 210 | MSETL [A0.2],D0Re0,D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7 |
| 211 | MOV D0Ar2,#0 /* Zero values */ |
| 212 | MOV D1Ar1,#0 |
| 213 | SETL [A0.2++],D0Ar2,D1Ar1 /* Zero CurrRPT, CurrBPOBITS, */ |
| 214 | SETL [A0.2++],D0Ar2,D1Ar1 /* CurrMODE, and pCurrCBuf */ |
| 215 | MSETL [A0.2],D0Ar6,D0Ar4,D0Ar2,D0FrT D0_5 /* Set DX and then AX regs */ |
| 216 | B $LSwitchExit /* All done! */ |
| 217 | .size ___TBISwitchInit,.-___TBISwitchInit |
| 218 | |
| 219 | .text |
| 220 | .balign 4 |
| 221 | .global ___TBIStart |
| 222 | .type ___TBIStart,function |
| 223 | ___TBIStart: |
| 224 | MOV D1Ar1,D1Re0 /* Pass TBIRES args to call */ |
| 225 | MOV D0Ar2,D0Re0 |
| 226 | MGETL D0Re0,D0Ar6,D0Ar4,[A0FrP] /* Get hidden args */ |
| 227 | SUB A0StP,A0FrP,#(8*3) /* Entry stack pointer */ |
| 228 | MOV A0FrP,D0Re0 /* Entry frame pointer */ |
| 229 | MOVT A1LbP,#HI(__exit) |
| 230 | ADD A1LbP,A1LbP,#LO(__exit) |
| 231 | MOV D1RtP,A1LbP /* D1RtP = __exit */ |
| 232 | MOV PC,D1Re0 /* Jump into fnMain */ |
| 233 | .size ___TBIStart,.-___TBIStart |
| 234 | |
| 235 | /* |
| 236 | * End of tbisoft.S |
| 237 | */ |