|
@@ -3,74 +3,77 @@
|
|
|
* shared by l.s and rebootcode.s
|
|
|
*/
|
|
|
|
|
|
-TEXT cacheiinv(SB), 1, $-4 /* I invalidate */
|
|
|
+TEXT cacheiinv(SB), $-4 /* I invalidate */
|
|
|
MOVW $0, R0
|
|
|
MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall /* ok on cortex */
|
|
|
BARRIERS
|
|
|
RET
|
|
|
|
|
|
/*
|
|
|
- * set/way operators
|
|
|
+ * set/way operators, passed a suitable set/way value in R0.
|
|
|
*/
|
|
|
-
|
|
|
-TEXT cachedwb_sw(SB), 1, $-4
|
|
|
+TEXT cachedwb_sw(SB), $-4
|
|
|
MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEsi
|
|
|
RET
|
|
|
|
|
|
-TEXT cachedwbinv_sw(SB), 1, $-4
|
|
|
+TEXT cachedwbinv_sw(SB), $-4
|
|
|
MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEsi
|
|
|
RET
|
|
|
|
|
|
-TEXT cachedinv_sw(SB), 1, $-4
|
|
|
+TEXT cachedinv_sw(SB), $-4
|
|
|
MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvd), CpCACHEsi
|
|
|
RET
|
|
|
|
|
|
/* set cache size select */
|
|
|
-TEXT setcachelvl(SB), 1, $-4
|
|
|
+TEXT setcachelvl(SB), $-4
|
|
|
MCR CpSC, CpIDcssel, R0, C(CpID), C(CpIDid), 0
|
|
|
BARRIERS
|
|
|
RET
|
|
|
|
|
|
/* return cache sizes */
|
|
|
-TEXT getwayssets(SB), 1, $-4
|
|
|
+TEXT getwayssets(SB), $-4
|
|
|
MRC CpSC, CpIDcsize, R0, C(CpID), C(CpIDid), 0
|
|
|
RET
|
|
|
|
|
|
/*
|
|
|
- * l1 cache operations
|
|
|
+ * l1 cache operations.
|
|
|
+ * l1 and l2 ops are intended to be called from C, thus need save no
|
|
|
+ * caller's regs, only those we need to preserve across calls.
|
|
|
*/
|
|
|
|
|
|
-TEXT cachedwb(SB), 1, $-4
|
|
|
+TEXT cachedwb(SB), $-4
|
|
|
MOVW.W R14, -8(R13)
|
|
|
MOVW $cachedwb_sw(SB), R0
|
|
|
MOVW $1, R8
|
|
|
BL cacheall(SB)
|
|
|
MOVW.P 8(R13), R15
|
|
|
|
|
|
-TEXT cachedwbinv(SB), 1, $-4
|
|
|
+TEXT cachedwbinv(SB), $-4
|
|
|
MOVW.W R14, -8(R13)
|
|
|
MOVW $cachedwbinv_sw(SB), R0
|
|
|
MOVW $1, R8
|
|
|
BL cacheall(SB)
|
|
|
MOVW.P 8(R13), R15
|
|
|
|
|
|
-TEXT cachedinv(SB), 1, $-4
|
|
|
+TEXT cachedinv(SB), $-4
|
|
|
MOVW.W R14, -8(R13)
|
|
|
MOVW $cachedinv_sw(SB), R0
|
|
|
MOVW $1, R8
|
|
|
BL cacheall(SB)
|
|
|
MOVW.P 8(R13), R15
|
|
|
|
|
|
-TEXT cacheuwbinv(SB), 1, $-4
|
|
|
+TEXT cacheuwbinv(SB), $-4
|
|
|
MOVM.DB.W [R14], (R13) /* save lr on stack */
|
|
|
MOVW CPSR, R1
|
|
|
ORR $(PsrDirq|PsrDfiq), R1, R0
|
|
|
MOVW R0, CPSR /* splhi */
|
|
|
BARRIERS
|
|
|
+ MOVM.DB.W [R1], (R13) /* save R1 on stack */
|
|
|
|
|
|
BL cachedwbinv(SB)
|
|
|
BL cacheiinv(SB)
|
|
|
|
|
|
+ MOVM.IA.W (R13), [R1] /* restore R1 */
|
|
|
MOVW R1, CPSR
|
|
|
BARRIERS
|
|
|
MOVM.IA.W (R13), [R14] /* restore lr */
|
|
@@ -80,40 +83,38 @@ TEXT cacheuwbinv(SB), 1, $-4
|
|
|
* l2 cache operations
|
|
|
*/
|
|
|
|
|
|
-TEXT l2cacheuwb(SB), 1, $-4
|
|
|
+TEXT l2cacheuwb(SB), $-4
|
|
|
MOVW.W R14, -8(R13)
|
|
|
MOVW $cachedwb_sw(SB), R0
|
|
|
MOVW $2, R8
|
|
|
BL cacheall(SB)
|
|
|
MOVW.P 8(R13), R15
|
|
|
|
|
|
-TEXT l2cacheuwbinv(SB), 1, $-4
|
|
|
+TEXT l2cacheuwbinv(SB), $-4
|
|
|
MOVW.W R14, -8(R13)
|
|
|
MOVW CPSR, R1
|
|
|
ORR $(PsrDirq|PsrDfiq), R1, R0
|
|
|
MOVW R0, CPSR /* splhi */
|
|
|
BARRIERS
|
|
|
+ MOVM.DB.W [R1], (R13) /* save R1 on stack */
|
|
|
|
|
|
MOVW $cachedwbinv_sw(SB), R0
|
|
|
MOVW $2, R8
|
|
|
BL cacheall(SB)
|
|
|
BL l2cacheuinv(SB)
|
|
|
|
|
|
+ MOVM.IA.W (R13), [R1] /* restore R1 */
|
|
|
MOVW R1, CPSR
|
|
|
BARRIERS
|
|
|
MOVW.P 8(R13), R15
|
|
|
|
|
|
-TEXT l2cacheuinv(SB), 1, $-4
|
|
|
+TEXT l2cacheuinv(SB), $-4
|
|
|
MOVW.W R14, -8(R13)
|
|
|
MOVW $cachedinv_sw(SB), R0
|
|
|
MOVW $2, R8
|
|
|
BL cacheall(SB)
|
|
|
MOVW.P 8(R13), R15
|
|
|
|
|
|
-/*
|
|
|
- * initial translation by 5c, then massaged by hand.
|
|
|
- */
|
|
|
-
|
|
|
/*
|
|
|
* these shift values are for the Cortex-A8 L1 cache (A=2, L=6) and
|
|
|
* the Cortex-A8 L2 cache (A=3, L=6).
|
|
@@ -125,21 +126,16 @@ TEXT l2cacheuinv(SB), 1, $-4
|
|
|
#define L2WAYSH 29
|
|
|
#define L2SETSH 6
|
|
|
|
|
|
-#define VARSTACK (8*4) /* generous stack space for local variables */
|
|
|
-
|
|
|
-/* first argument (in R0) is the function to call in the innermost loop */
|
|
|
-/* second argument (in R8 when called from assembler) is cache level */
|
|
|
-TEXT cacheall+0(SB), 1, $-4
|
|
|
-// MOVW lvl+4(FP), R8 /* cache level */
|
|
|
- MOVM.DB.W [R14,R1-R8], (R13) /* save regs on stack */
|
|
|
+/*
|
|
|
+ * callers are assumed to be the above l1 and l2 ops.
|
|
|
+ * R0 is the function to call in the innermost loop.
|
|
|
+ * R8 is the cache level (one-origin: 1 or 2).
|
|
|
+ *
|
|
|
+ * initial translation by 5c, then massaged by hand.
|
|
|
+ */
|
|
|
+TEXT cacheall+0(SB), $-4
|
|
|
MOVW R0, R1 /* save argument for inner loop in R1 */
|
|
|
-
|
|
|
- MOVW CPSR, R0
|
|
|
- MOVM.DB.W [R0], (R13) /* push CPSR */
|
|
|
-
|
|
|
- ORR $(PsrDirq|PsrDfiq), R0
|
|
|
- MOVW R0, CPSR /* splhi */
|
|
|
- BARRIERS
|
|
|
+ SUB $1, R8 /* convert cache level to zero origin */
|
|
|
|
|
|
/* we may not have the MMU on yet, so map R1 to PC's space */
|
|
|
BIC $KSEGM, R1 /* strip segment from address */
|
|
@@ -154,89 +150,61 @@ TEXT cacheall+0(SB), 1, $-4
|
|
|
MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait
|
|
|
BARRIERS
|
|
|
|
|
|
- SUB $1, R8, R0 /* R0 = cache - 1 */
|
|
|
- SLL $1, R0 /* R0 = (cache - 1) << 1 */
|
|
|
-
|
|
|
- /* set cache size select */
|
|
|
- MCR CpSC, CpIDcssel, R0, C(CpID), C(CpIDid), 0
|
|
|
+ MOVW CPSR, R2
|
|
|
+ MOVM.DB.W [R2,R14], (SP) /* save regs on stack */
|
|
|
+ ORR $(PsrDirq|PsrDfiq), R2
|
|
|
+ MOVW R2, CPSR /* splhi to make entire op atomic */
|
|
|
BARRIERS
|
|
|
|
|
|
+ /* get cache sizes */
|
|
|
+ SLL $1, R8, R0 /* R0 = (cache - 1) << 1 */
|
|
|
+ MCR CpSC, CpIDcssel, R0, C(CpID), C(CpIDid), 0 /* set cache size select */
|
|
|
+ BARRIERS
|
|
|
MRC CpSC, CpIDcsize, R0, C(CpID), C(CpIDid), 0 /* get cache sizes */
|
|
|
|
|
|
/* compute # of ways and sets for this cache level */
|
|
|
SRA $3, R0, R5 /* R5 (ways) = R0 >> 3 */
|
|
|
AND $1023, R5 /* R5 = (R0 >> 3) & MASK(10) */
|
|
|
- ADD $1, R5 /* R5 = ((R0 >> 3) & MASK(10)) + 1 */
|
|
|
- MOVW R5, ways-20(SP) /* ways = ((R0 >> 3) & MASK(10)) + 1 */
|
|
|
+ ADD $1, R5 /* R5 (ways) = ((R0 >> 3) & MASK(10)) + 1 */
|
|
|
|
|
|
- SRA $13, R0, R3 /* R3 (sets) = R0 >> 13 */
|
|
|
- AND $32767, R3 /* R3 = (R0 >> 13) & MASK(15) */
|
|
|
- ADD $1, R3 /* R3 = ((R0 >> 13) & MASK(15)) + 1 */
|
|
|
- MOVW R3, sets-12(SP) /* sets = ((R0 >> 13) & MASK(15)) + 1 */
|
|
|
+ SRA $13, R0, R2 /* R2 = R0 >> 13 */
|
|
|
+ AND $32767, R2 /* R2 = (R0 >> 13) & MASK(15) */
|
|
|
+ ADD $1, R2 /* R2 (sets) = ((R0 >> 13) & MASK(15)) + 1 */
|
|
|
|
|
|
- /* force writes to stack out to dram */
|
|
|
- BARRIERS
|
|
|
- MOVW R13, R0
|
|
|
- SUB $VARSTACK, R0 /* move down past local variables (ways) */
|
|
|
- BIC $(CACHELINESZ-1), R0
|
|
|
- MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEse
|
|
|
- ADD $CACHELINESZ, R0
|
|
|
- MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEse
|
|
|
- ADD $CACHELINESZ, R0
|
|
|
- MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEse
|
|
|
- ADD $CACHELINESZ, R0
|
|
|
- MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEse
|
|
|
- BARRIERS
|
|
|
- MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait
|
|
|
- BARRIERS
|
|
|
+ /* precompute set/way shifts for inner loop */
|
|
|
+ CMP $0, R8 /* cache == 1? */
|
|
|
+ MOVW.EQ $L1WAYSH, R3 /* yes */
|
|
|
+ MOVW.EQ $L1SETSH, R4
|
|
|
+ MOVW.NE $L2WAYSH, R3 /* no */
|
|
|
+ MOVW.NE $L2SETSH, R4
|
|
|
|
|
|
/* iterate over ways */
|
|
|
MOVW $0, R7 /* R7: way */
|
|
|
- B midtest
|
|
|
-middle:
|
|
|
- ADD $1, R7 /* way++ */
|
|
|
-midtest:
|
|
|
- MOVW ways-20(SP), R2 /* R2: ways */
|
|
|
- CMP R2, R7 /* way >= ways? */
|
|
|
- BGE ret /* then done */
|
|
|
-
|
|
|
+outer:
|
|
|
/* iterate over sets */
|
|
|
MOVW $0, R6 /* R6: set */
|
|
|
- B intest
|
|
|
inner:
|
|
|
+ /* compute set/way register contents */
|
|
|
+ SLL R3, R7, R0 /* R0 = way << R3 (L?WAYSH) */
|
|
|
+ ORR R8<<1, R0 /* R0 = way << L?WAYSH | (cache - 1) << 1 */
|
|
|
+ ORR R6<<R4, R0 /* R0 = way<<L?WAYSH | (cache-1)<<1 |set<<R4 */
|
|
|
+
|
|
|
+ BL (R1) /* call set/way operation with R0 */
|
|
|
+
|
|
|
ADD $1, R6 /* set++ */
|
|
|
-intest:
|
|
|
- MOVW sets-12(SP), R5 /* R5: sets */
|
|
|
- CMP R5, R6 /* set >= sets? */
|
|
|
- BGE middle /* then back to reinit of previous loop */
|
|
|
+ CMP R2, R6 /* set >= sets? */
|
|
|
+ BLT inner /* no, do next set */
|
|
|
|
|
|
- /* compute set/way register contents */
|
|
|
- SUB $1, R8, R4 /* R4 = cache - 1 */
|
|
|
- CMP $1, R8 /* cache == 1? */
|
|
|
- SLL.EQ $L1WAYSH, R7, R2 /* yes: R2 = way << L1WAYSH */
|
|
|
- SLL.NE $L2WAYSH, R7, R2 /* no: R2 = way << L2WAYSH */
|
|
|
- ORR R4<<1, R2, R4 /* R4 = way << L?WAYSH | (cache - 1) << 1 */
|
|
|
- ORR.EQ R6<<L1SETSH, R4, R0 /* R0=way<<L1WAYSH|(cache-1)<<1|set<<L1SETSH */
|
|
|
- ORR.NE R6<<L2SETSH, R4, R0 /* R0=way<<L2WAYSH|(cache-1)<<1|set<<L2SETSH */
|
|
|
-
|
|
|
- SUB $VARSTACK, R13 /* move sp down past local variables (ways) */
|
|
|
- /* must not use addresses relative to (SP) from here */
|
|
|
- BL (R1) /* call asm to do something with R0 */
|
|
|
- BARRIERS /* make sure it has executed */
|
|
|
- ADD $VARSTACK, R13 /* restore sp */
|
|
|
- /* may again use addresses relative to (SP) from here */
|
|
|
-
|
|
|
- B inner
|
|
|
-
|
|
|
-ret:
|
|
|
- /* drain write buffers */
|
|
|
- BARRIERS
|
|
|
- MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait
|
|
|
+ ADD $1, R7 /* way++ */
|
|
|
+ CMP R5, R7 /* way >= ways? */
|
|
|
+ BLT outer /* no, do next way */
|
|
|
+
|
|
|
+ MOVM.IA.W (SP), [R2,R14] /* restore regs */
|
|
|
+ MOVW R2, CPSR /* splx */
|
|
|
BARRIERS
|
|
|
|
|
|
- MOVM.IA.W (R13), [R0] /* pop CPSR */
|
|
|
- MOVM.IA.W (R13), [R14,R1-R8] /* restore regs */
|
|
|
- MOVW R0, CPSR
|
|
|
+ /* drain write buffers */
|
|
|
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait
|
|
|
BARRIERS
|
|
|
RET
|
|
|
|