master
h 252 lines 7.11 KB
Raw
1 /*
2 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #ifndef HEXAGON_SYS_MACROS_H
8 #define HEXAGON_SYS_MACROS_H
9
10 /*
11 * Macro definitions for Hexagon system mode
12 */
13
14 #ifndef CONFIG_USER_ONLY
15
16 #include "system/physmem.h"
17
18 #ifdef QEMU_GENERATE
19 #define GET_SSR_FIELD(RES, FIELD) \
20 GET_FIELD(RES, FIELD, hex_t_sreg[HEX_SREG_SSR])
21 #else
22
23 #define GET_SSR_FIELD(FIELD, REGIN) \
24 (uint32_t)GET_FIELD(FIELD, REGIN)
25 #define GET_SYSCFG_FIELD(FIELD, REGIN) \
26 (uint32_t)GET_FIELD(FIELD, REGIN)
27 #define SET_SYSTEM_FIELD(ENV, REG, FIELD, VAL) \
28 do { \
29 HexagonCPU *_sf_cpu = env_archcpu(ENV); \
30 uint32_t regval; \
31 if ((REG) < HEX_SREG_GLB_START) { \
32 regval = (ENV)->t_sreg[(REG)]; \
33 } else { \
34 regval = _sf_cpu->globalregs ? \
35 hexagon_globalreg_read(_sf_cpu->globalregs, (REG), \
36 (ENV)->threadId) : 0; \
37 } \
38 fINSERT_BITS(regval, reg_field_info[FIELD].width, \
39 reg_field_info[FIELD].offset, (VAL)); \
40 if ((REG) < HEX_SREG_GLB_START) { \
41 (ENV)->t_sreg[(REG)] = regval; \
42 } else if (_sf_cpu->globalregs) { \
43 hexagon_globalreg_write(_sf_cpu->globalregs, (REG), regval, \
44 (ENV)->threadId); \
45 } \
46 } while (0)
47 #define SET_SSR_FIELD(ENV, FIELD, VAL) \
48 SET_SYSTEM_FIELD(ENV, HEX_SREG_SSR, FIELD, VAL)
49 #define SET_SYSCFG_FIELD(ENV, FIELD, VAL) \
50 SET_SYSTEM_FIELD(ENV, HEX_SREG_SYSCFG, FIELD, VAL)
51
52 #define CCR_FIELD_SET(ENV, FIELD) \
53 (!!GET_FIELD(FIELD, (ENV)->t_sreg[HEX_SREG_CCR]))
54
55 /*
56 * Direct-to-guest is not implemented yet, continuing would cause unexpected
57 * behavior, so we abort.
58 */
59 #define ASSERT_DIRECT_TO_GUEST_UNSET(ENV, EXCP) \
60 do { \
61 switch (EXCP) { \
62 case HEX_EVENT_TRAP0: \
63 g_assert(!CCR_FIELD_SET(ENV, CCR_GTE)); \
64 break; \
65 case HEX_EVENT_IMPRECISE: \
66 case HEX_EVENT_PRECISE: \
67 case HEX_EVENT_FPTRAP: \
68 g_assert(!CCR_FIELD_SET(ENV, CCR_GEE)); \
69 break; \
70 default: \
71 if ((EXCP) >= HEX_EVENT_INT0) { \
72 g_assert(!CCR_FIELD_SET(ENV, CCR_GIE)); \
73 } \
74 break; \
75 } \
76 } while (0)
77 #endif
78
79 #define fREAD_ELR() (env->t_sreg[HEX_SREG_ELR])
80
81 #define fLOAD_PHYS(NUM, SIZE, SIGN, SRC1, SRC2, DST) { \
82 const uintptr_t rs = ((unsigned long)(unsigned)(SRC1)) & 0x7ff; \
83 const uintptr_t rt = ((unsigned long)(unsigned)(SRC2)) << 11; \
84 const uintptr_t addr = rs + rt; \
85 physical_memory_read(addr, &DST, sizeof(uint32_t)); \
86 }
87
88 #define fPOW2_HELP_ROUNDUP(VAL) \
89 ((VAL) | \
90 ((VAL) >> 1) | \
91 ((VAL) >> 2) | \
92 ((VAL) >> 4) | \
93 ((VAL) >> 8) | \
94 ((VAL) >> 16))
95 #define fPOW2_ROUNDUP(VAL) (fPOW2_HELP_ROUNDUP((VAL) - 1) + 1)
96
97 #define fTRAP(TRAPTYPE, IMM) \
98 register_trap_exception(env, TRAPTYPE, IMM, PC)
99
100 #ifdef QEMU_GENERATE
101 #define fFRAMECHECK(ADDR, EA) gen_framecheck(ctx, ADDR, EA)
102 #endif
103
104 #define fVIRTINSN_SPSWAP(IMM, REG)
105 #define fVIRTINSN_GETIE(IMM, REG) { REG = 0xdeafbeef; }
106 #define fVIRTINSN_SETIE(IMM, REG)
107 #define fVIRTINSN_RTE(IMM, REG)
108 #define fGRE_ENABLED() \
109 GET_FIELD(CCR_GRE, env->t_sreg[HEX_SREG_CCR])
110 #define fTRAP1_VIRTINSN(IMM) \
111 (fGRE_ENABLED() && \
112 (((IMM) == 1) || ((IMM) == 3) || ((IMM) == 4) || ((IMM) == 6)))
113
114 /* Not modeled in qemu */
115
116 #define MARK_LATE_PRED_WRITE(RNUM)
117 #define fICINVIDX(REG)
118 #define fICKILL()
119 #define fDCKILL()
120 #define fL2KILL()
121 #define fL2UNLOCK()
122 #define fL2CLEAN()
123 #define fL2CLEANINV()
124 #define fL2CLEANPA(REG)
125 #define fL2CLEANINVPA(REG)
126 #define fL2CLEANINVIDX(REG)
127 #define fL2CLEANIDX(REG)
128 #define fL2INVIDX(REG)
129 #define fL2TAGR(INDEX, DST, DSTREG)
130 #define fL2UNLOCKA(VA) ((void) VA)
131 #define fL2TAGW(INDEX, PART2)
132 #define fDCCLEANIDX(REG)
133 #define fDCCLEANINVIDX(REG)
134
135 /* Always succeed: */
136 #define fL2LOCKA(EA, PDV, PDN) ((void) EA, PDV = 0xFF)
137 #define fCLEAR_RTE_EX() \
138 do { \
139 uint32_t tmp = env->t_sreg[HEX_SREG_SSR]; \
140 fINSERT_BITS(tmp, reg_field_info[SSR_EX].width, \
141 reg_field_info[SSR_EX].offset, 0); \
142 log_sreg_write(env, HEX_SREG_SSR, tmp, slot); \
143 } while (0)
144
145 #define fDCINVIDX(REG)
146 #define fDCINVA(REG) do { REG = REG; } while (0) /* Nothing to do in qemu */
147
148 #define fSET_TLB_LOCK() hex_tlb_lock(env);
149 #define fCLEAR_TLB_LOCK() hex_tlb_unlock(env);
150
151 #define fSET_K0_LOCK() hex_k0_lock(env);
152 #define fCLEAR_K0_LOCK() hex_k0_unlock(env);
153
154 #define fTLB_IDXMASK(INDEX) \
155 ((INDEX) & (fPOW2_ROUNDUP( \
156 fCAST4u(hexagon_tlb_get_num_entries(env_archcpu(env)->tlb))) - 1))
157
158 #define fTLB_NONPOW2WRAP(INDEX) \
159 (((INDEX) >= hexagon_tlb_get_num_entries(env_archcpu(env)->tlb)) ? \
160 ((INDEX) - hexagon_tlb_get_num_entries(env_archcpu(env)->tlb)) : \
161 (INDEX))
162
163
164 #define fTLBW(INDEX, VALUE) \
165 hex_tlbw(env, (INDEX), (VALUE))
166 #define fTLBW_EXTENDED(INDEX, VALUE) \
167 hex_tlbw(env, (INDEX), (VALUE))
168 #define fTLB_ENTRY_OVERLAP(VALUE) \
169 (hex_tlb_check_overlap(env, VALUE, -1) != -2)
170 #define fTLB_ENTRY_OVERLAP_IDX(VALUE) \
171 hex_tlb_check_overlap(env, VALUE, -1)
172 #define fTLBR(INDEX) \
173 hexagon_tlb_read(env_archcpu(env)->tlb, \
174 fTLB_NONPOW2WRAP(fTLB_IDXMASK(INDEX)))
175 #define fTLBR_EXTENDED(INDEX) \
176 hexagon_tlb_read(env_archcpu(env)->tlb, \
177 fTLB_NONPOW2WRAP(fTLB_IDXMASK(INDEX)))
178 #define fTLBP(TLBHI) \
179 hex_tlb_lookup(env, ((TLBHI) >> 12), ((TLBHI) << 12))
180 #define iic_flush_cache(p)
181
182 #define fIN_DEBUG_MODE(TNUM) ({ \
183 HexagonCPU *_cpu = env_archcpu(env); \
184 uint32_t _isdbst = _cpu->globalregs ? \
185 hexagon_globalreg_read(_cpu->globalregs, \
186 HEX_SREG_ISDBST, env->threadId) : 0; \
187 (GET_FIELD(ISDBST_DEBUGMODE, _isdbst) \
188 & (0x1 << (TNUM))) != 0; })
189
190 #define fIN_DEBUG_MODE_NO_ISDB(TNUM) false
191 #define fIN_DEBUG_MODE_WARN(TNUM) false
192
193 #ifdef QEMU_GENERATE
194
195 /*
196 * Read tags back as zero for now:
197 *
198 * tag value in RD[31:10] for 32k, RD[31:9] for 16k
199 */
200 #define fICTAGR(RS, RD, RD2) \
201 do { \
202 RD = ctx->zero; \
203 } while (0)
204 #define fICTAGW(RS, RD)
205 #define fICDATAR(RS, RD) \
206 do { \
207 RD = ctx->zero; \
208 } while (0)
209 #define fICDATAW(RS, RD)
210
211 #define fDCTAGW(RS, RT)
212 /* tag: RD[23:0], state: RD[30:29] */
213 #define fDCTAGR(INDEX, DST, DST_REG_NUM) \
214 do { \
215 DST = ctx->zero; \
216 } while (0)
217 #else
218
219 /*
220 * Read tags back as zero for now:
221 *
222 * tag value in RD[31:10] for 32k, RD[31:9] for 16k
223 */
224 #define fICTAGR(RS, RD, RD2) \
225 do { \
226 RD = 0x00; \
227 } while (0)
228 #define fICTAGW(RS, RD)
229 #define fICDATAR(RS, RD) \
230 do { \
231 RD = 0x00; \
232 } while (0)
233 #define fICDATAW(RS, RD)
234
235 #define fDCTAGW(RS, RT)
236 /* tag: RD[23:0], state: RD[30:29] */
237 #define fDCTAGR(INDEX, DST, DST_REG_NUM) \
238 do { \
239 DST = 0; \
240 } while (0)
241 #endif
242
243 #else
244 #define ASSERT_DIRECT_TO_GUEST_UNSET(ENV, EXCP) do { } while (0)
245 #endif
246
247 #define NUM_TLB_REGS(x) (hexagon_tlb_get_num_entries(env_archcpu(env)->tlb))
248
249 /* NMI routing not yet implemented; Y4_nmi is a no-op for now */
250 #define fDO_NMI(THREAD_MASK) do { } while (0)
251
252 #endif