James Hogan | 027f891 | 2012-09-21 17:40:06 +0100 | [diff] [blame] | 1 | /* |
| 2 | * tbicore.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 | * Core functions needed to support use of the thread binary interface for META |
| 11 | * processors |
| 12 | */ |
| 13 | |
| 14 | .file "tbicore.S" |
| 15 | /* Get data structures and defines from the TBI C header */ |
| 16 | #include <asm/metag_mem.h> |
| 17 | #include <asm/metag_regs.h> |
| 18 | #include <asm/tbx.h> |
| 19 | |
| 20 | .data |
| 21 | .balign 8 |
| 22 | .global ___pTBISegs |
| 23 | .type ___pTBISegs,object |
| 24 | ___pTBISegs: |
| 25 | .quad 0 /* Segment list pointer with it's */ |
| 26 | .size ___pTBISegs,.-___pTBISegs |
| 27 | /* own id or spin-lock location */ |
| 28 | /* |
| 29 | * Return ___pTBISegs value specific to privilege level - not very complicated |
| 30 | * at the moment |
| 31 | * |
| 32 | * Register Usage: D0Re0 is the result, D1Re0 is used as a scratch |
| 33 | */ |
| 34 | .text |
| 35 | .balign 4 |
| 36 | .global ___TBISegList |
| 37 | .type ___TBISegList,function |
| 38 | ___TBISegList: |
| 39 | MOVT A1LbP,#HI(___pTBISegs) |
| 40 | ADD A1LbP,A1LbP,#LO(___pTBISegs) |
| 41 | GETL D0Re0,D1Re0,[A1LbP] |
| 42 | MOV PC,D1RtP |
| 43 | .size ___TBISegList,.-___TBISegList |
| 44 | |
| 45 | /* |
| 46 | * Search the segment list for a match given Id, pStart can be NULL |
| 47 | * |
| 48 | * Register Usage: D1Ar1 is pSeg, D0Ar2 is Id, D0Re0 is the result |
| 49 | * D0Ar4, D1Ar3 are used as a scratch |
| 50 | * NB: The PSTAT bit if Id in D0Ar2 may be toggled |
| 51 | */ |
| 52 | .text |
| 53 | .balign 4 |
| 54 | .global ___TBIFindSeg |
| 55 | .type ___TBIFindSeg,function |
| 56 | ___TBIFindSeg: |
| 57 | MOVT A1LbP,#HI(___pTBISegs) |
| 58 | ADD A1LbP,A1LbP,#LO(___pTBISegs) |
| 59 | GETL D1Ar3,D0Ar4,[A1LbP] /* Read segment list head */ |
| 60 | MOV D0Re0,TXSTATUS /* What priv level are we at? */ |
| 61 | CMP D1Ar1,#0 /* Is pStart provided? */ |
| 62 | /* Disable privilege adaption for now */ |
| 63 | ANDT D0Re0,D0Re0,#0 /*HI(TXSTATUS_PSTAT_BIT) ; Is PSTAT set? Zero if not */ |
| 64 | LSL D0Re0,D0Re0,#(TBID_PSTAT_S-TXSTATUS_PSTAT_S) |
| 65 | XOR D0Ar2,D0Ar2,D0Re0 /* Toggle Id PSTAT if privileged */ |
| 66 | MOVNZ D1Ar3,D1Ar1 /* Use pStart if provided */ |
| 67 | $LFindSegLoop: |
| 68 | ADDS D0Re0,D1Ar3,#0 /* End of list? Load result into D0Re0 */ |
| 69 | MOVZ PC,D1RtP /* If result is NULL we leave */ |
| 70 | GETL D1Ar3,D0Ar4,[D1Ar3] /* Read pLink and Id */ |
| 71 | CMP D0Ar4,D0Ar2 /* Does it match? */ |
| 72 | BNZ $LFindSegLoop /* Loop if there is no match */ |
| 73 | TST D0Re0,D0Re0 /* Clear zero flag - we found it! */ |
| 74 | MOV PC,D1RtP /* Return */ |
| 75 | .size ___TBIFindSeg,.-___TBIFindSeg |
| 76 | |
| 77 | /* Useful offsets to encode the lower bits of the lock/unlock addresses */ |
| 78 | #define UON (LINSYSEVENT_WR_ATOMIC_LOCK & 0xFFF8) |
| 79 | #define UOFF (LINSYSEVENT_WR_ATOMIC_UNLOCK & 0xFFF8) |
| 80 | |
| 81 | /* |
| 82 | * Perform a whole spin-lock sequence as used by the TBISignal routine |
| 83 | * |
| 84 | * Register Usage: D1Ar1 is pLock, D0Ar2 is Mask, D0Re0 is the result |
| 85 | * (All other usage due to ___TBIPoll - D0Ar6, D1Re0) |
| 86 | */ |
| 87 | .text |
| 88 | .balign 4 |
| 89 | .global ___TBISpin |
| 90 | .type ___TBISpin,function |
| 91 | ___TBISpin: |
| 92 | SETL [A0StP++],D0FrT,D1RtP /* Save our return address */ |
| 93 | ORS D0Re0,D0Re0,#1 /* Clear zero flag */ |
| 94 | MOV D1RtP,PC /* Setup return address to form loop */ |
| 95 | $LSpinLoop: |
| 96 | BNZ ___TBIPoll /* Keep repeating if fail to set */ |
| 97 | GETL D0FrT,D1RtP,[--A0StP] /* Restore return address */ |
| 98 | MOV PC,D1RtP /* Return */ |
| 99 | .size ___TBISpin,.-___TBISpin |
| 100 | |
| 101 | /* |
| 102 | * Perform an attempt to gain access to a spin-lock and set some bits |
| 103 | * |
| 104 | * Register Usage: D1Ar1 is pLock, D0Ar2 is Mask, D0Re0 is the result |
| 105 | * !!On return Zero flag is SET if we are sucessfull!! |
| 106 | * A0.3 is used to hold base address of system event region |
| 107 | * D1Re0 use to hold TXMASKI while interrupts are off |
| 108 | */ |
| 109 | .text |
| 110 | .balign 4 |
| 111 | .global ___TBIPoll |
| 112 | .type ___TBIPoll,function |
| 113 | ___TBIPoll: |
| 114 | MOV D1Re0,#0 /* Prepare to disable ints */ |
| 115 | MOVT A0.3,#HI(LINSYSEVENT_WR_ATOMIC_LOCK) |
| 116 | SWAP D1Re0,TXMASKI /* Really stop ints */ |
| 117 | LOCK2 /* Gain all locks */ |
| 118 | SET [A0.3+#UON],D1RtP /* Stop shared memory access too */ |
| 119 | DCACHE [D1Ar1],A0.3 /* Flush Cache line */ |
| 120 | GETD D0Re0,[D1Ar1] /* Get new state from memory or hit */ |
| 121 | DCACHE [D1Ar1],A0.3 /* Flush Cache line */ |
| 122 | GETD D0Re0,[D1Ar1] /* Get current state */ |
| 123 | TST D0Re0,D0Ar2 /* Are we clear to send? */ |
| 124 | ORZ D0Re0,D0Re0,D0Ar2 /* Yes: So set bits and */ |
| 125 | SETDZ [D1Ar1],D0Re0 /* transmit new state */ |
| 126 | SET [A0.3+#UOFF],D1RtP /* Allow shared memory access */ |
| 127 | LOCK0 /* Release all locks */ |
| 128 | MOV TXMASKI,D1Re0 /* Allow ints */ |
| 129 | $LPollEnd: |
| 130 | XORNZ D0Re0,D0Re0,D0Re0 /* No: Generate zero result */ |
| 131 | MOV PC,D1RtP /* Return (NZ indicates failure) */ |
| 132 | .size ___TBIPoll,.-___TBIPoll |
| 133 | |
| 134 | /* |
| 135 | * End of tbicore.S |
| 136 | */ |