1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
4  */
5 
6 #ifndef __ASM_TLB_MMU_V1_H__
7 #define __ASM_TLB_MMU_V1_H__
8 
9 #include <asm/mmu.h>
10 
11 #if defined(__ASSEMBLY__) && (CONFIG_ARC_MMU_VER == 1)
12 
13 .macro TLB_WRITE_HEURISTICS
14 
15 #define JH_HACK1
16 #undef JH_HACK2
17 #undef JH_HACK3
18 
19 #ifdef JH_HACK3
20 ; Calculate set index for 2-way MMU
21 ; -avoiding use of GetIndex from MMU
22 ;   and its unpleasant LFSR pseudo-random sequence
23 ;
24 ; r1 = TLBPD0 from TLB_RELOAD above
25 ;
26 ; -- jh_ex_way_set not cleared on startup
27 ;    didn't want to change setup.c
28 ;    hence extra instruction to clean
29 ;
30 ; -- should be in cache since in same line
31 ;    as r0/r1 saves above
32 ;
33 ld  r0,[jh_ex_way_sel]  ; victim pointer
34 and r0,r0,1         ; clean
35 xor.f   r0,r0,1         ; flip
36 st  r0,[jh_ex_way_sel]  ; store back
37 asr r0,r1,12        ; get set # <<1, note bit 12=R=0
38 or.nz   r0,r0,1         ; set way bit
39 and r0,r0,0xff      ; clean
40 sr  r0,[ARC_REG_TLBINDEX]
41 #endif
42 
43 #ifdef JH_HACK2
44 ; JH hack #2
45 ;  Faster than hack #1 in non-thrash case, but hard-coded for 2-way MMU
46 ;  Slower in thrash case (where it matters) because more code is executed
47 ;  Inefficient due to two-register paradigm of this miss handler
48 ;
49 /* r1 = data TLBPD0 at this point */
50 lr      r0,[eret]               /* instruction address */
51 xor     r0,r0,r1                /* compare set #       */
52 and.f   r0,r0,0x000fe000        /* 2-way MMU mask      */
53 bne     88f                     /* not in same set - no need to probe */
54 
55 lr      r0,[eret]               /* instruction address */
56 and     r0,r0,PAGE_MASK         /* VPN of instruction address */
57 ; lr  r1,[ARC_REG_TLBPD0]     /* Data VPN+ASID - already in r1 from TLB_RELOAD*/
58 and     r1,r1,0xff              /* Data ASID */
59 or      r0,r0,r1                /* Instruction address + Data ASID */
60 
61 lr      r1,[ARC_REG_TLBPD0]     /* save TLBPD0 containing data TLB*/
62 sr      r0,[ARC_REG_TLBPD0]     /* write instruction address to TLBPD0 */
63 sr      TLBProbe, [ARC_REG_TLBCOMMAND] /* Look for instruction */
64 lr      r0,[ARC_REG_TLBINDEX]   /* r0 = index where instruction is, if at all */
65 sr      r1,[ARC_REG_TLBPD0]     /* restore TLBPD0 */
66 
67 xor     r0,r0,1                 /* flip bottom bit of data index */
68 b.d     89f
69 sr      r0,[ARC_REG_TLBINDEX]   /* and put it back */
70 88:
71 sr  TLBGetIndex, [ARC_REG_TLBCOMMAND]
72 89:
73 #endif
74 
75 #ifdef JH_HACK1
76 ;
77 ; Always checks whether instruction will be kicked out by dtlb miss
78 ;
79 mov_s   r3, r1                  ; save PD0 prepared by TLB_RELOAD in r3
80 lr      r0,[eret]               /* instruction address */
81 and     r0,r0,PAGE_MASK         /* VPN of instruction address */
82 bmsk    r1,r3,7                 /* Data ASID, bits 7-0 */
83 or_s    r0,r0,r1                /* Instruction address + Data ASID */
84 
85 sr      r0,[ARC_REG_TLBPD0]     /* write instruction address to TLBPD0 */
86 sr      TLBProbe, [ARC_REG_TLBCOMMAND] /* Look for instruction */
87 lr      r0,[ARC_REG_TLBINDEX]   /* r0 = index where instruction is, if at all */
88 sr      r3,[ARC_REG_TLBPD0]     /* restore TLBPD0 */
89 
90 sr      TLBGetIndex, [ARC_REG_TLBCOMMAND]
91 lr      r1,[ARC_REG_TLBINDEX]   /* r1 = index where MMU wants to put data */
92 cmp     r0,r1                   /* if no match on indices, go around */
93 xor.eq  r1,r1,1                 /* flip bottom bit of data index */
94 sr      r1,[ARC_REG_TLBINDEX]   /* and put it back */
95 #endif
96 
97 .endm
98 
99 #endif
100 
101 #endif
102