| /* |
| * tbipcx.S |
| * |
| * Copyright (C) 2001, 2002, 2007, 2009, 2012 Imagination Technologies. |
| * |
| * This program is free software; you can redistribute it and/or modify it under |
| * the terms of the GNU General Public License version 2 as published by the |
| * Free Software Foundation. |
| * |
| * Asyncronous trigger handling including exceptions |
| */ |
| |
| .file "tbipcx.S" |
| #include <asm/metag_regs.h> |
| #include <asm/tbx.h> |
| |
| /* BEGIN HACK */ |
| /* define these for now while doing initial conversion to GAS |
| will fix properly later */ |
| |
| /* Signal identifiers always have the TBID_SIGNAL_BIT set and contain the |
| following related bit-fields */ |
| #define TBID_SIGNUM_S 2 |
| |
| /* END HACK */ |
| |
| #ifdef METAC_1_0 |
| /* Ax.4 is saved in TBICTX */ |
| #define A0_4 ,A0.4 |
| #else |
| /* Ax.4 is NOT saved in TBICTX */ |
| #define A0_4 |
| #endif |
| |
| /* Size of the TBICTX structure */ |
| #define TBICTX_BYTES ((TBICTX_AX_REGS*8)+TBICTX_AX) |
| |
| #ifdef METAC_1_1 |
| #ifndef BOOTROM |
| #ifndef SPECIAL_BUILD |
| /* Jump straight into the boot ROM version of this code */ |
| #define CODE_USES_BOOTROM |
| #endif |
| #endif |
| #endif |
| |
| /* Define space needed for CATCH buffer state in traditional units */ |
| #define CATCH_ENTRIES 5 |
| #define CATCH_ENTRY_BYTES 16 |
| |
| #ifndef CODE_USES_BOOTROM |
| #define A0GblIStP A0.15 /* PTBICTX for current thread in PRIV system */ |
| #define A1GblIGbP A1.15 /* Interrupt A1GbP value in PRIV system */ |
| #endif |
| |
| /* |
| * TBIRES __TBIASyncTrigger( TBIRES State ) |
| */ |
| .text |
| .balign 4 |
| .global ___TBIASyncTrigger |
| .type ___TBIASyncTrigger,function |
| ___TBIASyncTrigger: |
| #ifdef CODE_USES_BOOTROM |
| MOVT D0Re0,#HI(LINCORE_BASE) |
| JUMP D0Re0,#0xA0 |
| #else |
| MOV D0FrT,A0FrP /* Boing entry sequence */ |
| ADD A0FrP,A0StP,#0 |
| SETL [A0StP++],D0FrT,D1RtP |
| MOV D0Re0,PCX /* Check for repeat call */ |
| MOVT D0FrT,#HI(___TBIBoingRTI+4) |
| ADD D0FrT,D0FrT,#LO(___TBIBoingRTI+4) |
| CMP D0Re0,D0FrT |
| BEQ ___TBIBoingExit /* Already set up - come out */ |
| ADD D1Ar1,D1Ar1,#7 /* PRIV system stack here */ |
| MOV A0.2,A0StP /* else push context here */ |
| MOVS D0Re0,D0Ar2 /* Return in user mode? */ |
| ANDMB D1Ar1,D1Ar1,#0xfff8 /* align priv stack to 64-bit */ |
| MOV D1Re0,D1Ar1 /* and set result to arg */ |
| MOVMI A0.2,D1Ar1 /* use priv stack if PRIV set */ |
| /* |
| * Generate an initial TBICTX to return to our own current call context |
| */ |
| MOVT D1Ar5,#HI(___TBIBoingExit) /* Go here to return */ |
| ADD D1Ar5,D1Ar5,#LO(___TBIBoingExit) |
| ADD A0.3,A0.2,#TBICTX_DX /* DX Save area */ |
| ANDT D0Ar2,D0Ar2,#TBICTX_PRIV_BIT /* Extract PRIV bit */ |
| MOVT D0Ar6,#TBICTX_SOFT_BIT /* Only soft thread state */ |
| ADD D0Ar6,D0Ar6,D0Ar2 /* Add in PRIV bit if requested */ |
| SETL [A0.2],D0Ar6,D1Ar5 /* Push header fields */ |
| ADD D0FrT,A0.2,#TBICTX_AX /* Address AX save area */ |
| MSETL [A0.3],D0Re0,D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7 |
| MOV D0Ar6,#0 |
| MOV D1Ar5,#0 |
| SETL [A0.3++],D0Ar6,D1Ar5 /* Zero CT register states */ |
| SETL [A0.3++],D0Ar6,D1Ar5 |
| MSETL [D0FrT],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX regs */ |
| MOV A0FrP,A0.2 /* Restore me! */ |
| B ___TBIResume |
| .size ___TBIASyncTrigger,.-___TBIASyncTrigger |
| |
| /* |
| * Optimised return to handler for META Core |
| */ |
| ___TBIBoingRTH: |
| RTH /* Go to background level */ |
| MOVT A0.2, #HI($Lpcx_target) |
| ADD A0.2,A0.2,#LO($Lpcx_target) |
| MOV PCX,A0.2 /* Setup PCX for interrupts */ |
| MOV PC,D1Re0 /* Jump to handler */ |
| /* |
| * This is where the code below needs to jump to wait for outermost interrupt |
| * event in a non-privilege mode system (single shared interrupt stack). |
| */ |
| ___TBIBoingPCX: |
| MGETL A0StP,A0FrP,A0.2,A0.3 A0_4,[D1Re0] /* Restore AX regs */ |
| MOV TXSTATUS,D0Re0 /* Restore flags */ |
| GETL D0Re0,D1Re0,[D1Re0+#TBICTX_DX-TBICTX_BYTES] |
| ___TBIBoingRTI: |
| RTI /* Wait for interrupt */ |
| $Lpcx_target: |
| /* |
| * Save initial interrupt state on current stack |
| */ |
| SETL [A0StP+#TBICTX_DX],D0Re0,D1Re0 /* Save key registers */ |
| ADD D1Re0,A0StP,#TBICTX_AX /* Address AX save area */ |
| MOV D0Re0,TXSTATUS /* Read TXSTATUS into D0Re0 */ |
| MOV TXSTATUS,#0 /* Clear TXSTATUS */ |
| MSETL [D1Re0],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX critical regs */ |
| /* |
| * Register state at this point is- |
| * |
| * D0Re0 - Old TXSTATUS with PRIV and CBUF bits set if appropriate |
| * A0StP - Is call stack frame and base of TBICTX being generated |
| * A1GbP - Is valid static access link |
| */ |
| ___TBIBoing: |
| LOCK0 /* Make sure we have no locks! */ |
| ADD A1.2,A0StP,#TBICTX_DX+(8*1) /* Address DX.1 save area */ |
| MOV A0FrP,A0StP /* Setup frame pointer */ |
| MSETL [A1.2],D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7 |
| MOV D0Ar4,TXRPT /* Save critical CT regs */ |
| MOV D1Ar3,TXBPOBITS |
| MOV D1Ar1,TXDIVTIME /* Calc catch buffer pSrc */ |
| MOV D0Ar2,TXMODE |
| MOV TXMODE,#0 /* Clear TXMODE */ |
| #ifdef TXDIVTIME_RPDIRTY_BIT |
| TSTT D1Ar1,#HI(TXDIVTIME_RPDIRTY_BIT)/* NZ = RPDIRTY */ |
| MOVT D0Ar6,#TBICTX_CBRP_BIT |
| ORNZ D0Re0,D0Re0,D0Ar6 /* Set CBRP if RPDIRTY set */ |
| #endif |
| MSETL [A1.2],D0Ar4,D0Ar2 /* Save CT regs state */ |
| MOV D0Ar2,D0Re0 /* Copy TXSTATUS */ |
| ANDMT D0Ar2,D0Ar2,#TBICTX_CBUF_BIT+TBICTX_CBRP_BIT |
| #ifdef TBI_1_4 |
| MOVT D1Ar1,#TBICTX_FPAC_BIT /* Copy FPActive into FPAC */ |
| TSTT D0Re0,#HI(TXSTATUS_FPACTIVE_BIT) |
| ORNZ D0Ar2,D0Ar2,D1Ar1 |
| #endif |
| MOV D1Ar1,PCX /* Read CurrPC */ |
| ORT D0Ar2,D0Ar2,#TBICTX_CRIT_BIT /* SaveMask + CRIT bit */ |
| SETL [A0FrP+#TBICTX_Flags],D0Ar2,D1Ar1 /* Set pCtx header fields */ |
| /* |
| * Completed context save, now we need to make a call to an interrupt handler |
| * |
| * D0Re0 - holds PRIV, WAIT, CBUF flags, HALT reason if appropriate |
| * A0FrP - interrupt stack frame and base of TBICTX being generated |
| * A0StP - same as A0FrP |
| */ |
| ___TBIBoingWait: |
| /* Reserve space for TBICTX and CBUF */ |
| ADD A0StP,A0StP,#TBICTX_BYTES+(CATCH_ENTRY_BYTES*CATCH_ENTRIES) |
| MOV D0Ar4,TXSTATI /* Read the Triggers data */ |
| MOV D1Ar3,TXDIVTIME /* Read IRQEnc bits */ |
| MOV D0Ar2,D0Re0 /* Copy PRIV and WAIT flags */ |
| ANDT D0Ar2,D0Ar2,#TBICTX_PRIV_BIT+TBICTX_WAIT_BIT+TBICTX_CBUF_BIT |
| #ifdef TBI_1_4 |
| MOVT D1Ar5,#TBICTX_FPAC_BIT /* Copy FPActive into FPAC */ |
| TSTT D0Re0,#HI(TXSTATUS_FPACTIVE_BIT) |
| ORNZ D0Ar2,D0Ar2,D1Ar5 |
| #endif |
| ANDT D1Ar3,D1Ar3,#HI(TXDIVTIME_IRQENC_BITS) |
| LSR D1Ar3,D1Ar3,#TXDIVTIME_IRQENC_S |
| AND TXSTATI,D0Ar4,#TXSTATI_BGNDHALT_BIT/* Ack any HALT seen */ |
| ANDS D0Ar4,D0Ar4,#0xFFFF-TXSTATI_BGNDHALT_BIT /* Only seen HALT? */ |
| ORT D0Ar2,D0Ar2,#TBICTX_CRIT_BIT /* Set CRIT */ |
| #ifndef BOOTROM |
| MOVT A1LbP,#HI(___pTBIs) |
| ADD A1LbP,A1LbP,#LO(___pTBIs) |
| GETL D1Ar5,D0Ar6,[A1LbP] /* D0Ar6 = ___pTBIs[1] */ |
| #else |
| /* |
| * For BOOTROM support ___pTBIs must be allocated at offset 0 vs A1GbP |
| */ |
| GETL D1Ar5,D0Ar6,[A1GbP] /* D0Ar6 = ___pTBIs[1] */ |
| #endif |
| BZ ___TBIBoingHalt /* Yes: Service HALT */ |
| /* |
| * Encode interrupt as signal vector, strip away same/lower TXMASKI bits |
| */ |
| MOV D1Ar1,#1 /* Generate mask for this bit */ |
| MOV D0Re0,TXMASKI /* Get interrupt mask */ |
| LSL TXSTATI,D1Ar1,D1Ar3 /* Acknowledge trigger */ |
| AND TXMASKI,D0Re0,#TXSTATI_BGNDHALT_BIT /* Only allow HALTs */ |
| OR D0Ar2,D0Ar2,D0Re0 /* Set TBIRES.Sig.TrigMask */ |
| ADD D1Ar3,D1Ar3,#TBID_SIGNUM_TRT /* Offset into interrupt sigs */ |
| LSL D0Re0,D1Ar3,#TBID_SIGNUM_S /* Generate offset from SigNum */ |
| /* |
| * This is a key moment we are about to call the handler, register state is |
| * as follows- |
| * |
| * D0Re0 - Handler vector (SigNum<<TBID_SIGNUM_S) |
| * D0Ar2 - TXMASKI:TBICTX_CRIT_BIT with optional CBUF and PRIV bits |
| * D1Ar3 - SigNum |
| * D0Ar4 - State read from TXSTATI |
| * D1Ar5 - Inst for SWITCH trigger case only, otherwise undefined |
| * D0Ar6 - pTBI |
| */ |
| ___TBIBoingVec: |
| ADD D0Re0,D0Re0,#TBI_fnSigs /* Offset into signal table */ |
| GETD D1Re0,[D0Ar6+D0Re0] /* Get address for Handler */ |
| /* |
| * Call handler at interrupt level, when it returns simply resume execution |
| * of state indicated by D1Re0. |
| */ |
| MOV D1Ar1,A0FrP /* Pass in pCtx */ |
| CALLR D1RtP,___TBIBoingRTH /* Use RTH to invoke handler */ |
| |
| /* |
| * Perform critical state restore and execute background thread. |
| * |
| * A0FrP - is pointer to TBICTX structure to resume |
| * D0Re0 - contains additional TXMASKI triggers |
| */ |
| .text |
| .balign 4 |
| #ifdef BOOTROM |
| .global ___TBIResume |
| #endif |
| ___TBIResume: |
| /* |
| * New META IP method |
| */ |
| RTH /* Go to interrupt level */ |
| MOV D0Ar4,TXMASKI /* Read TXMASKI */ |
| OR TXMASKI,D0Ar4,D0Re0 /* -Write-Modify TXMASKI */ |
| GETL D0Re0,D1Re0,[A0FrP+#TBICTX_Flags]/* Get Flags:SaveMask, CurrPC */ |
| MOV A0StP,A0FrP /* Position stack pointer */ |
| MOV D0Ar2,TXPOLLI /* Read pending triggers */ |
| MOV PCX,D1Re0 /* Set resumption PC */ |
| TST D0Ar2,#0xFFFF /* Any pending triggers? */ |
| BNZ ___TBIBoingWait /* Yes: Go for triggers */ |
| TSTT D0Re0,#TBICTX_WAIT_BIT /* Do we WAIT anyway? */ |
| BNZ ___TBIBoingWait /* Yes: Go for triggers */ |
| LSLS D1Ar5,D0Re0,#1 /* Test XCBF (MI) & PRIV (CS)? */ |
| ADD D1Re0,A0FrP,#TBICTX_CurrRPT /* Address CT save area */ |
| ADD A0StP,A0FrP,#TBICTX_DX+(8*1) /* Address DX.1 save area */ |
| MGETL A0.2,A0.3,[D1Re0] /* Get CT reg states */ |
| MOV D1Ar3,A1.3 /* Copy old TXDIVTIME */ |
| BPL ___TBIResCrit /* No: Skip logic */ |
| ADD D0Ar4,A0FrP,#TBICTX_BYTES /* Source is after TBICTX */ |
| ANDST D1Ar3,D1Ar3,#HI(TXDIVTIME_RPMASK_BITS)/* !Z if RPDIRTY */ |
| MGETL D0.5,D0.6,[D0Ar4] /* Read Catch state */ |
| MOV TXCATCH0,D0.5 /* Restore TXCATCHn */ |
| MOV TXCATCH1,D1.5 |
| MOV TXCATCH2,D0.6 |
| MOV TXCATCH3,D1.6 |
| BZ ___TBIResCrit |
| MOV D0Ar2,#(1*8) |
| LSRS D1Ar3,D1Ar3,#TXDIVTIME_RPMASK_S+1 /* 2nd RPMASK bit -> bit 0 */ |
| ADD RA,D0Ar4,#(0*8) /* Re-read read pipeline */ |
| ADDNZ RA,D0Ar4,D0Ar2 /* If Bit 0 set issue RA */ |
| LSRS D1Ar3,D1Ar3,#2 /* Bit 1 -> C, Bit 2 -> Bit 0 */ |
| ADD D0Ar2,D0Ar2,#8 |
| ADDCS RA,D0Ar4,D0Ar2 /* If C issue RA */ |
| ADD D0Ar2,D0Ar2,#8 |
| ADDNZ RA,D0Ar4,D0Ar2 /* If Bit 0 set issue RA */ |
| LSRS D1Ar3,D1Ar3,#2 /* Bit 1 -> C, Bit 2 -> Bit 0 */ |
| ADD D0Ar2,D0Ar2,#8 |
| ADDCS RA,D0Ar4,D0Ar2 /* If C issue RA */ |
| ADD D0Ar2,D0Ar2,#8 |
| ADDNZ RA,D0Ar4,D0Ar2 /* If Bit 0 set issue RA */ |
| MOV TXDIVTIME,A1.3 /* Set RPDIRTY again */ |
| ___TBIResCrit: |
| LSLS D1Ar5,D0Re0,#1 /* Test XCBF (MI) & PRIV (CS)? */ |
| #ifdef TBI_1_4 |
| ANDT D1Ar5,D1Ar5,#(TBICTX_FPAC_BIT*2) |
| LSL D0Ar6,D1Ar5,#3 /* Convert FPAC into FPACTIVE */ |
| #endif |
| ANDMT D0Re0,D0Re0,#TBICTX_CBUF_BIT /* Keep CBUF bit from SaveMask */ |
| #ifdef TBI_1_4 |
| OR D0Re0,D0Re0,D0Ar6 /* Combine FPACTIVE with others */ |
| #endif |
| MGETL D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7,[A0StP] /* Restore DX */ |
| MOV TXRPT,A0.2 /* Restore CT regs */ |
| MOV TXBPOBITS,A1.2 |
| MOV TXMODE,A0.3 |
| BCC ___TBIBoingPCX /* Do non-PRIV wait! */ |
| MOV A1GblIGbP,A1GbP /* Save A1GbP too */ |
| MGETL A0StP,A0FrP,A0.2,A0.3 A0_4,[D1Re0] /* Restore AX regs */ |
| /* |
| * Wait for the first interrupt/exception trigger in a privilege mode system |
| * (interrupt stack area for current TASK to be pointed to by A0GblIStP |
| * or per_cpu__stack_save[hwthread_id]). |
| */ |
| MOV TXSTATUS,D0Re0 /* Restore flags */ |
| MOV D0Re0,TXPRIVEXT /* Set TXPRIVEXT_TXTOGGLEI_BIT */ |
| SUB D1Re0,D1Re0,#TBICTX_BYTES /* TBICTX is top of int stack */ |
| #ifdef TBX_PERCPU_SP_SAVE |
| SWAP D1Ar3,A1GbP |
| MOV D1Ar3,TXENABLE /* Which thread are we? */ |
| AND D1Ar3,D1Ar3,#TXENABLE_THREAD_BITS |
| LSR D1Ar3,D1Ar3,#TXENABLE_THREAD_S-2 |
| ADDT D1Ar3,D1Ar3,#HI(_per_cpu__stack_save) |
| ADD D1Ar3,D1Ar3,#LO(_per_cpu__stack_save) |
| SETD [D1Ar3],D1Re0 |
| SWAP D1Ar3,A1GbP |
| #else |
| MOV A0GblIStP, D1Re0 |
| #endif |
| OR D0Re0,D0Re0,#TXPRIVEXT_TXTOGGLEI_BIT |
| MOV TXPRIVEXT,D0Re0 /* Cannot set TXPRIVEXT if !priv */ |
| GETL D0Re0,D1Re0,[D1Re0+#TBICTX_DX] |
| RTI /* Wait for interrupt */ |
| /* |
| * Save initial interrupt state on A0GblIStP, switch to A0GblIStP if |
| * BOOTROM code, save and switch to [A1GbP] otherwise. |
| */ |
| ___TBIBoingPCXP: |
| #ifdef TBX_PERCPU_SP_SAVE |
| SWAP D1Ar3,A1GbP /* Get PRIV stack base */ |
| MOV D1Ar3,TXENABLE /* Which thread are we? */ |
| AND D1Ar3,D1Ar3,#TXENABLE_THREAD_BITS |
| LSR D1Ar3,D1Ar3,#TXENABLE_THREAD_S-2 |
| ADDT D1Ar3,D1Ar3,#HI(_per_cpu__stack_save) |
| ADD D1Ar3,D1Ar3,#LO(_per_cpu__stack_save) |
| GETD D1Ar3,[D1Ar3] |
| #else |
| SWAP D1Ar3,A0GblIStP /* Get PRIV stack base */ |
| #endif |
| SETL [D1Ar3+#TBICTX_DX],D0Re0,D1Re0 /* Save key registers */ |
| MOV D0Re0,TXPRIVEXT /* Clear TXPRIVEXT_TXTOGGLEI_BIT */ |
| ADD D1Re0,D1Ar3,#TBICTX_AX /* Address AX save area */ |
| ANDMB D0Re0,D0Re0,#0xFFFF-TXPRIVEXT_TXTOGGLEI_BIT |
| MOV TXPRIVEXT,D0Re0 /* Cannot set TXPRIVEXT if !priv */ |
| MOV D0Re0,TXSTATUS /* Read TXSTATUS into D0Re0 */ |
| MOV TXSTATUS,#0 /* Clear TXSTATUS */ |
| MSETL [D1Re0],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX critical regs */ |
| MOV A0StP,D1Ar3 /* Switch stacks */ |
| #ifdef TBX_PERCPU_SP_SAVE |
| MOV D1Ar3,A1GbP /* Get D1Ar2 back */ |
| #else |
| MOV D1Ar3,A0GblIStP /* Get D1Ar2 back */ |
| #endif |
| ORT D0Re0,D0Re0,#TBICTX_PRIV_BIT /* Add PRIV to TXSTATUS */ |
| MOV A1GbP,A1GblIGbP /* Restore A1GbP */ |
| B ___TBIBoing /* Enter common handler code */ |
| /* |
| * At this point we know it's a background HALT case we are handling. |
| * The restored TXSTATUS always needs to have zero in the reason bits. |
| */ |
| ___TBIBoingHalt: |
| MOV D0Ar4,TXMASKI /* Get interrupt mask */ |
| ANDST D0Re0,D0Re0,#HI(TXSTATUS_MAJOR_HALT_BITS+TXSTATUS_MEM_FAULT_BITS) |
| AND TXMASKI,D0Ar4,#TXSTATI_BGNDHALT_BIT /* Only allow HALTs */ |
| AND D0Ar4,D0Ar4,#0xFFFF-TXSTATI_BGNDHALT_BIT /* What ints are off? */ |
| OR D0Ar2,D0Ar2,D0Ar4 /* Set TBIRES.Sig.TrigMask */ |
| MOV D0Ar4,#TXSTATI_BGNDHALT_BIT /* This was the trigger state */ |
| LSR D1Ar3,D0Re0,#TXSTATUS_MAJOR_HALT_S |
| MOV D0Re0,#TBID_SIGNUM_XXF<<TBID_SIGNUM_S |
| BNZ ___TBIBoingVec /* Jump to XXF exception handler */ |
| /* |
| * Only the SWITCH cases are left, PCX must be valid |
| */ |
| #ifdef TBI_1_4 |
| MOV D1Ar5,TXPRIVEXT |
| TST D1Ar5,#TXPRIVEXT_MINIMON_BIT |
| LSR D1Ar3,D1Ar1,#1 /* Shift needed for MINIM paths (fill stall) */ |
| BZ $Lmeta /* If META only, skip */ |
| TSTT D1Ar1,#HI(0x00800000) |
| ANDMT D1Ar3,D1Ar3,#HI(0x007FFFFF >> 1)/* Shifted mask for large MINIM */ |
| ANDT D1Ar1,D1Ar1,#HI(0xFFE00000) /* Static mask for small MINIM */ |
| BZ $Llarge_minim /* If large MINIM */ |
| $Lsmall_minim: |
| TSTT D1Ar3,#HI(0x00100000 >> 1) |
| ANDMT D1Ar3,D1Ar3,#HI(0x001FFFFF >> 1)/* Correct shifted mask for large MINIM */ |
| ADDZ D1Ar1,D1Ar1,D1Ar3 /* If META rgn, add twice to undo LSR #1 */ |
| B $Lrecombine |
| $Llarge_minim: |
| ANDST D1Ar1,D1Ar1,#HI(0xFF800000) /* Correct static mask for small MINIM */ |
| /* Z=0 (Cannot place code at NULL) */ |
| $Lrecombine: |
| ADD D1Ar1,D1Ar1,D1Ar3 /* Combine static and shifted parts */ |
| $Lmeta: |
| GETW D1Ar5,[D1Ar1++] /* META: lo-16, MINIM: lo-16 (all-16 if short) */ |
| GETW D1Ar3,[D1Ar1] /* META: hi-16, MINIM: hi-16 (only if long) */ |
| MOV D1Re0,D1Ar5 |
| XOR D1Re0,D1Re0,#0x4000 |
| LSLSNZ D1Re0,D1Re0,#(32-14) /* MINIM: If long C=0, if short C=1 */ |
| LSLCC D1Ar3,D1Ar3,#16 /* META/MINIM long: Move hi-16 up */ |
| LSLCS D1Ar3,D1Ar5,#16 /* MINIM short: Dup all-16 */ |
| ADD D1Ar5,D1Ar5,D1Ar3 /* ALL: Combine both 16-bit parts */ |
| #else |
| GETD D1Ar5,[D1Ar1] /* Read instruction for switch */ |
| #endif |
| LSR D1Ar3,D1Ar5,#22 /* Convert into signal number */ |
| AND D1Ar3,D1Ar3,#TBID_SIGNUM_SW3-TBID_SIGNUM_SW0 |
| LSL D0Re0,D1Ar3,#TBID_SIGNUM_S /* Generate offset from SigNum */ |
| B ___TBIBoingVec /* Jump to switch handler */ |
| /* |
| * Exit from TBIASyncTrigger call |
| */ |
| ___TBIBoingExit: |
| GETL D0FrT,D1RtP,[A0FrP++] /* Restore state from frame */ |
| SUB A0StP,A0FrP,#8 /* Unwind stack */ |
| MOV A0FrP,D0FrT /* Last memory read completes */ |
| MOV PC,D1RtP /* Return to caller */ |
| #endif /* ifdef CODE_USES_BOOTROM */ |
| .size ___TBIResume,.-___TBIResume |
| |
| #ifndef BOOTROM |
| /* |
| * void __TBIASyncResume( TBIRES State ) |
| */ |
| .text |
| .balign 4 |
| .global ___TBIASyncResume |
| .type ___TBIASyncResume,function |
| ___TBIASyncResume: |
| /* |
| * Perform CRIT|SOFT state restore and execute background thread. |
| */ |
| MOV D1Ar3,D1Ar1 /* Restore this context */ |
| MOV D0Re0,D0Ar2 /* Carry in additional triggers */ |
| /* Reserve space for TBICTX */ |
| ADD D1Ar3,D1Ar3,#TBICTX_BYTES+(CATCH_ENTRY_BYTES*CATCH_ENTRIES) |
| MOV A0StP,D1Ar3 /* Enter with protection of */ |
| MOV A0FrP,D1Ar1 /* TBICTX on our stack */ |
| #ifdef CODE_USES_BOOTROM |
| MOVT D1Ar1,#HI(LINCORE_BASE) |
| JUMP D1Ar1,#0xA4 |
| #else |
| B ___TBIResume |
| #endif |
| .size ___TBIASyncResume,.-___TBIASyncResume |
| #endif /* ifndef BOOTROM */ |
| |
| /* |
| * End of tbipcx.S |
| */ |