James Hogan | 027f891 | 2012-09-21 17:40:06 +0100 | [diff] [blame] | 1 | /* |
| 2 | * tbipcx.S |
| 3 | * |
| 4 | * Copyright (C) 2001, 2002, 2007, 2009, 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 | * Asyncronous trigger handling including exceptions |
| 11 | */ |
| 12 | |
| 13 | .file "tbipcx.S" |
| 14 | #include <asm/metag_regs.h> |
| 15 | #include <asm/tbx.h> |
| 16 | |
| 17 | /* BEGIN HACK */ |
| 18 | /* define these for now while doing inital conversion to GAS |
| 19 | will fix properly later */ |
| 20 | |
| 21 | /* Signal identifiers always have the TBID_SIGNAL_BIT set and contain the |
| 22 | following related bit-fields */ |
| 23 | #define TBID_SIGNUM_S 2 |
| 24 | |
| 25 | /* END HACK */ |
| 26 | |
| 27 | #ifdef METAC_1_0 |
| 28 | /* Ax.4 is saved in TBICTX */ |
| 29 | #define A0_4 ,A0.4 |
| 30 | #else |
| 31 | /* Ax.4 is NOT saved in TBICTX */ |
| 32 | #define A0_4 |
| 33 | #endif |
| 34 | |
| 35 | /* Size of the TBICTX structure */ |
| 36 | #define TBICTX_BYTES ((TBICTX_AX_REGS*8)+TBICTX_AX) |
| 37 | |
| 38 | #ifdef METAC_1_1 |
| 39 | #ifndef BOOTROM |
| 40 | #ifndef SPECIAL_BUILD |
| 41 | /* Jump straight into the boot ROM version of this code */ |
| 42 | #define CODE_USES_BOOTROM |
| 43 | #endif |
| 44 | #endif |
| 45 | #endif |
| 46 | |
| 47 | /* Define space needed for CATCH buffer state in traditional units */ |
| 48 | #define CATCH_ENTRIES 5 |
| 49 | #define CATCH_ENTRY_BYTES 16 |
| 50 | |
| 51 | #ifndef CODE_USES_BOOTROM |
| 52 | #define A0GblIStP A0.15 /* PTBICTX for current thread in PRIV system */ |
| 53 | #define A1GblIGbP A1.15 /* Interrupt A1GbP value in PRIV system */ |
| 54 | #endif |
| 55 | |
| 56 | /* |
| 57 | * TBIRES __TBIASyncTrigger( TBIRES State ) |
| 58 | */ |
| 59 | .text |
| 60 | .balign 4 |
| 61 | .global ___TBIASyncTrigger |
| 62 | .type ___TBIASyncTrigger,function |
| 63 | ___TBIASyncTrigger: |
| 64 | #ifdef CODE_USES_BOOTROM |
| 65 | MOVT D0Re0,#HI(LINCORE_BASE) |
| 66 | JUMP D0Re0,#0xA0 |
| 67 | #else |
| 68 | MOV D0FrT,A0FrP /* Boing entry sequence */ |
| 69 | ADD A0FrP,A0StP,#0 |
| 70 | SETL [A0StP++],D0FrT,D1RtP |
| 71 | MOV D0Re0,PCX /* Check for repeat call */ |
| 72 | MOVT D0FrT,#HI(___TBIBoingRTI+4) |
| 73 | ADD D0FrT,D0FrT,#LO(___TBIBoingRTI+4) |
| 74 | CMP D0Re0,D0FrT |
| 75 | BEQ ___TBIBoingExit /* Already set up - come out */ |
| 76 | ADD D1Ar1,D1Ar1,#7 /* PRIV system stack here */ |
| 77 | MOV A0.2,A0StP /* else push context here */ |
| 78 | MOVS D0Re0,D0Ar2 /* Return in user mode? */ |
| 79 | ANDMB D1Ar1,D1Ar1,#0xfff8 /* align priv stack to 64-bit */ |
| 80 | MOV D1Re0,D1Ar1 /* and set result to arg */ |
| 81 | MOVMI A0.2,D1Ar1 /* use priv stack if PRIV set */ |
| 82 | /* |
| 83 | * Generate an initial TBICTX to return to our own current call context |
| 84 | */ |
| 85 | MOVT D1Ar5,#HI(___TBIBoingExit) /* Go here to return */ |
| 86 | ADD D1Ar5,D1Ar5,#LO(___TBIBoingExit) |
| 87 | ADD A0.3,A0.2,#TBICTX_DX /* DX Save area */ |
| 88 | ANDT D0Ar2,D0Ar2,#TBICTX_PRIV_BIT /* Extract PRIV bit */ |
| 89 | MOVT D0Ar6,#TBICTX_SOFT_BIT /* Only soft thread state */ |
| 90 | ADD D0Ar6,D0Ar6,D0Ar2 /* Add in PRIV bit if requested */ |
| 91 | SETL [A0.2],D0Ar6,D1Ar5 /* Push header fields */ |
| 92 | ADD D0FrT,A0.2,#TBICTX_AX /* Address AX save area */ |
| 93 | MSETL [A0.3],D0Re0,D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7 |
| 94 | MOV D0Ar6,#0 |
| 95 | MOV D1Ar5,#0 |
| 96 | SETL [A0.3++],D0Ar6,D1Ar5 /* Zero CT register states */ |
| 97 | SETL [A0.3++],D0Ar6,D1Ar5 |
| 98 | MSETL [D0FrT],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX regs */ |
| 99 | MOV A0FrP,A0.2 /* Restore me! */ |
| 100 | B ___TBIResume |
| 101 | .size ___TBIASyncTrigger,.-___TBIASyncTrigger |
| 102 | |
| 103 | /* |
| 104 | * Optimised return to handler for META Core |
| 105 | */ |
| 106 | ___TBIBoingRTH: |
| 107 | RTH /* Go to background level */ |
| 108 | MOVT A0.2, #HI($Lpcx_target) |
| 109 | ADD A0.2,A0.2,#LO($Lpcx_target) |
| 110 | MOV PCX,A0.2 /* Setup PCX for interrupts */ |
| 111 | MOV PC,D1Re0 /* Jump to handler */ |
| 112 | /* |
| 113 | * This is where the code below needs to jump to wait for outermost interrupt |
| 114 | * event in a non-privilege mode system (single shared interrupt stack). |
| 115 | */ |
| 116 | ___TBIBoingPCX: |
| 117 | MGETL A0StP,A0FrP,A0.2,A0.3 A0_4,[D1Re0] /* Restore AX regs */ |
| 118 | MOV TXSTATUS,D0Re0 /* Restore flags */ |
| 119 | GETL D0Re0,D1Re0,[D1Re0+#TBICTX_DX-TBICTX_BYTES] |
| 120 | ___TBIBoingRTI: |
| 121 | RTI /* Wait for interrupt */ |
| 122 | $Lpcx_target: |
| 123 | /* |
| 124 | * Save initial interrupt state on current stack |
| 125 | */ |
| 126 | SETL [A0StP+#TBICTX_DX],D0Re0,D1Re0 /* Save key registers */ |
| 127 | ADD D1Re0,A0StP,#TBICTX_AX /* Address AX save area */ |
| 128 | MOV D0Re0,TXSTATUS /* Read TXSTATUS into D0Re0 */ |
| 129 | MOV TXSTATUS,#0 /* Clear TXSTATUS */ |
| 130 | MSETL [D1Re0],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX critical regs */ |
| 131 | /* |
| 132 | * Register state at this point is- |
| 133 | * |
| 134 | * D0Re0 - Old TXSTATUS with PRIV and CBUF bits set if appropriate |
| 135 | * A0StP - Is call stack frame and base of TBICTX being generated |
| 136 | * A1GbP - Is valid static access link |
| 137 | */ |
| 138 | ___TBIBoing: |
| 139 | LOCK0 /* Make sure we have no locks! */ |
| 140 | ADD A1.2,A0StP,#TBICTX_DX+(8*1) /* Address DX.1 save area */ |
| 141 | MOV A0FrP,A0StP /* Setup frame pointer */ |
| 142 | MSETL [A1.2],D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7 |
| 143 | MOV D0Ar4,TXRPT /* Save critical CT regs */ |
| 144 | MOV D1Ar3,TXBPOBITS |
| 145 | MOV D1Ar1,TXDIVTIME /* Calc catch buffer pSrc */ |
| 146 | MOV D0Ar2,TXMODE |
| 147 | MOV TXMODE,#0 /* Clear TXMODE */ |
| 148 | #ifdef TXDIVTIME_RPDIRTY_BIT |
| 149 | TSTT D1Ar1,#HI(TXDIVTIME_RPDIRTY_BIT)/* NZ = RPDIRTY */ |
| 150 | MOVT D0Ar6,#TBICTX_CBRP_BIT |
| 151 | ORNZ D0Re0,D0Re0,D0Ar6 /* Set CBRP if RPDIRTY set */ |
| 152 | #endif |
| 153 | MSETL [A1.2],D0Ar4,D0Ar2 /* Save CT regs state */ |
| 154 | MOV D0Ar2,D0Re0 /* Copy TXSTATUS */ |
| 155 | ANDMT D0Ar2,D0Ar2,#TBICTX_CBUF_BIT+TBICTX_CBRP_BIT |
| 156 | #ifdef TBI_1_4 |
| 157 | MOVT D1Ar1,#TBICTX_FPAC_BIT /* Copy FPActive into FPAC */ |
| 158 | TSTT D0Re0,#HI(TXSTATUS_FPACTIVE_BIT) |
| 159 | ORNZ D0Ar2,D0Ar2,D1Ar1 |
| 160 | #endif |
| 161 | MOV D1Ar1,PCX /* Read CurrPC */ |
| 162 | ORT D0Ar2,D0Ar2,#TBICTX_CRIT_BIT /* SaveMask + CRIT bit */ |
| 163 | SETL [A0FrP+#TBICTX_Flags],D0Ar2,D1Ar1 /* Set pCtx header fields */ |
| 164 | /* |
| 165 | * Completed context save, now we need to make a call to an interrupt handler |
| 166 | * |
| 167 | * D0Re0 - holds PRIV, WAIT, CBUF flags, HALT reason if appropriate |
| 168 | * A0FrP - interrupt stack frame and base of TBICTX being generated |
| 169 | * A0StP - same as A0FrP |
| 170 | */ |
| 171 | ___TBIBoingWait: |
| 172 | /* Reserve space for TBICTX and CBUF */ |
| 173 | ADD A0StP,A0StP,#TBICTX_BYTES+(CATCH_ENTRY_BYTES*CATCH_ENTRIES) |
| 174 | MOV D0Ar4,TXSTATI /* Read the Triggers data */ |
| 175 | MOV D1Ar3,TXDIVTIME /* Read IRQEnc bits */ |
| 176 | MOV D0Ar2,D0Re0 /* Copy PRIV and WAIT flags */ |
| 177 | ANDT D0Ar2,D0Ar2,#TBICTX_PRIV_BIT+TBICTX_WAIT_BIT+TBICTX_CBUF_BIT |
| 178 | #ifdef TBI_1_4 |
| 179 | MOVT D1Ar5,#TBICTX_FPAC_BIT /* Copy FPActive into FPAC */ |
| 180 | TSTT D0Re0,#HI(TXSTATUS_FPACTIVE_BIT) |
| 181 | ORNZ D0Ar2,D0Ar2,D1Ar5 |
| 182 | #endif |
| 183 | ANDT D1Ar3,D1Ar3,#HI(TXDIVTIME_IRQENC_BITS) |
| 184 | LSR D1Ar3,D1Ar3,#TXDIVTIME_IRQENC_S |
| 185 | AND TXSTATI,D0Ar4,#TXSTATI_BGNDHALT_BIT/* Ack any HALT seen */ |
| 186 | ANDS D0Ar4,D0Ar4,#0xFFFF-TXSTATI_BGNDHALT_BIT /* Only seen HALT? */ |
| 187 | ORT D0Ar2,D0Ar2,#TBICTX_CRIT_BIT /* Set CRIT */ |
| 188 | #ifndef BOOTROM |
| 189 | MOVT A1LbP,#HI(___pTBIs) |
| 190 | ADD A1LbP,A1LbP,#LO(___pTBIs) |
| 191 | GETL D1Ar5,D0Ar6,[A1LbP] /* D0Ar6 = ___pTBIs[1] */ |
| 192 | #else |
| 193 | /* |
| 194 | * For BOOTROM support ___pTBIs must be allocated at offset 0 vs A1GbP |
| 195 | */ |
| 196 | GETL D1Ar5,D0Ar6,[A1GbP] /* D0Ar6 = ___pTBIs[1] */ |
| 197 | #endif |
| 198 | BZ ___TBIBoingHalt /* Yes: Service HALT */ |
| 199 | /* |
| 200 | * Encode interrupt as signal vector, strip away same/lower TXMASKI bits |
| 201 | */ |
| 202 | MOV D1Ar1,#1 /* Generate mask for this bit */ |
| 203 | MOV D0Re0,TXMASKI /* Get interrupt mask */ |
| 204 | LSL TXSTATI,D1Ar1,D1Ar3 /* Acknowledge trigger */ |
| 205 | AND TXMASKI,D0Re0,#TXSTATI_BGNDHALT_BIT /* Only allow HALTs */ |
| 206 | OR D0Ar2,D0Ar2,D0Re0 /* Set TBIRES.Sig.TrigMask */ |
| 207 | ADD D1Ar3,D1Ar3,#TBID_SIGNUM_TRT /* Offset into interrupt sigs */ |
| 208 | LSL D0Re0,D1Ar3,#TBID_SIGNUM_S /* Generate offset from SigNum */ |
| 209 | /* |
| 210 | * This is a key moment we are about to call the handler, register state is |
| 211 | * as follows- |
| 212 | * |
| 213 | * D0Re0 - Handler vector (SigNum<<TBID_SIGNUM_S) |
| 214 | * D0Ar2 - TXMASKI:TBICTX_CRIT_BIT with optional CBUF and PRIV bits |
| 215 | * D1Ar3 - SigNum |
| 216 | * D0Ar4 - State read from TXSTATI |
| 217 | * D1Ar5 - Inst for SWITCH trigger case only, otherwise undefined |
| 218 | * D0Ar6 - pTBI |
| 219 | */ |
| 220 | ___TBIBoingVec: |
| 221 | ADD D0Re0,D0Re0,#TBI_fnSigs /* Offset into signal table */ |
| 222 | GETD D1Re0,[D0Ar6+D0Re0] /* Get address for Handler */ |
| 223 | /* |
| 224 | * Call handler at interrupt level, when it returns simply resume execution |
| 225 | * of state indicated by D1Re0. |
| 226 | */ |
| 227 | MOV D1Ar1,A0FrP /* Pass in pCtx */ |
| 228 | CALLR D1RtP,___TBIBoingRTH /* Use RTH to invoke handler */ |
| 229 | |
| 230 | /* |
| 231 | * Perform critical state restore and execute background thread. |
| 232 | * |
| 233 | * A0FrP - is pointer to TBICTX structure to resume |
| 234 | * D0Re0 - contains additional TXMASKI triggers |
| 235 | */ |
| 236 | .text |
| 237 | .balign 4 |
| 238 | #ifdef BOOTROM |
| 239 | .global ___TBIResume |
| 240 | #endif |
| 241 | ___TBIResume: |
| 242 | /* |
| 243 | * New META IP method |
| 244 | */ |
| 245 | RTH /* Go to interrupt level */ |
| 246 | MOV D0Ar4,TXMASKI /* Read TXMASKI */ |
| 247 | OR TXMASKI,D0Ar4,D0Re0 /* -Write-Modify TXMASKI */ |
| 248 | GETL D0Re0,D1Re0,[A0FrP+#TBICTX_Flags]/* Get Flags:SaveMask, CurrPC */ |
| 249 | MOV A0StP,A0FrP /* Position stack pointer */ |
| 250 | MOV D0Ar2,TXPOLLI /* Read pending triggers */ |
| 251 | MOV PCX,D1Re0 /* Set resumption PC */ |
| 252 | TST D0Ar2,#0xFFFF /* Any pending triggers? */ |
| 253 | BNZ ___TBIBoingWait /* Yes: Go for triggers */ |
| 254 | TSTT D0Re0,#TBICTX_WAIT_BIT /* Do we WAIT anyway? */ |
| 255 | BNZ ___TBIBoingWait /* Yes: Go for triggers */ |
| 256 | LSLS D1Ar5,D0Re0,#1 /* Test XCBF (MI) & PRIV (CS)? */ |
| 257 | ADD D1Re0,A0FrP,#TBICTX_CurrRPT /* Address CT save area */ |
| 258 | ADD A0StP,A0FrP,#TBICTX_DX+(8*1) /* Address DX.1 save area */ |
| 259 | MGETL A0.2,A0.3,[D1Re0] /* Get CT reg states */ |
| 260 | MOV D1Ar3,A1.3 /* Copy old TXDIVTIME */ |
| 261 | BPL ___TBIResCrit /* No: Skip logic */ |
| 262 | ADD D0Ar4,A0FrP,#TBICTX_BYTES /* Source is after TBICTX */ |
| 263 | ANDST D1Ar3,D1Ar3,#HI(TXDIVTIME_RPMASK_BITS)/* !Z if RPDIRTY */ |
| 264 | MGETL D0.5,D0.6,[D0Ar4] /* Read Catch state */ |
| 265 | MOV TXCATCH0,D0.5 /* Restore TXCATCHn */ |
| 266 | MOV TXCATCH1,D1.5 |
| 267 | MOV TXCATCH2,D0.6 |
| 268 | MOV TXCATCH3,D1.6 |
| 269 | BZ ___TBIResCrit |
| 270 | MOV D0Ar2,#(1*8) |
| 271 | LSRS D1Ar3,D1Ar3,#TXDIVTIME_RPMASK_S+1 /* 2nd RPMASK bit -> bit 0 */ |
| 272 | ADD RA,D0Ar4,#(0*8) /* Re-read read pipeline */ |
| 273 | ADDNZ RA,D0Ar4,D0Ar2 /* If Bit 0 set issue RA */ |
| 274 | LSRS D1Ar3,D1Ar3,#2 /* Bit 1 -> C, Bit 2 -> Bit 0 */ |
| 275 | ADD D0Ar2,D0Ar2,#8 |
| 276 | ADDCS RA,D0Ar4,D0Ar2 /* If C issue RA */ |
| 277 | ADD D0Ar2,D0Ar2,#8 |
| 278 | ADDNZ RA,D0Ar4,D0Ar2 /* If Bit 0 set issue RA */ |
| 279 | LSRS D1Ar3,D1Ar3,#2 /* Bit 1 -> C, Bit 2 -> Bit 0 */ |
| 280 | ADD D0Ar2,D0Ar2,#8 |
| 281 | ADDCS RA,D0Ar4,D0Ar2 /* If C issue RA */ |
| 282 | ADD D0Ar2,D0Ar2,#8 |
| 283 | ADDNZ RA,D0Ar4,D0Ar2 /* If Bit 0 set issue RA */ |
| 284 | MOV TXDIVTIME,A1.3 /* Set RPDIRTY again */ |
| 285 | ___TBIResCrit: |
| 286 | LSLS D1Ar5,D0Re0,#1 /* Test XCBF (MI) & PRIV (CS)? */ |
| 287 | #ifdef TBI_1_4 |
| 288 | ANDT D1Ar5,D1Ar5,#(TBICTX_FPAC_BIT*2) |
| 289 | LSL D0Ar6,D1Ar5,#3 /* Convert FPAC into FPACTIVE */ |
| 290 | #endif |
| 291 | ANDMT D0Re0,D0Re0,#TBICTX_CBUF_BIT /* Keep CBUF bit from SaveMask */ |
| 292 | #ifdef TBI_1_4 |
| 293 | OR D0Re0,D0Re0,D0Ar6 /* Combine FPACTIVE with others */ |
| 294 | #endif |
| 295 | MGETL D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7,[A0StP] /* Restore DX */ |
| 296 | MOV TXRPT,A0.2 /* Restore CT regs */ |
| 297 | MOV TXBPOBITS,A1.2 |
| 298 | MOV TXMODE,A0.3 |
| 299 | BCC ___TBIBoingPCX /* Do non-PRIV wait! */ |
| 300 | MOV A1GblIGbP,A1GbP /* Save A1GbP too */ |
| 301 | MGETL A0StP,A0FrP,A0.2,A0.3 A0_4,[D1Re0] /* Restore AX regs */ |
| 302 | /* |
| 303 | * Wait for the first interrupt/exception trigger in a privilege mode system |
| 304 | * (interrupt stack area for current TASK to be pointed to by A0GblIStP |
| 305 | * or per_cpu__stack_save[hwthread_id]). |
| 306 | */ |
| 307 | MOV TXSTATUS,D0Re0 /* Restore flags */ |
| 308 | MOV D0Re0,TXPRIVEXT /* Set TXPRIVEXT_TXTOGGLEI_BIT */ |
| 309 | SUB D1Re0,D1Re0,#TBICTX_BYTES /* TBICTX is top of int stack */ |
| 310 | #ifdef TBX_PERCPU_SP_SAVE |
| 311 | SWAP D1Ar3,A1GbP |
| 312 | MOV D1Ar3,TXENABLE /* Which thread are we? */ |
| 313 | AND D1Ar3,D1Ar3,#TXENABLE_THREAD_BITS |
| 314 | LSR D1Ar3,D1Ar3,#TXENABLE_THREAD_S-2 |
| 315 | ADDT D1Ar3,D1Ar3,#HI(_per_cpu__stack_save) |
| 316 | ADD D1Ar3,D1Ar3,#LO(_per_cpu__stack_save) |
| 317 | SETD [D1Ar3],D1Re0 |
| 318 | SWAP D1Ar3,A1GbP |
| 319 | #else |
| 320 | MOV A0GblIStP, D1Re0 |
| 321 | #endif |
| 322 | OR D0Re0,D0Re0,#TXPRIVEXT_TXTOGGLEI_BIT |
| 323 | MOV TXPRIVEXT,D0Re0 /* Cannot set TXPRIVEXT if !priv */ |
| 324 | GETL D0Re0,D1Re0,[D1Re0+#TBICTX_DX] |
| 325 | RTI /* Wait for interrupt */ |
| 326 | /* |
| 327 | * Save initial interrupt state on A0GblIStP, switch to A0GblIStP if |
| 328 | * BOOTROM code, save and switch to [A1GbP] otherwise. |
| 329 | */ |
| 330 | ___TBIBoingPCXP: |
| 331 | #ifdef TBX_PERCPU_SP_SAVE |
| 332 | SWAP D1Ar3,A1GbP /* Get PRIV stack base */ |
| 333 | MOV D1Ar3,TXENABLE /* Which thread are we? */ |
| 334 | AND D1Ar3,D1Ar3,#TXENABLE_THREAD_BITS |
| 335 | LSR D1Ar3,D1Ar3,#TXENABLE_THREAD_S-2 |
| 336 | ADDT D1Ar3,D1Ar3,#HI(_per_cpu__stack_save) |
| 337 | ADD D1Ar3,D1Ar3,#LO(_per_cpu__stack_save) |
| 338 | GETD D1Ar3,[D1Ar3] |
| 339 | #else |
| 340 | SWAP D1Ar3,A0GblIStP /* Get PRIV stack base */ |
| 341 | #endif |
| 342 | SETL [D1Ar3+#TBICTX_DX],D0Re0,D1Re0 /* Save key registers */ |
| 343 | MOV D0Re0,TXPRIVEXT /* Clear TXPRIVEXT_TXTOGGLEI_BIT */ |
| 344 | ADD D1Re0,D1Ar3,#TBICTX_AX /* Address AX save area */ |
| 345 | ANDMB D0Re0,D0Re0,#0xFFFF-TXPRIVEXT_TXTOGGLEI_BIT |
| 346 | MOV TXPRIVEXT,D0Re0 /* Cannot set TXPRIVEXT if !priv */ |
| 347 | MOV D0Re0,TXSTATUS /* Read TXSTATUS into D0Re0 */ |
| 348 | MOV TXSTATUS,#0 /* Clear TXSTATUS */ |
| 349 | MSETL [D1Re0],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX critical regs */ |
| 350 | MOV A0StP,D1Ar3 /* Switch stacks */ |
| 351 | #ifdef TBX_PERCPU_SP_SAVE |
| 352 | MOV D1Ar3,A1GbP /* Get D1Ar2 back */ |
| 353 | #else |
| 354 | MOV D1Ar3,A0GblIStP /* Get D1Ar2 back */ |
| 355 | #endif |
| 356 | ORT D0Re0,D0Re0,#TBICTX_PRIV_BIT /* Add PRIV to TXSTATUS */ |
| 357 | MOV A1GbP,A1GblIGbP /* Restore A1GbP */ |
| 358 | B ___TBIBoing /* Enter common handler code */ |
| 359 | /* |
| 360 | * At this point we know it's a background HALT case we are handling. |
| 361 | * The restored TXSTATUS always needs to have zero in the reason bits. |
| 362 | */ |
| 363 | ___TBIBoingHalt: |
| 364 | MOV D0Ar4,TXMASKI /* Get interrupt mask */ |
| 365 | ANDST D0Re0,D0Re0,#HI(TXSTATUS_MAJOR_HALT_BITS+TXSTATUS_MEM_FAULT_BITS) |
| 366 | AND TXMASKI,D0Ar4,#TXSTATI_BGNDHALT_BIT /* Only allow HALTs */ |
| 367 | AND D0Ar4,D0Ar4,#0xFFFF-TXSTATI_BGNDHALT_BIT /* What ints are off? */ |
| 368 | OR D0Ar2,D0Ar2,D0Ar4 /* Set TBIRES.Sig.TrigMask */ |
| 369 | MOV D0Ar4,#TXSTATI_BGNDHALT_BIT /* This was the trigger state */ |
| 370 | LSR D1Ar3,D0Re0,#TXSTATUS_MAJOR_HALT_S |
| 371 | MOV D0Re0,#TBID_SIGNUM_XXF<<TBID_SIGNUM_S |
| 372 | BNZ ___TBIBoingVec /* Jump to XXF exception handler */ |
| 373 | /* |
| 374 | * Only the SWITCH cases are left, PCX must be valid |
| 375 | */ |
| 376 | #ifdef TBI_1_4 |
| 377 | MOV D1Ar5,TXPRIVEXT |
| 378 | TST D1Ar5,#TXPRIVEXT_MINIMON_BIT |
| 379 | LSR D1Ar3,D1Ar1,#1 /* Shift needed for MINIM paths (fill stall) */ |
| 380 | BZ $Lmeta /* If META only, skip */ |
| 381 | TSTT D1Ar1,#HI(0x00800000) |
| 382 | ANDMT D1Ar3,D1Ar3,#HI(0x007FFFFF >> 1)/* Shifted mask for large MINIM */ |
| 383 | ANDT D1Ar1,D1Ar1,#HI(0xFFE00000) /* Static mask for small MINIM */ |
| 384 | BZ $Llarge_minim /* If large MINIM */ |
| 385 | $Lsmall_minim: |
| 386 | TSTT D1Ar3,#HI(0x00100000 >> 1) |
| 387 | ANDMT D1Ar3,D1Ar3,#HI(0x001FFFFF >> 1)/* Correct shifted mask for large MINIM */ |
| 388 | ADDZ D1Ar1,D1Ar1,D1Ar3 /* If META rgn, add twice to undo LSR #1 */ |
| 389 | B $Lrecombine |
| 390 | $Llarge_minim: |
| 391 | ANDST D1Ar1,D1Ar1,#HI(0xFF800000) /* Correct static mask for small MINIM */ |
| 392 | /* Z=0 (Cannot place code at NULL) */ |
| 393 | $Lrecombine: |
| 394 | ADD D1Ar1,D1Ar1,D1Ar3 /* Combine static and shifted parts */ |
| 395 | $Lmeta: |
| 396 | GETW D1Ar5,[D1Ar1++] /* META: lo-16, MINIM: lo-16 (all-16 if short) */ |
| 397 | GETW D1Ar3,[D1Ar1] /* META: hi-16, MINIM: hi-16 (only if long) */ |
| 398 | MOV D1Re0,D1Ar5 |
| 399 | XOR D1Re0,D1Re0,#0x4000 |
| 400 | LSLSNZ D1Re0,D1Re0,#(32-14) /* MINIM: If long C=0, if short C=1 */ |
| 401 | LSLCC D1Ar3,D1Ar3,#16 /* META/MINIM long: Move hi-16 up */ |
| 402 | LSLCS D1Ar3,D1Ar5,#16 /* MINIM short: Dup all-16 */ |
| 403 | ADD D1Ar5,D1Ar5,D1Ar3 /* ALL: Combine both 16-bit parts */ |
| 404 | #else |
| 405 | GETD D1Ar5,[D1Ar1] /* Read instruction for switch */ |
| 406 | #endif |
| 407 | LSR D1Ar3,D1Ar5,#22 /* Convert into signal number */ |
| 408 | AND D1Ar3,D1Ar3,#TBID_SIGNUM_SW3-TBID_SIGNUM_SW0 |
| 409 | LSL D0Re0,D1Ar3,#TBID_SIGNUM_S /* Generate offset from SigNum */ |
| 410 | B ___TBIBoingVec /* Jump to switch handler */ |
| 411 | /* |
| 412 | * Exit from TBIASyncTrigger call |
| 413 | */ |
| 414 | ___TBIBoingExit: |
| 415 | GETL D0FrT,D1RtP,[A0FrP++] /* Restore state from frame */ |
| 416 | SUB A0StP,A0FrP,#8 /* Unwind stack */ |
| 417 | MOV A0FrP,D0FrT /* Last memory read completes */ |
| 418 | MOV PC,D1RtP /* Return to caller */ |
| 419 | #endif /* ifdef CODE_USES_BOOTROM */ |
| 420 | .size ___TBIResume,.-___TBIResume |
| 421 | |
| 422 | #ifndef BOOTROM |
| 423 | /* |
| 424 | * void __TBIASyncResume( TBIRES State ) |
| 425 | */ |
| 426 | .text |
| 427 | .balign 4 |
| 428 | .global ___TBIASyncResume |
| 429 | .type ___TBIASyncResume,function |
| 430 | ___TBIASyncResume: |
| 431 | /* |
| 432 | * Perform CRIT|SOFT state restore and execute background thread. |
| 433 | */ |
| 434 | MOV D1Ar3,D1Ar1 /* Restore this context */ |
| 435 | MOV D0Re0,D0Ar2 /* Carry in additional triggers */ |
| 436 | /* Reserve space for TBICTX */ |
| 437 | ADD D1Ar3,D1Ar3,#TBICTX_BYTES+(CATCH_ENTRY_BYTES*CATCH_ENTRIES) |
| 438 | MOV A0StP,D1Ar3 /* Enter with protection of */ |
| 439 | MOV A0FrP,D1Ar1 /* TBICTX on our stack */ |
| 440 | #ifdef CODE_USES_BOOTROM |
| 441 | MOVT D1Ar1,#HI(LINCORE_BASE) |
| 442 | JUMP D1Ar1,#0xA4 |
| 443 | #else |
| 444 | B ___TBIResume |
| 445 | #endif |
| 446 | .size ___TBIASyncResume,.-___TBIASyncResume |
| 447 | #endif /* ifndef BOOTROM */ |
| 448 | |
| 449 | /* |
| 450 | * End of tbipcx.S |
| 451 | */ |