]>
Commit | Line | Data |
---|---|---|
2328826b MF |
1 | /* |
2 | * Xtensa ISA: | |
3 | * http://www.tensilica.com/products/literature-docs/documentation/xtensa-isa-databook.htm | |
4 | * | |
5 | * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab. | |
6 | * All rights reserved. | |
7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions are met: | |
10 | * * Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | |
12 | * * Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | |
15 | * * Neither the name of the Open Source and Linux Lab nor the | |
16 | * names of its contributors may be used to endorse or promote products | |
17 | * derived from this software without specific prior written permission. | |
18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | |
23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
26 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 | */ | |
30 | ||
09aae23d | 31 | #include "qemu/osdep.h" |
2328826b MF |
32 | |
33 | #include "cpu.h" | |
022c62cb | 34 | #include "exec/exec-all.h" |
76cad711 | 35 | #include "disas/disas.h" |
2328826b | 36 | #include "tcg-op.h" |
1de7afc9 | 37 | #include "qemu/log.h" |
9c17d615 | 38 | #include "sysemu/sysemu.h" |
f08b6170 | 39 | #include "exec/cpu_ldst.h" |
cfe67cef | 40 | #include "exec/semihost.h" |
77fc6f5e | 41 | #include "exec/translator.h" |
2328826b | 42 | |
2ef6175a RH |
43 | #include "exec/helper-proto.h" |
44 | #include "exec/helper-gen.h" | |
dedc5eae | 45 | |
a7e30d84 | 46 | #include "trace-tcg.h" |
508127e2 | 47 | #include "exec/log.h" |
a7e30d84 LV |
48 | |
49 | ||
77fc6f5e LV |
50 | /* is_jmp field values */ |
51 | #define DISAS_UPDATE DISAS_TARGET_0 /* cpu state was modified dynamically */ | |
52 | ||
a3380cf6 | 53 | struct DisasContext { |
dedc5eae MF |
54 | const XtensaConfig *config; |
55 | TranslationBlock *tb; | |
56 | uint32_t pc; | |
57 | uint32_t next_pc; | |
f0a548b9 MF |
58 | int cring; |
59 | int ring; | |
797d780b MF |
60 | uint32_t lbeg; |
61 | uint32_t lend; | |
dedc5eae MF |
62 | int is_jmp; |
63 | int singlestep_enabled; | |
3580ecad MF |
64 | |
65 | bool sar_5bit; | |
66 | bool sar_m32_5bit; | |
67 | bool sar_m32_allocated; | |
68 | TCGv_i32 sar_m32; | |
b994e91b | 69 | |
2db59a76 | 70 | unsigned window; |
e61dc8f7 MF |
71 | |
72 | bool debug; | |
35b5c044 MF |
73 | bool icount; |
74 | TCGv_i32 next_icount; | |
ef04a846 MF |
75 | |
76 | unsigned cpenable; | |
168c12b0 MF |
77 | |
78 | uint32_t *raw_arg; | |
33071f68 MF |
79 | xtensa_insnbuf insnbuf; |
80 | xtensa_insnbuf slotbuf; | |
a3380cf6 | 81 | }; |
dedc5eae | 82 | |
dedc5eae MF |
83 | static TCGv_i32 cpu_pc; |
84 | static TCGv_i32 cpu_R[16]; | |
dd519cbe | 85 | static TCGv_i32 cpu_FR[16]; |
2af3da91 MF |
86 | static TCGv_i32 cpu_SR[256]; |
87 | static TCGv_i32 cpu_UR[256]; | |
dedc5eae | 88 | |
022c62cb | 89 | #include "exec/gen-icount.h" |
2328826b | 90 | |
fe0bd475 MF |
91 | typedef struct XtensaReg { |
92 | const char *name; | |
93 | uint64_t opt_bits; | |
53593e90 MF |
94 | enum { |
95 | SR_R = 1, | |
96 | SR_W = 2, | |
97 | SR_X = 4, | |
98 | SR_RW = 3, | |
99 | SR_RWX = 7, | |
100 | } access; | |
fe0bd475 MF |
101 | } XtensaReg; |
102 | ||
53593e90 | 103 | #define XTENSA_REG_ACCESS(regname, opt, acc) { \ |
fe0bd475 MF |
104 | .name = (regname), \ |
105 | .opt_bits = XTENSA_OPTION_BIT(opt), \ | |
53593e90 | 106 | .access = (acc), \ |
fe0bd475 MF |
107 | } |
108 | ||
53593e90 MF |
109 | #define XTENSA_REG(regname, opt) XTENSA_REG_ACCESS(regname, opt, SR_RWX) |
110 | ||
604e1f9c | 111 | #define XTENSA_REG_BITS_ACCESS(regname, opt, acc) { \ |
fe0bd475 MF |
112 | .name = (regname), \ |
113 | .opt_bits = (opt), \ | |
604e1f9c | 114 | .access = (acc), \ |
fe0bd475 MF |
115 | } |
116 | ||
604e1f9c MF |
117 | #define XTENSA_REG_BITS(regname, opt) \ |
118 | XTENSA_REG_BITS_ACCESS(regname, opt, SR_RWX) | |
119 | ||
fe0bd475 MF |
120 | static const XtensaReg sregnames[256] = { |
121 | [LBEG] = XTENSA_REG("LBEG", XTENSA_OPTION_LOOP), | |
122 | [LEND] = XTENSA_REG("LEND", XTENSA_OPTION_LOOP), | |
123 | [LCOUNT] = XTENSA_REG("LCOUNT", XTENSA_OPTION_LOOP), | |
124 | [SAR] = XTENSA_REG_BITS("SAR", XTENSA_OPTION_ALL), | |
125 | [BR] = XTENSA_REG("BR", XTENSA_OPTION_BOOLEAN), | |
126 | [LITBASE] = XTENSA_REG("LITBASE", XTENSA_OPTION_EXTENDED_L32R), | |
127 | [SCOMPARE1] = XTENSA_REG("SCOMPARE1", XTENSA_OPTION_CONDITIONAL_STORE), | |
128 | [ACCLO] = XTENSA_REG("ACCLO", XTENSA_OPTION_MAC16), | |
129 | [ACCHI] = XTENSA_REG("ACCHI", XTENSA_OPTION_MAC16), | |
130 | [MR] = XTENSA_REG("MR0", XTENSA_OPTION_MAC16), | |
131 | [MR + 1] = XTENSA_REG("MR1", XTENSA_OPTION_MAC16), | |
132 | [MR + 2] = XTENSA_REG("MR2", XTENSA_OPTION_MAC16), | |
133 | [MR + 3] = XTENSA_REG("MR3", XTENSA_OPTION_MAC16), | |
134 | [WINDOW_BASE] = XTENSA_REG("WINDOW_BASE", XTENSA_OPTION_WINDOWED_REGISTER), | |
135 | [WINDOW_START] = XTENSA_REG("WINDOW_START", | |
136 | XTENSA_OPTION_WINDOWED_REGISTER), | |
137 | [PTEVADDR] = XTENSA_REG("PTEVADDR", XTENSA_OPTION_MMU), | |
13f6a7cd | 138 | [MMID] = XTENSA_REG_BITS("MMID", XTENSA_OPTION_ALL), |
fe0bd475 MF |
139 | [RASID] = XTENSA_REG("RASID", XTENSA_OPTION_MMU), |
140 | [ITLBCFG] = XTENSA_REG("ITLBCFG", XTENSA_OPTION_MMU), | |
141 | [DTLBCFG] = XTENSA_REG("DTLBCFG", XTENSA_OPTION_MMU), | |
142 | [IBREAKENABLE] = XTENSA_REG("IBREAKENABLE", XTENSA_OPTION_DEBUG), | |
9e03ade4 | 143 | [MEMCTL] = XTENSA_REG_BITS("MEMCTL", XTENSA_OPTION_ALL), |
fe0bd475 MF |
144 | [CACHEATTR] = XTENSA_REG("CACHEATTR", XTENSA_OPTION_CACHEATTR), |
145 | [ATOMCTL] = XTENSA_REG("ATOMCTL", XTENSA_OPTION_ATOMCTL), | |
13f6a7cd | 146 | [DDR] = XTENSA_REG("DDR", XTENSA_OPTION_DEBUG), |
fe0bd475 MF |
147 | [IBREAKA] = XTENSA_REG("IBREAKA0", XTENSA_OPTION_DEBUG), |
148 | [IBREAKA + 1] = XTENSA_REG("IBREAKA1", XTENSA_OPTION_DEBUG), | |
149 | [DBREAKA] = XTENSA_REG("DBREAKA0", XTENSA_OPTION_DEBUG), | |
150 | [DBREAKA + 1] = XTENSA_REG("DBREAKA1", XTENSA_OPTION_DEBUG), | |
151 | [DBREAKC] = XTENSA_REG("DBREAKC0", XTENSA_OPTION_DEBUG), | |
152 | [DBREAKC + 1] = XTENSA_REG("DBREAKC1", XTENSA_OPTION_DEBUG), | |
604e1f9c | 153 | [CONFIGID0] = XTENSA_REG_BITS_ACCESS("CONFIGID0", XTENSA_OPTION_ALL, SR_R), |
fe0bd475 MF |
154 | [EPC1] = XTENSA_REG("EPC1", XTENSA_OPTION_EXCEPTION), |
155 | [EPC1 + 1] = XTENSA_REG("EPC2", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
156 | [EPC1 + 2] = XTENSA_REG("EPC3", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
157 | [EPC1 + 3] = XTENSA_REG("EPC4", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
158 | [EPC1 + 4] = XTENSA_REG("EPC5", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
159 | [EPC1 + 5] = XTENSA_REG("EPC6", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
160 | [EPC1 + 6] = XTENSA_REG("EPC7", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
161 | [DEPC] = XTENSA_REG("DEPC", XTENSA_OPTION_EXCEPTION), | |
162 | [EPS2] = XTENSA_REG("EPS2", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
163 | [EPS2 + 1] = XTENSA_REG("EPS3", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
164 | [EPS2 + 2] = XTENSA_REG("EPS4", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
165 | [EPS2 + 3] = XTENSA_REG("EPS5", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
166 | [EPS2 + 4] = XTENSA_REG("EPS6", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
167 | [EPS2 + 5] = XTENSA_REG("EPS7", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
604e1f9c | 168 | [CONFIGID1] = XTENSA_REG_BITS_ACCESS("CONFIGID1", XTENSA_OPTION_ALL, SR_R), |
fe0bd475 MF |
169 | [EXCSAVE1] = XTENSA_REG("EXCSAVE1", XTENSA_OPTION_EXCEPTION), |
170 | [EXCSAVE1 + 1] = XTENSA_REG("EXCSAVE2", | |
171 | XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
172 | [EXCSAVE1 + 2] = XTENSA_REG("EXCSAVE3", | |
173 | XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
174 | [EXCSAVE1 + 3] = XTENSA_REG("EXCSAVE4", | |
175 | XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
176 | [EXCSAVE1 + 4] = XTENSA_REG("EXCSAVE5", | |
177 | XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
178 | [EXCSAVE1 + 5] = XTENSA_REG("EXCSAVE6", | |
179 | XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
180 | [EXCSAVE1 + 6] = XTENSA_REG("EXCSAVE7", | |
181 | XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT), | |
182 | [CPENABLE] = XTENSA_REG("CPENABLE", XTENSA_OPTION_COPROCESSOR), | |
53593e90 MF |
183 | [INTSET] = XTENSA_REG_ACCESS("INTSET", XTENSA_OPTION_INTERRUPT, SR_RW), |
184 | [INTCLEAR] = XTENSA_REG_ACCESS("INTCLEAR", XTENSA_OPTION_INTERRUPT, SR_W), | |
fe0bd475 MF |
185 | [INTENABLE] = XTENSA_REG("INTENABLE", XTENSA_OPTION_INTERRUPT), |
186 | [PS] = XTENSA_REG_BITS("PS", XTENSA_OPTION_ALL), | |
187 | [VECBASE] = XTENSA_REG("VECBASE", XTENSA_OPTION_RELOCATABLE_VECTOR), | |
188 | [EXCCAUSE] = XTENSA_REG("EXCCAUSE", XTENSA_OPTION_EXCEPTION), | |
53593e90 | 189 | [DEBUGCAUSE] = XTENSA_REG_ACCESS("DEBUGCAUSE", XTENSA_OPTION_DEBUG, SR_R), |
fe0bd475 | 190 | [CCOUNT] = XTENSA_REG("CCOUNT", XTENSA_OPTION_TIMER_INTERRUPT), |
53593e90 | 191 | [PRID] = XTENSA_REG_ACCESS("PRID", XTENSA_OPTION_PROCESSOR_ID, SR_R), |
fe0bd475 MF |
192 | [ICOUNT] = XTENSA_REG("ICOUNT", XTENSA_OPTION_DEBUG), |
193 | [ICOUNTLEVEL] = XTENSA_REG("ICOUNTLEVEL", XTENSA_OPTION_DEBUG), | |
194 | [EXCVADDR] = XTENSA_REG("EXCVADDR", XTENSA_OPTION_EXCEPTION), | |
195 | [CCOMPARE] = XTENSA_REG("CCOMPARE0", XTENSA_OPTION_TIMER_INTERRUPT), | |
196 | [CCOMPARE + 1] = XTENSA_REG("CCOMPARE1", | |
197 | XTENSA_OPTION_TIMER_INTERRUPT), | |
198 | [CCOMPARE + 2] = XTENSA_REG("CCOMPARE2", | |
199 | XTENSA_OPTION_TIMER_INTERRUPT), | |
b7909d81 MF |
200 | [MISC] = XTENSA_REG("MISC0", XTENSA_OPTION_MISC_SR), |
201 | [MISC + 1] = XTENSA_REG("MISC1", XTENSA_OPTION_MISC_SR), | |
202 | [MISC + 2] = XTENSA_REG("MISC2", XTENSA_OPTION_MISC_SR), | |
203 | [MISC + 3] = XTENSA_REG("MISC3", XTENSA_OPTION_MISC_SR), | |
2af3da91 MF |
204 | }; |
205 | ||
fe0bd475 | 206 | static const XtensaReg uregnames[256] = { |
e9872741 | 207 | [EXPSTATE] = XTENSA_REG_BITS("EXPSTATE", XTENSA_OPTION_ALL), |
fe0bd475 MF |
208 | [THREADPTR] = XTENSA_REG("THREADPTR", XTENSA_OPTION_THREAD_POINTER), |
209 | [FCR] = XTENSA_REG("FCR", XTENSA_OPTION_FP_COPROCESSOR), | |
210 | [FSR] = XTENSA_REG("FSR", XTENSA_OPTION_FP_COPROCESSOR), | |
2af3da91 MF |
211 | }; |
212 | ||
2328826b MF |
213 | void xtensa_translate_init(void) |
214 | { | |
dedc5eae MF |
215 | static const char * const regnames[] = { |
216 | "ar0", "ar1", "ar2", "ar3", | |
217 | "ar4", "ar5", "ar6", "ar7", | |
218 | "ar8", "ar9", "ar10", "ar11", | |
219 | "ar12", "ar13", "ar14", "ar15", | |
220 | }; | |
dd519cbe MF |
221 | static const char * const fregnames[] = { |
222 | "f0", "f1", "f2", "f3", | |
223 | "f4", "f5", "f6", "f7", | |
224 | "f8", "f9", "f10", "f11", | |
225 | "f12", "f13", "f14", "f15", | |
226 | }; | |
dedc5eae MF |
227 | int i; |
228 | ||
e1ccc054 | 229 | cpu_pc = tcg_global_mem_new_i32(cpu_env, |
97129ac8 | 230 | offsetof(CPUXtensaState, pc), "pc"); |
dedc5eae MF |
231 | |
232 | for (i = 0; i < 16; i++) { | |
e1ccc054 | 233 | cpu_R[i] = tcg_global_mem_new_i32(cpu_env, |
97129ac8 | 234 | offsetof(CPUXtensaState, regs[i]), |
dedc5eae MF |
235 | regnames[i]); |
236 | } | |
2af3da91 | 237 | |
dd519cbe | 238 | for (i = 0; i < 16; i++) { |
e1ccc054 | 239 | cpu_FR[i] = tcg_global_mem_new_i32(cpu_env, |
ddd44279 | 240 | offsetof(CPUXtensaState, fregs[i].f32[FP_F32_LOW]), |
dd519cbe MF |
241 | fregnames[i]); |
242 | } | |
243 | ||
2af3da91 | 244 | for (i = 0; i < 256; ++i) { |
fe0bd475 | 245 | if (sregnames[i].name) { |
e1ccc054 | 246 | cpu_SR[i] = tcg_global_mem_new_i32(cpu_env, |
97129ac8 | 247 | offsetof(CPUXtensaState, sregs[i]), |
fe0bd475 | 248 | sregnames[i].name); |
2af3da91 MF |
249 | } |
250 | } | |
251 | ||
252 | for (i = 0; i < 256; ++i) { | |
fe0bd475 | 253 | if (uregnames[i].name) { |
e1ccc054 | 254 | cpu_UR[i] = tcg_global_mem_new_i32(cpu_env, |
97129ac8 | 255 | offsetof(CPUXtensaState, uregs[i]), |
fe0bd475 | 256 | uregnames[i].name); |
2af3da91 MF |
257 | } |
258 | } | |
dedc5eae MF |
259 | } |
260 | ||
261 | static inline bool option_enabled(DisasContext *dc, int opt) | |
262 | { | |
263 | return xtensa_option_enabled(dc->config, opt); | |
264 | } | |
265 | ||
3580ecad MF |
266 | static void init_sar_tracker(DisasContext *dc) |
267 | { | |
268 | dc->sar_5bit = false; | |
269 | dc->sar_m32_5bit = false; | |
270 | dc->sar_m32_allocated = false; | |
271 | } | |
272 | ||
273 | static void reset_sar_tracker(DisasContext *dc) | |
274 | { | |
275 | if (dc->sar_m32_allocated) { | |
276 | tcg_temp_free(dc->sar_m32); | |
277 | } | |
278 | } | |
279 | ||
280 | static void gen_right_shift_sar(DisasContext *dc, TCGv_i32 sa) | |
281 | { | |
282 | tcg_gen_andi_i32(cpu_SR[SAR], sa, 0x1f); | |
283 | if (dc->sar_m32_5bit) { | |
284 | tcg_gen_discard_i32(dc->sar_m32); | |
285 | } | |
286 | dc->sar_5bit = true; | |
287 | dc->sar_m32_5bit = false; | |
288 | } | |
289 | ||
290 | static void gen_left_shift_sar(DisasContext *dc, TCGv_i32 sa) | |
291 | { | |
292 | TCGv_i32 tmp = tcg_const_i32(32); | |
293 | if (!dc->sar_m32_allocated) { | |
294 | dc->sar_m32 = tcg_temp_local_new_i32(); | |
295 | dc->sar_m32_allocated = true; | |
296 | } | |
297 | tcg_gen_andi_i32(dc->sar_m32, sa, 0x1f); | |
298 | tcg_gen_sub_i32(cpu_SR[SAR], tmp, dc->sar_m32); | |
299 | dc->sar_5bit = false; | |
300 | dc->sar_m32_5bit = true; | |
301 | tcg_temp_free(tmp); | |
302 | } | |
303 | ||
b994e91b | 304 | static void gen_exception(DisasContext *dc, int excp) |
dedc5eae MF |
305 | { |
306 | TCGv_i32 tmp = tcg_const_i32(excp); | |
f492b82d | 307 | gen_helper_exception(cpu_env, tmp); |
dedc5eae MF |
308 | tcg_temp_free(tmp); |
309 | } | |
310 | ||
40643d7c MF |
311 | static void gen_exception_cause(DisasContext *dc, uint32_t cause) |
312 | { | |
313 | TCGv_i32 tpc = tcg_const_i32(dc->pc); | |
314 | TCGv_i32 tcause = tcg_const_i32(cause); | |
f492b82d | 315 | gen_helper_exception_cause(cpu_env, tpc, tcause); |
40643d7c MF |
316 | tcg_temp_free(tpc); |
317 | tcg_temp_free(tcause); | |
6b814719 MF |
318 | if (cause == ILLEGAL_INSTRUCTION_CAUSE || |
319 | cause == SYSCALL_CAUSE) { | |
320 | dc->is_jmp = DISAS_UPDATE; | |
321 | } | |
40643d7c MF |
322 | } |
323 | ||
5b4e481b MF |
324 | static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause, |
325 | TCGv_i32 vaddr) | |
326 | { | |
327 | TCGv_i32 tpc = tcg_const_i32(dc->pc); | |
328 | TCGv_i32 tcause = tcg_const_i32(cause); | |
f492b82d | 329 | gen_helper_exception_cause_vaddr(cpu_env, tpc, tcause, vaddr); |
5b4e481b MF |
330 | tcg_temp_free(tpc); |
331 | tcg_temp_free(tcause); | |
332 | } | |
333 | ||
e61dc8f7 MF |
334 | static void gen_debug_exception(DisasContext *dc, uint32_t cause) |
335 | { | |
336 | TCGv_i32 tpc = tcg_const_i32(dc->pc); | |
337 | TCGv_i32 tcause = tcg_const_i32(cause); | |
f492b82d | 338 | gen_helper_debug_exception(cpu_env, tpc, tcause); |
e61dc8f7 MF |
339 | tcg_temp_free(tpc); |
340 | tcg_temp_free(tcause); | |
341 | if (cause & (DEBUGCAUSE_IB | DEBUGCAUSE_BI | DEBUGCAUSE_BN)) { | |
342 | dc->is_jmp = DISAS_UPDATE; | |
343 | } | |
344 | } | |
345 | ||
97e89ee9 | 346 | static bool gen_check_privilege(DisasContext *dc) |
40643d7c | 347 | { |
ba7651fb MF |
348 | #ifndef CONFIG_USER_ONLY |
349 | if (!dc->cring) { | |
350 | return true; | |
40643d7c | 351 | } |
ba7651fb MF |
352 | #endif |
353 | gen_exception_cause(dc, PRIVILEGED_CAUSE); | |
354 | dc->is_jmp = DISAS_UPDATE; | |
355 | return false; | |
40643d7c MF |
356 | } |
357 | ||
97e89ee9 | 358 | static bool gen_check_cpenable(DisasContext *dc, unsigned cp) |
ef04a846 MF |
359 | { |
360 | if (option_enabled(dc, XTENSA_OPTION_COPROCESSOR) && | |
361 | !(dc->cpenable & (1 << cp))) { | |
362 | gen_exception_cause(dc, COPROCESSOR0_DISABLED + cp); | |
363 | dc->is_jmp = DISAS_UPDATE; | |
97e89ee9 | 364 | return false; |
ef04a846 | 365 | } |
97e89ee9 | 366 | return true; |
ef04a846 MF |
367 | } |
368 | ||
dedc5eae MF |
369 | static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot) |
370 | { | |
371 | tcg_gen_mov_i32(cpu_pc, dest); | |
35b5c044 MF |
372 | if (dc->icount) { |
373 | tcg_gen_mov_i32(cpu_SR[ICOUNT], dc->next_icount); | |
374 | } | |
dedc5eae | 375 | if (dc->singlestep_enabled) { |
b994e91b | 376 | gen_exception(dc, EXCP_DEBUG); |
dedc5eae MF |
377 | } else { |
378 | if (slot >= 0) { | |
379 | tcg_gen_goto_tb(slot); | |
07ea28b4 | 380 | tcg_gen_exit_tb(dc->tb, slot); |
dedc5eae | 381 | } else { |
07ea28b4 | 382 | tcg_gen_exit_tb(NULL, 0); |
dedc5eae MF |
383 | } |
384 | } | |
385 | dc->is_jmp = DISAS_UPDATE; | |
386 | } | |
387 | ||
67882fd1 MF |
388 | static void gen_jump(DisasContext *dc, TCGv dest) |
389 | { | |
390 | gen_jump_slot(dc, dest, -1); | |
391 | } | |
392 | ||
dedc5eae MF |
393 | static void gen_jumpi(DisasContext *dc, uint32_t dest, int slot) |
394 | { | |
395 | TCGv_i32 tmp = tcg_const_i32(dest); | |
90aa39a1 | 396 | #ifndef CONFIG_USER_ONLY |
433d33c5 | 397 | if (((dc->tb->pc ^ dest) & TARGET_PAGE_MASK) != 0) { |
dedc5eae MF |
398 | slot = -1; |
399 | } | |
90aa39a1 | 400 | #endif |
dedc5eae MF |
401 | gen_jump_slot(dc, tmp, slot); |
402 | tcg_temp_free(tmp); | |
403 | } | |
404 | ||
553e44f9 MF |
405 | static void gen_callw_slot(DisasContext *dc, int callinc, TCGv_i32 dest, |
406 | int slot) | |
407 | { | |
408 | TCGv_i32 tcallinc = tcg_const_i32(callinc); | |
409 | ||
410 | tcg_gen_deposit_i32(cpu_SR[PS], cpu_SR[PS], | |
411 | tcallinc, PS_CALLINC_SHIFT, PS_CALLINC_LEN); | |
412 | tcg_temp_free(tcallinc); | |
413 | tcg_gen_movi_i32(cpu_R[callinc << 2], | |
414 | (callinc << 30) | (dc->next_pc & 0x3fffffff)); | |
415 | gen_jump_slot(dc, dest, slot); | |
416 | } | |
417 | ||
418 | static void gen_callw(DisasContext *dc, int callinc, TCGv_i32 dest) | |
419 | { | |
420 | gen_callw_slot(dc, callinc, dest, -1); | |
421 | } | |
422 | ||
423 | static void gen_callwi(DisasContext *dc, int callinc, uint32_t dest, int slot) | |
424 | { | |
425 | TCGv_i32 tmp = tcg_const_i32(dest); | |
90aa39a1 | 426 | #ifndef CONFIG_USER_ONLY |
433d33c5 | 427 | if (((dc->tb->pc ^ dest) & TARGET_PAGE_MASK) != 0) { |
553e44f9 MF |
428 | slot = -1; |
429 | } | |
90aa39a1 | 430 | #endif |
553e44f9 MF |
431 | gen_callw_slot(dc, callinc, tmp, slot); |
432 | tcg_temp_free(tmp); | |
433 | } | |
434 | ||
797d780b MF |
435 | static bool gen_check_loop_end(DisasContext *dc, int slot) |
436 | { | |
437 | if (option_enabled(dc, XTENSA_OPTION_LOOP) && | |
438 | !(dc->tb->flags & XTENSA_TBFLAG_EXCM) && | |
439 | dc->next_pc == dc->lend) { | |
42a268c2 | 440 | TCGLabel *label = gen_new_label(); |
797d780b MF |
441 | |
442 | tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_SR[LCOUNT], 0, label); | |
443 | tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_SR[LCOUNT], 1); | |
444 | gen_jumpi(dc, dc->lbeg, slot); | |
445 | gen_set_label(label); | |
446 | gen_jumpi(dc, dc->next_pc, -1); | |
447 | return true; | |
448 | } | |
449 | return false; | |
450 | } | |
451 | ||
452 | static void gen_jumpi_check_loop_end(DisasContext *dc, int slot) | |
453 | { | |
454 | if (!gen_check_loop_end(dc, slot)) { | |
455 | gen_jumpi(dc, dc->next_pc, slot); | |
456 | } | |
457 | } | |
458 | ||
bd57fb91 | 459 | static void gen_brcond(DisasContext *dc, TCGCond cond, |
33071f68 | 460 | TCGv_i32 t0, TCGv_i32 t1, uint32_t addr) |
bd57fb91 | 461 | { |
42a268c2 | 462 | TCGLabel *label = gen_new_label(); |
bd57fb91 MF |
463 | |
464 | tcg_gen_brcond_i32(cond, t0, t1, label); | |
797d780b | 465 | gen_jumpi_check_loop_end(dc, 0); |
bd57fb91 | 466 | gen_set_label(label); |
33071f68 | 467 | gen_jumpi(dc, addr, 1); |
bd57fb91 MF |
468 | } |
469 | ||
470 | static void gen_brcondi(DisasContext *dc, TCGCond cond, | |
33071f68 | 471 | TCGv_i32 t0, uint32_t t1, uint32_t addr) |
bd57fb91 MF |
472 | { |
473 | TCGv_i32 tmp = tcg_const_i32(t1); | |
33071f68 | 474 | gen_brcond(dc, cond, t0, tmp, addr); |
bd57fb91 MF |
475 | tcg_temp_free(tmp); |
476 | } | |
477 | ||
0857a06e | 478 | static bool gen_check_sr(DisasContext *dc, uint32_t sr, unsigned access) |
fe0bd475 MF |
479 | { |
480 | if (!xtensa_option_bits_enabled(dc->config, sregnames[sr].opt_bits)) { | |
481 | if (sregnames[sr].name) { | |
c30f0d18 | 482 | qemu_log_mask(LOG_GUEST_ERROR, "SR %s is not configured\n", sregnames[sr].name); |
fe0bd475 | 483 | } else { |
c30f0d18 | 484 | qemu_log_mask(LOG_UNIMP, "SR %d is not implemented\n", sr); |
fe0bd475 MF |
485 | } |
486 | gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); | |
0857a06e | 487 | return false; |
53593e90 MF |
488 | } else if (!(sregnames[sr].access & access)) { |
489 | static const char * const access_text[] = { | |
490 | [SR_R] = "rsr", | |
491 | [SR_W] = "wsr", | |
492 | [SR_X] = "xsr", | |
493 | }; | |
494 | assert(access < ARRAY_SIZE(access_text) && access_text[access]); | |
c30f0d18 PB |
495 | qemu_log_mask(LOG_GUEST_ERROR, "SR %s is not available for %s\n", sregnames[sr].name, |
496 | access_text[access]); | |
53593e90 | 497 | gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); |
0857a06e | 498 | return false; |
fe0bd475 | 499 | } |
0857a06e | 500 | return true; |
fe0bd475 MF |
501 | } |
502 | ||
ba7651fb | 503 | #ifndef CONFIG_USER_ONLY |
d2132510 | 504 | static bool gen_rsr_ccount(DisasContext *dc, TCGv_i32 d, uint32_t sr) |
b994e91b | 505 | { |
c5a49c63 | 506 | if (tb_cflags(dc->tb) & CF_USE_ICOUNT) { |
d2132510 MF |
507 | gen_io_start(); |
508 | } | |
59a71f75 | 509 | gen_helper_update_ccount(cpu_env); |
b994e91b | 510 | tcg_gen_mov_i32(d, cpu_SR[sr]); |
c5a49c63 | 511 | if (tb_cflags(dc->tb) & CF_USE_ICOUNT) { |
d2132510 MF |
512 | gen_io_end(); |
513 | return true; | |
514 | } | |
515 | return false; | |
b994e91b MF |
516 | } |
517 | ||
d2132510 | 518 | static bool gen_rsr_ptevaddr(DisasContext *dc, TCGv_i32 d, uint32_t sr) |
b67ea0cd MF |
519 | { |
520 | tcg_gen_shri_i32(d, cpu_SR[EXCVADDR], 10); | |
521 | tcg_gen_or_i32(d, d, cpu_SR[sr]); | |
522 | tcg_gen_andi_i32(d, d, 0xfffffffc); | |
d2132510 | 523 | return false; |
b67ea0cd | 524 | } |
ba7651fb | 525 | #endif |
b67ea0cd | 526 | |
d2132510 | 527 | static bool gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr) |
b8132eff | 528 | { |
d2132510 | 529 | static bool (* const rsr_handler[256])(DisasContext *dc, |
b8132eff | 530 | TCGv_i32 d, uint32_t sr) = { |
ba7651fb | 531 | #ifndef CONFIG_USER_ONLY |
b994e91b | 532 | [CCOUNT] = gen_rsr_ccount, |
59a71f75 | 533 | [INTSET] = gen_rsr_ccount, |
b67ea0cd | 534 | [PTEVADDR] = gen_rsr_ptevaddr, |
ba7651fb | 535 | #endif |
b8132eff MF |
536 | }; |
537 | ||
fe0bd475 | 538 | if (rsr_handler[sr]) { |
d2132510 | 539 | return rsr_handler[sr](dc, d, sr); |
b8132eff | 540 | } else { |
fe0bd475 | 541 | tcg_gen_mov_i32(d, cpu_SR[sr]); |
d2132510 | 542 | return false; |
b8132eff MF |
543 | } |
544 | } | |
545 | ||
d2132510 | 546 | static bool gen_wsr_lbeg(DisasContext *dc, uint32_t sr, TCGv_i32 s) |
797d780b | 547 | { |
f492b82d | 548 | gen_helper_wsr_lbeg(cpu_env, s); |
3d0be8a5 | 549 | gen_jumpi_check_loop_end(dc, 0); |
d2132510 | 550 | return false; |
797d780b MF |
551 | } |
552 | ||
d2132510 | 553 | static bool gen_wsr_lend(DisasContext *dc, uint32_t sr, TCGv_i32 s) |
797d780b | 554 | { |
f492b82d | 555 | gen_helper_wsr_lend(cpu_env, s); |
3d0be8a5 | 556 | gen_jumpi_check_loop_end(dc, 0); |
d2132510 | 557 | return false; |
797d780b MF |
558 | } |
559 | ||
d2132510 | 560 | static bool gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s) |
3580ecad MF |
561 | { |
562 | tcg_gen_andi_i32(cpu_SR[sr], s, 0x3f); | |
563 | if (dc->sar_m32_5bit) { | |
564 | tcg_gen_discard_i32(dc->sar_m32); | |
565 | } | |
566 | dc->sar_5bit = false; | |
567 | dc->sar_m32_5bit = false; | |
d2132510 | 568 | return false; |
3580ecad MF |
569 | } |
570 | ||
d2132510 | 571 | static bool gen_wsr_br(DisasContext *dc, uint32_t sr, TCGv_i32 s) |
4dd85b6b MF |
572 | { |
573 | tcg_gen_andi_i32(cpu_SR[sr], s, 0xffff); | |
d2132510 | 574 | return false; |
4dd85b6b MF |
575 | } |
576 | ||
d2132510 | 577 | static bool gen_wsr_litbase(DisasContext *dc, uint32_t sr, TCGv_i32 s) |
6ad6dbf7 MF |
578 | { |
579 | tcg_gen_andi_i32(cpu_SR[sr], s, 0xfffff001); | |
580 | /* This can change tb->flags, so exit tb */ | |
581 | gen_jumpi_check_loop_end(dc, -1); | |
d2132510 | 582 | return true; |
6ad6dbf7 MF |
583 | } |
584 | ||
d2132510 | 585 | static bool gen_wsr_acchi(DisasContext *dc, uint32_t sr, TCGv_i32 s) |
6825b6c3 MF |
586 | { |
587 | tcg_gen_ext8s_i32(cpu_SR[sr], s); | |
d2132510 | 588 | return false; |
6825b6c3 MF |
589 | } |
590 | ||
ba7651fb | 591 | #ifndef CONFIG_USER_ONLY |
d2132510 | 592 | static bool gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
553e44f9 | 593 | { |
f492b82d | 594 | gen_helper_wsr_windowbase(cpu_env, v); |
2db59a76 MF |
595 | /* This can change tb->flags, so exit tb */ |
596 | gen_jumpi_check_loop_end(dc, -1); | |
d2132510 | 597 | return true; |
772177c1 MF |
598 | } |
599 | ||
d2132510 | 600 | static bool gen_wsr_windowstart(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
772177c1 | 601 | { |
53a72dfd | 602 | tcg_gen_andi_i32(cpu_SR[sr], v, (1 << dc->config->nareg / 4) - 1); |
2db59a76 MF |
603 | /* This can change tb->flags, so exit tb */ |
604 | gen_jumpi_check_loop_end(dc, -1); | |
d2132510 | 605 | return true; |
553e44f9 MF |
606 | } |
607 | ||
d2132510 | 608 | static bool gen_wsr_ptevaddr(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
b67ea0cd MF |
609 | { |
610 | tcg_gen_andi_i32(cpu_SR[sr], v, 0xffc00000); | |
d2132510 | 611 | return false; |
b67ea0cd MF |
612 | } |
613 | ||
d2132510 | 614 | static bool gen_wsr_rasid(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
b67ea0cd | 615 | { |
f492b82d | 616 | gen_helper_wsr_rasid(cpu_env, v); |
b67ea0cd MF |
617 | /* This can change tb->flags, so exit tb */ |
618 | gen_jumpi_check_loop_end(dc, -1); | |
d2132510 | 619 | return true; |
b67ea0cd MF |
620 | } |
621 | ||
d2132510 | 622 | static bool gen_wsr_tlbcfg(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
b67ea0cd MF |
623 | { |
624 | tcg_gen_andi_i32(cpu_SR[sr], v, 0x01130000); | |
d2132510 | 625 | return false; |
b67ea0cd MF |
626 | } |
627 | ||
d2132510 | 628 | static bool gen_wsr_ibreakenable(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
e61dc8f7 | 629 | { |
f492b82d | 630 | gen_helper_wsr_ibreakenable(cpu_env, v); |
e61dc8f7 | 631 | gen_jumpi_check_loop_end(dc, 0); |
d2132510 | 632 | return true; |
e61dc8f7 MF |
633 | } |
634 | ||
9e03ade4 MF |
635 | static bool gen_wsr_memctl(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
636 | { | |
637 | gen_helper_wsr_memctl(cpu_env, v); | |
638 | return false; | |
e61dc8f7 MF |
639 | } |
640 | ||
d2132510 | 641 | static bool gen_wsr_atomctl(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
fcc803d1 MF |
642 | { |
643 | tcg_gen_andi_i32(cpu_SR[sr], v, 0x3f); | |
d2132510 | 644 | return false; |
fcc803d1 MF |
645 | } |
646 | ||
d2132510 | 647 | static bool gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
e61dc8f7 MF |
648 | { |
649 | unsigned id = sr - IBREAKA; | |
650 | ||
651 | if (id < dc->config->nibreak) { | |
652 | TCGv_i32 tmp = tcg_const_i32(id); | |
f492b82d | 653 | gen_helper_wsr_ibreaka(cpu_env, tmp, v); |
e61dc8f7 MF |
654 | tcg_temp_free(tmp); |
655 | gen_jumpi_check_loop_end(dc, 0); | |
d2132510 | 656 | return true; |
e61dc8f7 | 657 | } |
d2132510 | 658 | return false; |
e61dc8f7 MF |
659 | } |
660 | ||
d2132510 | 661 | static bool gen_wsr_dbreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
f14c4b5f MF |
662 | { |
663 | unsigned id = sr - DBREAKA; | |
664 | ||
665 | if (id < dc->config->ndbreak) { | |
666 | TCGv_i32 tmp = tcg_const_i32(id); | |
f492b82d | 667 | gen_helper_wsr_dbreaka(cpu_env, tmp, v); |
f14c4b5f MF |
668 | tcg_temp_free(tmp); |
669 | } | |
d2132510 | 670 | return false; |
f14c4b5f MF |
671 | } |
672 | ||
d2132510 | 673 | static bool gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
f14c4b5f MF |
674 | { |
675 | unsigned id = sr - DBREAKC; | |
676 | ||
677 | if (id < dc->config->ndbreak) { | |
678 | TCGv_i32 tmp = tcg_const_i32(id); | |
f492b82d | 679 | gen_helper_wsr_dbreakc(cpu_env, tmp, v); |
f14c4b5f MF |
680 | tcg_temp_free(tmp); |
681 | } | |
d2132510 | 682 | return false; |
f14c4b5f MF |
683 | } |
684 | ||
d2132510 | 685 | static bool gen_wsr_cpenable(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
ef04a846 MF |
686 | { |
687 | tcg_gen_andi_i32(cpu_SR[sr], v, 0xff); | |
688 | /* This can change tb->flags, so exit tb */ | |
689 | gen_jumpi_check_loop_end(dc, -1); | |
d2132510 | 690 | return true; |
ef04a846 MF |
691 | } |
692 | ||
d2132510 MF |
693 | static void gen_check_interrupts(DisasContext *dc) |
694 | { | |
c5a49c63 | 695 | if (tb_cflags(dc->tb) & CF_USE_ICOUNT) { |
d2132510 MF |
696 | gen_io_start(); |
697 | } | |
698 | gen_helper_check_interrupts(cpu_env); | |
c5a49c63 | 699 | if (tb_cflags(dc->tb) & CF_USE_ICOUNT) { |
d2132510 MF |
700 | gen_io_end(); |
701 | } | |
702 | } | |
703 | ||
704 | static bool gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v) | |
b994e91b MF |
705 | { |
706 | tcg_gen_andi_i32(cpu_SR[sr], v, | |
707 | dc->config->inttype_mask[INTTYPE_SOFTWARE]); | |
d2132510 | 708 | gen_check_interrupts(dc); |
b994e91b | 709 | gen_jumpi_check_loop_end(dc, 0); |
d2132510 | 710 | return true; |
b994e91b MF |
711 | } |
712 | ||
d2132510 | 713 | static bool gen_wsr_intclear(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
b994e91b MF |
714 | { |
715 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
716 | ||
717 | tcg_gen_andi_i32(tmp, v, | |
718 | dc->config->inttype_mask[INTTYPE_EDGE] | | |
719 | dc->config->inttype_mask[INTTYPE_NMI] | | |
720 | dc->config->inttype_mask[INTTYPE_SOFTWARE]); | |
721 | tcg_gen_andc_i32(cpu_SR[INTSET], cpu_SR[INTSET], tmp); | |
722 | tcg_temp_free(tmp); | |
d2132510 MF |
723 | gen_check_interrupts(dc); |
724 | gen_jumpi_check_loop_end(dc, 0); | |
725 | return true; | |
b994e91b MF |
726 | } |
727 | ||
d2132510 | 728 | static bool gen_wsr_intenable(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
b994e91b MF |
729 | { |
730 | tcg_gen_mov_i32(cpu_SR[sr], v); | |
d2132510 | 731 | gen_check_interrupts(dc); |
b994e91b | 732 | gen_jumpi_check_loop_end(dc, 0); |
d2132510 | 733 | return true; |
b994e91b MF |
734 | } |
735 | ||
d2132510 | 736 | static bool gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
f0a548b9 MF |
737 | { |
738 | uint32_t mask = PS_WOE | PS_CALLINC | PS_OWB | | |
739 | PS_UM | PS_EXCM | PS_INTLEVEL; | |
740 | ||
741 | if (option_enabled(dc, XTENSA_OPTION_MMU)) { | |
742 | mask |= PS_RING; | |
743 | } | |
744 | tcg_gen_andi_i32(cpu_SR[sr], v, mask); | |
d2132510 | 745 | gen_check_interrupts(dc); |
b994e91b | 746 | /* This can change mmu index and tb->flags, so exit tb */ |
797d780b | 747 | gen_jumpi_check_loop_end(dc, -1); |
d2132510 | 748 | return true; |
f0a548b9 MF |
749 | } |
750 | ||
d2132510 | 751 | static bool gen_wsr_ccount(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
59a71f75 | 752 | { |
c5a49c63 | 753 | if (tb_cflags(dc->tb) & CF_USE_ICOUNT) { |
d2132510 MF |
754 | gen_io_start(); |
755 | } | |
59a71f75 | 756 | gen_helper_wsr_ccount(cpu_env, v); |
c5a49c63 | 757 | if (tb_cflags(dc->tb) & CF_USE_ICOUNT) { |
d2132510 MF |
758 | gen_io_end(); |
759 | gen_jumpi_check_loop_end(dc, 0); | |
760 | return true; | |
761 | } | |
762 | return false; | |
f0a548b9 MF |
763 | } |
764 | ||
d2132510 | 765 | static bool gen_wsr_icount(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
35b5c044 MF |
766 | { |
767 | if (dc->icount) { | |
768 | tcg_gen_mov_i32(dc->next_icount, v); | |
769 | } else { | |
770 | tcg_gen_mov_i32(cpu_SR[sr], v); | |
771 | } | |
d2132510 | 772 | return false; |
35b5c044 MF |
773 | } |
774 | ||
d2132510 | 775 | static bool gen_wsr_icountlevel(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
35b5c044 MF |
776 | { |
777 | tcg_gen_andi_i32(cpu_SR[sr], v, 0xf); | |
778 | /* This can change tb->flags, so exit tb */ | |
779 | gen_jumpi_check_loop_end(dc, -1); | |
d2132510 | 780 | return true; |
35b5c044 MF |
781 | } |
782 | ||
d2132510 | 783 | static bool gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v) |
b994e91b MF |
784 | { |
785 | uint32_t id = sr - CCOMPARE; | |
d2132510 MF |
786 | bool ret = false; |
787 | ||
b994e91b MF |
788 | if (id < dc->config->nccompare) { |
789 | uint32_t int_bit = 1 << dc->config->timerint[id]; | |
59a71f75 MF |
790 | TCGv_i32 tmp = tcg_const_i32(id); |
791 | ||
b994e91b MF |
792 | tcg_gen_mov_i32(cpu_SR[sr], v); |
793 | tcg_gen_andi_i32(cpu_SR[INTSET], cpu_SR[INTSET], ~int_bit); | |
c5a49c63 | 794 | if (tb_cflags(dc->tb) & CF_USE_ICOUNT) { |
d2132510 MF |
795 | gen_io_start(); |
796 | } | |
59a71f75 | 797 | gen_helper_update_ccompare(cpu_env, tmp); |
c5a49c63 | 798 | if (tb_cflags(dc->tb) & CF_USE_ICOUNT) { |
d2132510 MF |
799 | gen_io_end(); |
800 | gen_jumpi_check_loop_end(dc, 0); | |
801 | ret = true; | |
802 | } | |
59a71f75 | 803 | tcg_temp_free(tmp); |
b994e91b | 804 | } |
d2132510 | 805 | return ret; |
b994e91b | 806 | } |
ba7651fb MF |
807 | #else |
808 | static void gen_check_interrupts(DisasContext *dc) | |
809 | { | |
810 | } | |
811 | #endif | |
b994e91b | 812 | |
d2132510 | 813 | static bool gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s) |
b8132eff | 814 | { |
d2132510 | 815 | static bool (* const wsr_handler[256])(DisasContext *dc, |
b8132eff | 816 | uint32_t sr, TCGv_i32 v) = { |
797d780b MF |
817 | [LBEG] = gen_wsr_lbeg, |
818 | [LEND] = gen_wsr_lend, | |
3580ecad | 819 | [SAR] = gen_wsr_sar, |
4dd85b6b | 820 | [BR] = gen_wsr_br, |
6ad6dbf7 | 821 | [LITBASE] = gen_wsr_litbase, |
6825b6c3 | 822 | [ACCHI] = gen_wsr_acchi, |
ba7651fb | 823 | #ifndef CONFIG_USER_ONLY |
553e44f9 | 824 | [WINDOW_BASE] = gen_wsr_windowbase, |
772177c1 | 825 | [WINDOW_START] = gen_wsr_windowstart, |
b67ea0cd MF |
826 | [PTEVADDR] = gen_wsr_ptevaddr, |
827 | [RASID] = gen_wsr_rasid, | |
828 | [ITLBCFG] = gen_wsr_tlbcfg, | |
829 | [DTLBCFG] = gen_wsr_tlbcfg, | |
e61dc8f7 | 830 | [IBREAKENABLE] = gen_wsr_ibreakenable, |
9e03ade4 | 831 | [MEMCTL] = gen_wsr_memctl, |
fcc803d1 | 832 | [ATOMCTL] = gen_wsr_atomctl, |
e61dc8f7 MF |
833 | [IBREAKA] = gen_wsr_ibreaka, |
834 | [IBREAKA + 1] = gen_wsr_ibreaka, | |
f14c4b5f MF |
835 | [DBREAKA] = gen_wsr_dbreaka, |
836 | [DBREAKA + 1] = gen_wsr_dbreaka, | |
837 | [DBREAKC] = gen_wsr_dbreakc, | |
838 | [DBREAKC + 1] = gen_wsr_dbreakc, | |
ef04a846 | 839 | [CPENABLE] = gen_wsr_cpenable, |
b994e91b MF |
840 | [INTSET] = gen_wsr_intset, |
841 | [INTCLEAR] = gen_wsr_intclear, | |
842 | [INTENABLE] = gen_wsr_intenable, | |
f0a548b9 | 843 | [PS] = gen_wsr_ps, |
59a71f75 | 844 | [CCOUNT] = gen_wsr_ccount, |
35b5c044 MF |
845 | [ICOUNT] = gen_wsr_icount, |
846 | [ICOUNTLEVEL] = gen_wsr_icountlevel, | |
b994e91b MF |
847 | [CCOMPARE] = gen_wsr_ccompare, |
848 | [CCOMPARE + 1] = gen_wsr_ccompare, | |
849 | [CCOMPARE + 2] = gen_wsr_ccompare, | |
ba7651fb | 850 | #endif |
b8132eff MF |
851 | }; |
852 | ||
fe0bd475 | 853 | if (wsr_handler[sr]) { |
d2132510 | 854 | return wsr_handler[sr](dc, sr, s); |
b8132eff | 855 | } else { |
fe0bd475 | 856 | tcg_gen_mov_i32(cpu_SR[sr], s); |
d2132510 | 857 | return false; |
b8132eff MF |
858 | } |
859 | } | |
860 | ||
dd519cbe MF |
861 | static void gen_wur(uint32_t ur, TCGv_i32 s) |
862 | { | |
863 | switch (ur) { | |
864 | case FCR: | |
865 | gen_helper_wur_fcr(cpu_env, s); | |
866 | break; | |
867 | ||
868 | case FSR: | |
869 | tcg_gen_andi_i32(cpu_UR[ur], s, 0xffffff80); | |
870 | break; | |
871 | ||
872 | default: | |
873 | tcg_gen_mov_i32(cpu_UR[ur], s); | |
874 | break; | |
875 | } | |
876 | } | |
877 | ||
5b4e481b MF |
878 | static void gen_load_store_alignment(DisasContext *dc, int shift, |
879 | TCGv_i32 addr, bool no_hw_alignment) | |
880 | { | |
881 | if (!option_enabled(dc, XTENSA_OPTION_UNALIGNED_EXCEPTION)) { | |
882 | tcg_gen_andi_i32(addr, addr, ~0 << shift); | |
883 | } else if (option_enabled(dc, XTENSA_OPTION_HW_ALIGNMENT) && | |
884 | no_hw_alignment) { | |
42a268c2 | 885 | TCGLabel *label = gen_new_label(); |
5b4e481b MF |
886 | TCGv_i32 tmp = tcg_temp_new_i32(); |
887 | tcg_gen_andi_i32(tmp, addr, ~(~0 << shift)); | |
888 | tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); | |
889 | gen_exception_cause_vaddr(dc, LOAD_STORE_ALIGNMENT_CAUSE, addr); | |
890 | gen_set_label(label); | |
891 | tcg_temp_free(tmp); | |
892 | } | |
893 | } | |
894 | ||
ba7651fb | 895 | #ifndef CONFIG_USER_ONLY |
b994e91b MF |
896 | static void gen_waiti(DisasContext *dc, uint32_t imm4) |
897 | { | |
898 | TCGv_i32 pc = tcg_const_i32(dc->next_pc); | |
899 | TCGv_i32 intlevel = tcg_const_i32(imm4); | |
d2132510 | 900 | |
c5a49c63 | 901 | if (tb_cflags(dc->tb) & CF_USE_ICOUNT) { |
d2132510 MF |
902 | gen_io_start(); |
903 | } | |
f492b82d | 904 | gen_helper_waiti(cpu_env, pc, intlevel); |
c5a49c63 | 905 | if (tb_cflags(dc->tb) & CF_USE_ICOUNT) { |
d2132510 MF |
906 | gen_io_end(); |
907 | } | |
b994e91b MF |
908 | tcg_temp_free(pc); |
909 | tcg_temp_free(intlevel); | |
d2132510 | 910 | gen_jumpi_check_loop_end(dc, 0); |
b994e91b | 911 | } |
ba7651fb | 912 | #endif |
b994e91b | 913 | |
97e89ee9 | 914 | static bool gen_window_check1(DisasContext *dc, unsigned r1) |
772177c1 | 915 | { |
2db59a76 MF |
916 | if (r1 / 4 > dc->window) { |
917 | TCGv_i32 pc = tcg_const_i32(dc->pc); | |
918 | TCGv_i32 w = tcg_const_i32(r1 / 4); | |
908c67fc | 919 | |
2db59a76 MF |
920 | gen_helper_window_check(cpu_env, pc, w); |
921 | dc->is_jmp = DISAS_UPDATE; | |
97e89ee9 | 922 | return false; |
772177c1 | 923 | } |
97e89ee9 | 924 | return true; |
772177c1 MF |
925 | } |
926 | ||
97e89ee9 | 927 | static bool gen_window_check2(DisasContext *dc, unsigned r1, unsigned r2) |
772177c1 | 928 | { |
97e89ee9 | 929 | return gen_window_check1(dc, r1 > r2 ? r1 : r2); |
772177c1 MF |
930 | } |
931 | ||
97e89ee9 | 932 | static bool gen_window_check3(DisasContext *dc, unsigned r1, unsigned r2, |
772177c1 MF |
933 | unsigned r3) |
934 | { | |
97e89ee9 | 935 | return gen_window_check2(dc, r1, r2 > r3 ? r2 : r3); |
772177c1 MF |
936 | } |
937 | ||
6825b6c3 MF |
938 | static TCGv_i32 gen_mac16_m(TCGv_i32 v, bool hi, bool is_unsigned) |
939 | { | |
940 | TCGv_i32 m = tcg_temp_new_i32(); | |
941 | ||
942 | if (hi) { | |
943 | (is_unsigned ? tcg_gen_shri_i32 : tcg_gen_sari_i32)(m, v, 16); | |
944 | } else { | |
945 | (is_unsigned ? tcg_gen_ext16u_i32 : tcg_gen_ext16s_i32)(m, v); | |
946 | } | |
947 | return m; | |
948 | } | |
949 | ||
33071f68 | 950 | static inline unsigned xtensa_op0_insn_len(DisasContext *dc, uint8_t op0) |
01673a34 | 951 | { |
33071f68 | 952 | return xtensa_isa_length_from_chars(dc->config->isa, &op0); |
01673a34 MF |
953 | } |
954 | ||
0c4fabea | 955 | static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) |
dedc5eae | 956 | { |
33071f68 MF |
957 | xtensa_isa isa = dc->config->isa; |
958 | unsigned char b[MAX_INSN_LENGTH] = {cpu_ldub_code(env, dc->pc)}; | |
959 | unsigned len = xtensa_op0_insn_len(dc, b[0]); | |
960 | xtensa_format fmt; | |
847a6473 | 961 | int slot, slots; |
33071f68 | 962 | unsigned i; |
01673a34 | 963 | |
33071f68 MF |
964 | if (len == XTENSA_UNDEFINED) { |
965 | qemu_log_mask(LOG_GUEST_ERROR, | |
966 | "unknown instruction length (pc = %08x)\n", | |
967 | dc->pc); | |
968 | gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); | |
969 | return; | |
dedc5eae | 970 | } |
dedc5eae | 971 | |
33071f68 | 972 | dc->next_pc = dc->pc + len; |
f40385c9 MF |
973 | if (xtensa_option_enabled(dc->config, XTENSA_OPTION_LOOP) && |
974 | dc->lbeg == dc->pc && | |
975 | ((dc->pc ^ (dc->next_pc - 1)) & -dc->config->inst_fetch_width)) { | |
976 | qemu_log_mask(LOG_GUEST_ERROR, | |
977 | "unaligned first instruction of a loop (pc = %08x)\n", | |
978 | dc->pc); | |
979 | } | |
33071f68 MF |
980 | for (i = 1; i < len; ++i) { |
981 | b[i] = cpu_ldub_code(env, dc->pc + i); | |
982 | } | |
983 | xtensa_insnbuf_from_chars(isa, dc->insnbuf, b, len); | |
984 | fmt = xtensa_format_decode(isa, dc->insnbuf); | |
985 | if (fmt == XTENSA_UNDEFINED) { | |
986 | qemu_log_mask(LOG_GUEST_ERROR, | |
987 | "unrecognized instruction format (pc = %08x)\n", | |
988 | dc->pc); | |
989 | gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); | |
990 | return; | |
991 | } | |
992 | slots = xtensa_format_num_slots(isa, fmt); | |
993 | for (slot = 0; slot < slots; ++slot) { | |
994 | xtensa_opcode opc; | |
847a6473 | 995 | int opnd, vopnd, opnds; |
33071f68 MF |
996 | uint32_t raw_arg[MAX_OPCODE_ARGS]; |
997 | uint32_t arg[MAX_OPCODE_ARGS]; | |
998 | XtensaOpcodeOps *ops; | |
999 | ||
1000 | dc->raw_arg = raw_arg; | |
1001 | ||
1002 | xtensa_format_get_slot(isa, fmt, slot, dc->insnbuf, dc->slotbuf); | |
1003 | opc = xtensa_opcode_decode(isa, fmt, slot, dc->slotbuf); | |
1004 | if (opc == XTENSA_UNDEFINED) { | |
1005 | qemu_log_mask(LOG_GUEST_ERROR, | |
1006 | "unrecognized opcode in slot %d (pc = %08x)\n", | |
1007 | slot, dc->pc); | |
1008 | gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); | |
1009 | return; | |
dedc5eae | 1010 | } |
33071f68 | 1011 | opnds = xtensa_opcode_num_operands(isa, opc); |
bd57fb91 | 1012 | |
33071f68 MF |
1013 | for (opnd = vopnd = 0; opnd < opnds; ++opnd) { |
1014 | if (xtensa_operand_is_visible(isa, opc, opnd)) { | |
1015 | uint32_t v; | |
dedc5eae | 1016 | |
33071f68 MF |
1017 | xtensa_operand_get_field(isa, opc, opnd, fmt, slot, |
1018 | dc->slotbuf, &v); | |
1019 | xtensa_operand_decode(isa, opc, opnd, &v); | |
1020 | raw_arg[vopnd] = v; | |
1021 | if (xtensa_operand_is_PCrelative(isa, opc, opnd)) { | |
1022 | xtensa_operand_undo_reloc(isa, opc, opnd, &v, dc->pc); | |
bd57fb91 | 1023 | } |
33071f68 MF |
1024 | arg[vopnd] = v; |
1025 | ++vopnd; | |
bd57fb91 MF |
1026 | } |
1027 | } | |
33071f68 MF |
1028 | ops = dc->config->opcode_ops[opc]; |
1029 | if (ops) { | |
1030 | ops->translate(dc, arg, ops->par); | |
1031 | } else { | |
1032 | qemu_log_mask(LOG_GUEST_ERROR, | |
1033 | "unimplemented opcode '%s' in slot %d (pc = %08x)\n", | |
1034 | xtensa_opcode_name(isa, opc), slot, dc->pc); | |
1035 | gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); | |
1036 | return; | |
67882fd1 | 1037 | } |
dedc5eae | 1038 | } |
c26032b2 MF |
1039 | if (dc->is_jmp == DISAS_NEXT) { |
1040 | gen_check_loop_end(dc, 0); | |
1041 | } | |
dedc5eae | 1042 | dc->pc = dc->next_pc; |
dedc5eae MF |
1043 | } |
1044 | ||
01673a34 MF |
1045 | static inline unsigned xtensa_insn_len(CPUXtensaState *env, DisasContext *dc) |
1046 | { | |
1047 | uint8_t b0 = cpu_ldub_code(env, dc->pc); | |
33071f68 | 1048 | return xtensa_op0_insn_len(dc, b0); |
01673a34 MF |
1049 | } |
1050 | ||
97129ac8 | 1051 | static void gen_ibreak_check(CPUXtensaState *env, DisasContext *dc) |
e61dc8f7 MF |
1052 | { |
1053 | unsigned i; | |
1054 | ||
1055 | for (i = 0; i < dc->config->nibreak; ++i) { | |
1056 | if ((env->sregs[IBREAKENABLE] & (1 << i)) && | |
1057 | env->sregs[IBREAKA + i] == dc->pc) { | |
1058 | gen_debug_exception(dc, DEBUGCAUSE_IB); | |
1059 | break; | |
1060 | } | |
1061 | } | |
1062 | } | |
1063 | ||
9c489ea6 | 1064 | void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) |
dedc5eae | 1065 | { |
9c489ea6 | 1066 | CPUXtensaState *env = cs->env_ptr; |
dedc5eae MF |
1067 | DisasContext dc; |
1068 | int insn_count = 0; | |
c5a49c63 | 1069 | int max_insns = tb_cflags(tb) & CF_COUNT_MASK; |
dedc5eae | 1070 | uint32_t pc_start = tb->pc; |
4e8b44b6 | 1071 | uint32_t page_start = pc_start & TARGET_PAGE_MASK; |
dedc5eae MF |
1072 | |
1073 | if (max_insns == 0) { | |
1074 | max_insns = CF_COUNT_MASK; | |
1075 | } | |
190ce7fb RH |
1076 | if (max_insns > TCG_MAX_INSNS) { |
1077 | max_insns = TCG_MAX_INSNS; | |
1078 | } | |
dedc5eae MF |
1079 | |
1080 | dc.config = env->config; | |
ed2803da | 1081 | dc.singlestep_enabled = cs->singlestep_enabled; |
dedc5eae MF |
1082 | dc.tb = tb; |
1083 | dc.pc = pc_start; | |
f0a548b9 MF |
1084 | dc.ring = tb->flags & XTENSA_TBFLAG_RING_MASK; |
1085 | dc.cring = (tb->flags & XTENSA_TBFLAG_EXCM) ? 0 : dc.ring; | |
797d780b MF |
1086 | dc.lbeg = env->sregs[LBEG]; |
1087 | dc.lend = env->sregs[LEND]; | |
dedc5eae | 1088 | dc.is_jmp = DISAS_NEXT; |
e61dc8f7 | 1089 | dc.debug = tb->flags & XTENSA_TBFLAG_DEBUG; |
35b5c044 | 1090 | dc.icount = tb->flags & XTENSA_TBFLAG_ICOUNT; |
ef04a846 MF |
1091 | dc.cpenable = (tb->flags & XTENSA_TBFLAG_CPENABLE_MASK) >> |
1092 | XTENSA_TBFLAG_CPENABLE_SHIFT; | |
2db59a76 MF |
1093 | dc.window = ((tb->flags & XTENSA_TBFLAG_WINDOW_MASK) >> |
1094 | XTENSA_TBFLAG_WINDOW_SHIFT); | |
dedc5eae | 1095 | |
33071f68 MF |
1096 | if (dc.config->isa) { |
1097 | dc.insnbuf = xtensa_insnbuf_alloc(dc.config->isa); | |
1098 | dc.slotbuf = xtensa_insnbuf_alloc(dc.config->isa); | |
1099 | } | |
1100 | ||
3580ecad | 1101 | init_sar_tracker(&dc); |
35b5c044 MF |
1102 | if (dc.icount) { |
1103 | dc.next_icount = tcg_temp_local_new_i32(); | |
1104 | } | |
3580ecad | 1105 | |
cd42d5b2 | 1106 | gen_tb_start(tb); |
dedc5eae | 1107 | |
c5a49c63 | 1108 | if ((tb_cflags(tb) & CF_USE_ICOUNT) && |
d2132510 MF |
1109 | (tb->flags & XTENSA_TBFLAG_YIELD)) { |
1110 | tcg_gen_insn_start(dc.pc); | |
1111 | ++insn_count; | |
1112 | gen_exception(&dc, EXCP_YIELD); | |
1113 | dc.is_jmp = DISAS_UPDATE; | |
1114 | goto done; | |
1115 | } | |
a00817cc | 1116 | if (tb->flags & XTENSA_TBFLAG_EXCEPTION) { |
787eaa49 MF |
1117 | tcg_gen_insn_start(dc.pc); |
1118 | ++insn_count; | |
b994e91b | 1119 | gen_exception(&dc, EXCP_DEBUG); |
787eaa49 MF |
1120 | dc.is_jmp = DISAS_UPDATE; |
1121 | goto done; | |
40643d7c MF |
1122 | } |
1123 | ||
dedc5eae | 1124 | do { |
667b8e29 | 1125 | tcg_gen_insn_start(dc.pc); |
959082fc | 1126 | ++insn_count; |
dedc5eae | 1127 | |
b933066a RH |
1128 | if (unlikely(cpu_breakpoint_test(cs, dc.pc, BP_ANY))) { |
1129 | tcg_gen_movi_i32(cpu_pc, dc.pc); | |
1130 | gen_exception(&dc, EXCP_DEBUG); | |
1131 | dc.is_jmp = DISAS_UPDATE; | |
522a0d4e RH |
1132 | /* The address covered by the breakpoint must be included in |
1133 | [tb->pc, tb->pc + tb->size) in order to for it to be | |
1134 | properly cleared -- thus we increment the PC here so that | |
1135 | the logic setting tb->size below does the right thing. */ | |
1136 | dc.pc += 2; | |
b933066a RH |
1137 | break; |
1138 | } | |
1139 | ||
c5a49c63 | 1140 | if (insn_count == max_insns && (tb_cflags(tb) & CF_LAST_IO)) { |
b994e91b MF |
1141 | gen_io_start(); |
1142 | } | |
1143 | ||
35b5c044 | 1144 | if (dc.icount) { |
42a268c2 | 1145 | TCGLabel *label = gen_new_label(); |
35b5c044 MF |
1146 | |
1147 | tcg_gen_addi_i32(dc.next_icount, cpu_SR[ICOUNT], 1); | |
1148 | tcg_gen_brcondi_i32(TCG_COND_NE, dc.next_icount, 0, label); | |
1149 | tcg_gen_mov_i32(dc.next_icount, cpu_SR[ICOUNT]); | |
1150 | if (dc.debug) { | |
1151 | gen_debug_exception(&dc, DEBUGCAUSE_IC); | |
1152 | } | |
1153 | gen_set_label(label); | |
1154 | } | |
1155 | ||
e61dc8f7 MF |
1156 | if (dc.debug) { |
1157 | gen_ibreak_check(env, &dc); | |
1158 | } | |
1159 | ||
0c4fabea | 1160 | disas_xtensa_insn(env, &dc); |
35b5c044 MF |
1161 | if (dc.icount) { |
1162 | tcg_gen_mov_i32(cpu_SR[ICOUNT], dc.next_icount); | |
1163 | } | |
ed2803da | 1164 | if (cs->singlestep_enabled) { |
dedc5eae | 1165 | tcg_gen_movi_i32(cpu_pc, dc.pc); |
b994e91b | 1166 | gen_exception(&dc, EXCP_DEBUG); |
dedc5eae MF |
1167 | break; |
1168 | } | |
1169 | } while (dc.is_jmp == DISAS_NEXT && | |
1170 | insn_count < max_insns && | |
4e8b44b6 EC |
1171 | dc.pc - page_start < TARGET_PAGE_SIZE && |
1172 | dc.pc - page_start + xtensa_insn_len(env, &dc) <= TARGET_PAGE_SIZE | |
1173 | && !tcg_op_buf_full()); | |
d2132510 | 1174 | done: |
3580ecad | 1175 | reset_sar_tracker(&dc); |
35b5c044 MF |
1176 | if (dc.icount) { |
1177 | tcg_temp_free(dc.next_icount); | |
1178 | } | |
33071f68 MF |
1179 | if (dc.config->isa) { |
1180 | xtensa_insnbuf_free(dc.config->isa, dc.insnbuf); | |
1181 | xtensa_insnbuf_free(dc.config->isa, dc.slotbuf); | |
1182 | } | |
3580ecad | 1183 | |
c5a49c63 | 1184 | if (tb_cflags(tb) & CF_LAST_IO) { |
b994e91b MF |
1185 | gen_io_end(); |
1186 | } | |
1187 | ||
dedc5eae MF |
1188 | if (dc.is_jmp == DISAS_NEXT) { |
1189 | gen_jumpi(&dc, dc.pc, 0); | |
1190 | } | |
806f352d | 1191 | gen_tb_end(tb, insn_count); |
dedc5eae | 1192 | |
ca529f8e | 1193 | #ifdef DEBUG_DISAS |
4910e6e4 RH |
1194 | if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) |
1195 | && qemu_log_in_addr_range(pc_start)) { | |
1ee73216 | 1196 | qemu_log_lock(); |
ca529f8e MF |
1197 | qemu_log("----------------\n"); |
1198 | qemu_log("IN: %s\n", lookup_symbol(pc_start)); | |
1d48474d | 1199 | log_target_disas(cs, pc_start, dc.pc - pc_start); |
ca529f8e | 1200 | qemu_log("\n"); |
1ee73216 | 1201 | qemu_log_unlock(); |
ca529f8e MF |
1202 | } |
1203 | #endif | |
4e5e1215 RH |
1204 | tb->size = dc.pc - pc_start; |
1205 | tb->icount = insn_count; | |
2328826b MF |
1206 | } |
1207 | ||
878096ee AF |
1208 | void xtensa_cpu_dump_state(CPUState *cs, FILE *f, |
1209 | fprintf_function cpu_fprintf, int flags) | |
2328826b | 1210 | { |
878096ee AF |
1211 | XtensaCPU *cpu = XTENSA_CPU(cs); |
1212 | CPUXtensaState *env = &cpu->env; | |
2af3da91 MF |
1213 | int i, j; |
1214 | ||
1215 | cpu_fprintf(f, "PC=%08x\n\n", env->pc); | |
1216 | ||
1217 | for (i = j = 0; i < 256; ++i) { | |
fe0bd475 MF |
1218 | if (xtensa_option_bits_enabled(env->config, sregnames[i].opt_bits)) { |
1219 | cpu_fprintf(f, "%12s=%08x%c", sregnames[i].name, env->sregs[i], | |
2af3da91 MF |
1220 | (j++ % 4) == 3 ? '\n' : ' '); |
1221 | } | |
1222 | } | |
1223 | ||
1224 | cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n"); | |
1225 | ||
1226 | for (i = j = 0; i < 256; ++i) { | |
fe0bd475 MF |
1227 | if (xtensa_option_bits_enabled(env->config, uregnames[i].opt_bits)) { |
1228 | cpu_fprintf(f, "%s=%08x%c", uregnames[i].name, env->uregs[i], | |
2af3da91 MF |
1229 | (j++ % 4) == 3 ? '\n' : ' '); |
1230 | } | |
1231 | } | |
2328826b | 1232 | |
2af3da91 | 1233 | cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n"); |
2328826b MF |
1234 | |
1235 | for (i = 0; i < 16; ++i) { | |
fe0bd475 | 1236 | cpu_fprintf(f, " A%02d=%08x%c", i, env->regs[i], |
2328826b MF |
1237 | (i % 4) == 3 ? '\n' : ' '); |
1238 | } | |
553e44f9 | 1239 | |
b55b1afd | 1240 | xtensa_sync_phys_from_window(env); |
553e44f9 MF |
1241 | cpu_fprintf(f, "\n"); |
1242 | ||
1243 | for (i = 0; i < env->config->nareg; ++i) { | |
b9317a2a MF |
1244 | cpu_fprintf(f, "AR%02d=%08x ", i, env->phys_regs[i]); |
1245 | if (i % 4 == 3) { | |
1246 | bool ws = (env->sregs[WINDOW_START] & (1 << (i / 4))) != 0; | |
1247 | bool cw = env->sregs[WINDOW_BASE] == i / 4; | |
1248 | ||
1249 | cpu_fprintf(f, "%c%c\n", ws ? '<' : ' ', cw ? '=' : ' '); | |
1250 | } | |
553e44f9 | 1251 | } |
dd519cbe | 1252 | |
f29c0b17 RH |
1253 | if ((flags & CPU_DUMP_FPU) && |
1254 | xtensa_option_enabled(env->config, XTENSA_OPTION_FP_COPROCESSOR)) { | |
dd519cbe MF |
1255 | cpu_fprintf(f, "\n"); |
1256 | ||
1257 | for (i = 0; i < 16; ++i) { | |
1258 | cpu_fprintf(f, "F%02d=%08x (%+10.8e)%c", i, | |
ddd44279 MF |
1259 | float32_val(env->fregs[i].f32[FP_F32_LOW]), |
1260 | *(float *)(env->fregs[i].f32 + FP_F32_LOW), | |
1261 | (i % 2) == 1 ? '\n' : ' '); | |
dd519cbe MF |
1262 | } |
1263 | } | |
2328826b MF |
1264 | } |
1265 | ||
bad729e2 RH |
1266 | void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, |
1267 | target_ulong *data) | |
2328826b | 1268 | { |
bad729e2 | 1269 | env->pc = data[0]; |
2328826b | 1270 | } |
168c12b0 MF |
1271 | |
1272 | static int compare_opcode_ops(const void *a, const void *b) | |
1273 | { | |
1274 | return strcmp((const char *)a, | |
1275 | ((const XtensaOpcodeOps *)b)->name); | |
1276 | } | |
1277 | ||
1278 | XtensaOpcodeOps * | |
1279 | xtensa_find_opcode_ops(const XtensaOpcodeTranslators *t, | |
1280 | const char *name) | |
1281 | { | |
4a4ff4c5 LV |
1282 | return bsearch(name, t->opcode, t->num_opcodes, |
1283 | sizeof(XtensaOpcodeOps), compare_opcode_ops); | |
168c12b0 MF |
1284 | } |
1285 | ||
1286 | static void translate_abs(DisasContext *dc, const uint32_t arg[], | |
1287 | const uint32_t par[]) | |
1288 | { | |
1289 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
1290 | TCGv_i32 zero = tcg_const_i32(0); | |
1291 | TCGv_i32 neg = tcg_temp_new_i32(); | |
1292 | ||
1293 | tcg_gen_neg_i32(neg, cpu_R[arg[1]]); | |
1294 | tcg_gen_movcond_i32(TCG_COND_GE, cpu_R[arg[0]], | |
1295 | cpu_R[arg[1]], zero, cpu_R[arg[1]], neg); | |
1296 | tcg_temp_free(neg); | |
1297 | tcg_temp_free(zero); | |
1298 | } | |
1299 | } | |
1300 | ||
1301 | static void translate_add(DisasContext *dc, const uint32_t arg[], | |
1302 | const uint32_t par[]) | |
1303 | { | |
1304 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
1305 | tcg_gen_add_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); | |
1306 | } | |
1307 | } | |
1308 | ||
1309 | static void translate_addi(DisasContext *dc, const uint32_t arg[], | |
1310 | const uint32_t par[]) | |
1311 | { | |
1312 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
1313 | tcg_gen_addi_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]); | |
1314 | } | |
1315 | } | |
1316 | ||
1317 | static void translate_addx(DisasContext *dc, const uint32_t arg[], | |
1318 | const uint32_t par[]) | |
1319 | { | |
1320 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
1321 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
1322 | tcg_gen_shli_i32(tmp, cpu_R[arg[1]], par[0]); | |
1323 | tcg_gen_add_i32(cpu_R[arg[0]], tmp, cpu_R[arg[2]]); | |
1324 | tcg_temp_free(tmp); | |
1325 | } | |
1326 | } | |
1327 | ||
1328 | static void translate_all(DisasContext *dc, const uint32_t arg[], | |
1329 | const uint32_t par[]) | |
1330 | { | |
1331 | uint32_t shift = par[1]; | |
1332 | TCGv_i32 mask = tcg_const_i32(((1 << shift) - 1) << arg[1]); | |
1333 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
1334 | ||
1335 | tcg_gen_and_i32(tmp, cpu_SR[BR], mask); | |
1336 | if (par[0]) { | |
1337 | tcg_gen_addi_i32(tmp, tmp, 1 << arg[1]); | |
1338 | } else { | |
1339 | tcg_gen_add_i32(tmp, tmp, mask); | |
1340 | } | |
1341 | tcg_gen_shri_i32(tmp, tmp, arg[1] + shift); | |
1342 | tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR], | |
1343 | tmp, arg[0], 1); | |
1344 | tcg_temp_free(mask); | |
1345 | tcg_temp_free(tmp); | |
1346 | } | |
1347 | ||
1348 | static void translate_and(DisasContext *dc, const uint32_t arg[], | |
1349 | const uint32_t par[]) | |
1350 | { | |
1351 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
1352 | tcg_gen_and_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); | |
1353 | } | |
1354 | } | |
1355 | ||
1356 | static void translate_ball(DisasContext *dc, const uint32_t arg[], | |
1357 | const uint32_t par[]) | |
1358 | { | |
1359 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
1360 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
1361 | tcg_gen_and_i32(tmp, cpu_R[arg[0]], cpu_R[arg[1]]); | |
1362 | gen_brcond(dc, par[0], tmp, cpu_R[arg[1]], arg[2]); | |
1363 | tcg_temp_free(tmp); | |
1364 | } | |
1365 | } | |
1366 | ||
1367 | static void translate_bany(DisasContext *dc, const uint32_t arg[], | |
1368 | const uint32_t par[]) | |
1369 | { | |
1370 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
1371 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
1372 | tcg_gen_and_i32(tmp, cpu_R[arg[0]], cpu_R[arg[1]]); | |
1373 | gen_brcondi(dc, par[0], tmp, 0, arg[2]); | |
1374 | tcg_temp_free(tmp); | |
1375 | } | |
1376 | } | |
1377 | ||
1378 | static void translate_b(DisasContext *dc, const uint32_t arg[], | |
1379 | const uint32_t par[]) | |
1380 | { | |
1381 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
1382 | gen_brcond(dc, par[0], cpu_R[arg[0]], cpu_R[arg[1]], arg[2]); | |
1383 | } | |
1384 | } | |
1385 | ||
1386 | static void translate_bb(DisasContext *dc, const uint32_t arg[], | |
1387 | const uint32_t par[]) | |
1388 | { | |
1389 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
1390 | #ifdef TARGET_WORDS_BIGENDIAN | |
1391 | TCGv_i32 bit = tcg_const_i32(0x80000000u); | |
1392 | #else | |
1393 | TCGv_i32 bit = tcg_const_i32(0x00000001u); | |
1394 | #endif | |
1395 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
1396 | tcg_gen_andi_i32(tmp, cpu_R[arg[1]], 0x1f); | |
1397 | #ifdef TARGET_WORDS_BIGENDIAN | |
1398 | tcg_gen_shr_i32(bit, bit, tmp); | |
1399 | #else | |
1400 | tcg_gen_shl_i32(bit, bit, tmp); | |
1401 | #endif | |
1402 | tcg_gen_and_i32(tmp, cpu_R[arg[0]], bit); | |
1403 | gen_brcondi(dc, par[0], tmp, 0, arg[2]); | |
1404 | tcg_temp_free(tmp); | |
1405 | tcg_temp_free(bit); | |
1406 | } | |
1407 | } | |
1408 | ||
1409 | static void translate_bbi(DisasContext *dc, const uint32_t arg[], | |
1410 | const uint32_t par[]) | |
1411 | { | |
1412 | if (gen_window_check1(dc, arg[0])) { | |
1413 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
1414 | #ifdef TARGET_WORDS_BIGENDIAN | |
1415 | tcg_gen_andi_i32(tmp, cpu_R[arg[0]], 0x80000000u >> arg[1]); | |
1416 | #else | |
1417 | tcg_gen_andi_i32(tmp, cpu_R[arg[0]], 0x00000001u << arg[1]); | |
1418 | #endif | |
1419 | gen_brcondi(dc, par[0], tmp, 0, arg[2]); | |
1420 | tcg_temp_free(tmp); | |
1421 | } | |
1422 | } | |
1423 | ||
1424 | static void translate_bi(DisasContext *dc, const uint32_t arg[], | |
1425 | const uint32_t par[]) | |
1426 | { | |
1427 | if (gen_window_check1(dc, arg[0])) { | |
1428 | gen_brcondi(dc, par[0], cpu_R[arg[0]], arg[1], arg[2]); | |
1429 | } | |
1430 | } | |
1431 | ||
1432 | static void translate_bz(DisasContext *dc, const uint32_t arg[], | |
1433 | const uint32_t par[]) | |
1434 | { | |
1435 | if (gen_window_check1(dc, arg[0])) { | |
1436 | gen_brcondi(dc, par[0], cpu_R[arg[0]], 0, arg[1]); | |
1437 | } | |
1438 | } | |
1439 | ||
1440 | enum { | |
1441 | BOOLEAN_AND, | |
1442 | BOOLEAN_ANDC, | |
1443 | BOOLEAN_OR, | |
1444 | BOOLEAN_ORC, | |
1445 | BOOLEAN_XOR, | |
1446 | }; | |
1447 | ||
1448 | static void translate_boolean(DisasContext *dc, const uint32_t arg[], | |
1449 | const uint32_t par[]) | |
1450 | { | |
1451 | static void (* const op[])(TCGv_i32, TCGv_i32, TCGv_i32) = { | |
1452 | [BOOLEAN_AND] = tcg_gen_and_i32, | |
1453 | [BOOLEAN_ANDC] = tcg_gen_andc_i32, | |
1454 | [BOOLEAN_OR] = tcg_gen_or_i32, | |
1455 | [BOOLEAN_ORC] = tcg_gen_orc_i32, | |
1456 | [BOOLEAN_XOR] = tcg_gen_xor_i32, | |
1457 | }; | |
1458 | ||
1459 | TCGv_i32 tmp1 = tcg_temp_new_i32(); | |
1460 | TCGv_i32 tmp2 = tcg_temp_new_i32(); | |
1461 | ||
1462 | tcg_gen_shri_i32(tmp1, cpu_SR[BR], arg[1]); | |
1463 | tcg_gen_shri_i32(tmp2, cpu_SR[BR], arg[2]); | |
1464 | op[par[0]](tmp1, tmp1, tmp2); | |
1465 | tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR], tmp1, arg[0], 1); | |
1466 | tcg_temp_free(tmp1); | |
1467 | tcg_temp_free(tmp2); | |
1468 | } | |
1469 | ||
1470 | static void translate_bp(DisasContext *dc, const uint32_t arg[], | |
1471 | const uint32_t par[]) | |
1472 | { | |
1473 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
1474 | ||
1475 | tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[0]); | |
1476 | gen_brcondi(dc, par[0], tmp, 0, arg[1]); | |
1477 | tcg_temp_free(tmp); | |
1478 | } | |
1479 | ||
1480 | static void translate_break(DisasContext *dc, const uint32_t arg[], | |
1481 | const uint32_t par[]) | |
1482 | { | |
1483 | if (dc->debug) { | |
1484 | gen_debug_exception(dc, par[0]); | |
1485 | } | |
1486 | } | |
1487 | ||
1488 | static void translate_call0(DisasContext *dc, const uint32_t arg[], | |
1489 | const uint32_t par[]) | |
1490 | { | |
1491 | tcg_gen_movi_i32(cpu_R[0], dc->next_pc); | |
1492 | gen_jumpi(dc, arg[0], 0); | |
1493 | } | |
1494 | ||
1495 | static void translate_callw(DisasContext *dc, const uint32_t arg[], | |
1496 | const uint32_t par[]) | |
1497 | { | |
1498 | if (gen_window_check1(dc, par[0] << 2)) { | |
1499 | gen_callwi(dc, par[0], arg[0], 0); | |
1500 | } | |
1501 | } | |
1502 | ||
1503 | static void translate_callx0(DisasContext *dc, const uint32_t arg[], | |
1504 | const uint32_t par[]) | |
1505 | { | |
1506 | if (gen_window_check1(dc, arg[0])) { | |
1507 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
1508 | tcg_gen_mov_i32(tmp, cpu_R[arg[0]]); | |
1509 | tcg_gen_movi_i32(cpu_R[0], dc->next_pc); | |
1510 | gen_jump(dc, tmp); | |
1511 | tcg_temp_free(tmp); | |
1512 | } | |
1513 | } | |
1514 | ||
1515 | static void translate_callxw(DisasContext *dc, const uint32_t arg[], | |
1516 | const uint32_t par[]) | |
1517 | { | |
1518 | if (gen_window_check2(dc, arg[0], par[0] << 2)) { | |
1519 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
1520 | ||
1521 | tcg_gen_mov_i32(tmp, cpu_R[arg[0]]); | |
1522 | gen_callw(dc, par[0], tmp); | |
1523 | tcg_temp_free(tmp); | |
1524 | } | |
1525 | } | |
1526 | ||
1527 | static void translate_clamps(DisasContext *dc, const uint32_t arg[], | |
1528 | const uint32_t par[]) | |
1529 | { | |
1530 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
1531 | TCGv_i32 tmp1 = tcg_const_i32(-1u << arg[2]); | |
1532 | TCGv_i32 tmp2 = tcg_const_i32((1 << arg[2]) - 1); | |
1533 | ||
426afc3b RH |
1534 | tcg_gen_smax_i32(tmp1, tmp1, cpu_R[arg[1]]); |
1535 | tcg_gen_smin_i32(cpu_R[arg[0]], tmp1, tmp2); | |
168c12b0 MF |
1536 | tcg_temp_free(tmp1); |
1537 | tcg_temp_free(tmp2); | |
1538 | } | |
1539 | } | |
1540 | ||
e9872741 MF |
1541 | static void translate_clrb_expstate(DisasContext *dc, const uint32_t arg[], |
1542 | const uint32_t par[]) | |
1543 | { | |
1544 | /* TODO: GPIO32 may be a part of coprocessor */ | |
1545 | tcg_gen_andi_i32(cpu_UR[EXPSTATE], cpu_UR[EXPSTATE], ~(1u << arg[0])); | |
1546 | } | |
1547 | ||
c5ac936e MF |
1548 | static void translate_const16(DisasContext *dc, const uint32_t arg[], |
1549 | const uint32_t par[]) | |
1550 | { | |
1551 | if (gen_window_check1(dc, arg[0])) { | |
1552 | TCGv_i32 c = tcg_const_i32(arg[1]); | |
1553 | ||
1554 | tcg_gen_deposit_i32(cpu_R[arg[0]], c, cpu_R[arg[0]], 16, 16); | |
1555 | tcg_temp_free(c); | |
1556 | } | |
1557 | } | |
1558 | ||
168c12b0 MF |
1559 | /* par[0]: privileged, par[1]: check memory access */ |
1560 | static void translate_dcache(DisasContext *dc, const uint32_t arg[], | |
1561 | const uint32_t par[]) | |
1562 | { | |
1563 | if ((!par[0] || gen_check_privilege(dc)) && | |
1564 | gen_window_check1(dc, arg[0]) && par[1]) { | |
1565 | TCGv_i32 addr = tcg_temp_new_i32(); | |
1566 | TCGv_i32 res = tcg_temp_new_i32(); | |
1567 | ||
1568 | tcg_gen_addi_i32(addr, cpu_R[arg[0]], arg[1]); | |
1569 | tcg_gen_qemu_ld8u(res, addr, dc->cring); | |
1570 | tcg_temp_free(addr); | |
1571 | tcg_temp_free(res); | |
1572 | } | |
1573 | } | |
1574 | ||
1575 | static void translate_depbits(DisasContext *dc, const uint32_t arg[], | |
1576 | const uint32_t par[]) | |
1577 | { | |
1578 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
1579 | tcg_gen_deposit_i32(cpu_R[arg[1]], cpu_R[arg[1]], cpu_R[arg[0]], | |
1580 | arg[2], arg[3]); | |
1581 | } | |
1582 | } | |
1583 | ||
1584 | static void translate_entry(DisasContext *dc, const uint32_t arg[], | |
1585 | const uint32_t par[]) | |
1586 | { | |
1587 | TCGv_i32 pc = tcg_const_i32(dc->pc); | |
1588 | TCGv_i32 s = tcg_const_i32(arg[0]); | |
1589 | TCGv_i32 imm = tcg_const_i32(arg[1]); | |
1590 | gen_helper_entry(cpu_env, pc, s, imm); | |
1591 | tcg_temp_free(imm); | |
1592 | tcg_temp_free(s); | |
1593 | tcg_temp_free(pc); | |
1594 | /* This can change tb->flags, so exit tb */ | |
1595 | gen_jumpi_check_loop_end(dc, -1); | |
1596 | } | |
1597 | ||
1598 | static void translate_extui(DisasContext *dc, const uint32_t arg[], | |
1599 | const uint32_t par[]) | |
1600 | { | |
1601 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
1602 | int maskimm = (1 << arg[3]) - 1; | |
1603 | ||
1604 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
1605 | tcg_gen_shri_i32(tmp, cpu_R[arg[1]], arg[2]); | |
1606 | tcg_gen_andi_i32(cpu_R[arg[0]], tmp, maskimm); | |
1607 | tcg_temp_free(tmp); | |
1608 | } | |
1609 | } | |
1610 | ||
1611 | /* par[0]: privileged, par[1]: check memory access */ | |
1612 | static void translate_icache(DisasContext *dc, const uint32_t arg[], | |
1613 | const uint32_t par[]) | |
1614 | { | |
1615 | if ((!par[0] || gen_check_privilege(dc)) && | |
1616 | gen_window_check1(dc, arg[0]) && par[1]) { | |
ba7651fb | 1617 | #ifndef CONFIG_USER_ONLY |
168c12b0 MF |
1618 | TCGv_i32 addr = tcg_temp_new_i32(); |
1619 | ||
1620 | tcg_gen_movi_i32(cpu_pc, dc->pc); | |
1621 | tcg_gen_addi_i32(addr, cpu_R[arg[0]], arg[1]); | |
1622 | gen_helper_itlb_hit_test(cpu_env, addr); | |
1623 | tcg_temp_free(addr); | |
ba7651fb | 1624 | #endif |
168c12b0 MF |
1625 | } |
1626 | } | |
1627 | ||
1628 | static void translate_itlb(DisasContext *dc, const uint32_t arg[], | |
1629 | const uint32_t par[]) | |
1630 | { | |
1631 | if (gen_check_privilege(dc) && | |
1632 | gen_window_check1(dc, arg[0])) { | |
ba7651fb | 1633 | #ifndef CONFIG_USER_ONLY |
168c12b0 MF |
1634 | TCGv_i32 dtlb = tcg_const_i32(par[0]); |
1635 | ||
1636 | gen_helper_itlb(cpu_env, cpu_R[arg[0]], dtlb); | |
1637 | /* This could change memory mapping, so exit tb */ | |
1638 | gen_jumpi_check_loop_end(dc, -1); | |
1639 | tcg_temp_free(dtlb); | |
ba7651fb | 1640 | #endif |
168c12b0 MF |
1641 | } |
1642 | } | |
1643 | ||
1644 | static void translate_ill(DisasContext *dc, const uint32_t arg[], | |
1645 | const uint32_t par[]) | |
1646 | { | |
1647 | gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); | |
1648 | } | |
1649 | ||
1650 | static void translate_j(DisasContext *dc, const uint32_t arg[], | |
1651 | const uint32_t par[]) | |
1652 | { | |
1653 | gen_jumpi(dc, arg[0], 0); | |
1654 | } | |
1655 | ||
1656 | static void translate_jx(DisasContext *dc, const uint32_t arg[], | |
1657 | const uint32_t par[]) | |
1658 | { | |
1659 | if (gen_window_check1(dc, arg[0])) { | |
1660 | gen_jump(dc, cpu_R[arg[0]]); | |
1661 | } | |
1662 | } | |
1663 | ||
1664 | static void translate_l32e(DisasContext *dc, const uint32_t arg[], | |
1665 | const uint32_t par[]) | |
1666 | { | |
1667 | if (gen_check_privilege(dc) && | |
1668 | gen_window_check2(dc, arg[0], arg[1])) { | |
1669 | TCGv_i32 addr = tcg_temp_new_i32(); | |
1670 | ||
1671 | tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); | |
1672 | gen_load_store_alignment(dc, 2, addr, false); | |
1673 | tcg_gen_qemu_ld_tl(cpu_R[arg[0]], addr, dc->ring, MO_TEUL); | |
1674 | tcg_temp_free(addr); | |
1675 | } | |
1676 | } | |
1677 | ||
1678 | static void translate_ldst(DisasContext *dc, const uint32_t arg[], | |
1679 | const uint32_t par[]) | |
1680 | { | |
1681 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
1682 | TCGv_i32 addr = tcg_temp_new_i32(); | |
1683 | ||
1684 | tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); | |
1685 | if (par[0] & MO_SIZE) { | |
1686 | gen_load_store_alignment(dc, par[0] & MO_SIZE, addr, par[1]); | |
1687 | } | |
1688 | if (par[2]) { | |
9fb40342 MF |
1689 | if (par[1]) { |
1690 | tcg_gen_mb(TCG_BAR_STRL | TCG_MO_ALL); | |
1691 | } | |
168c12b0 MF |
1692 | tcg_gen_qemu_st_tl(cpu_R[arg[0]], addr, dc->cring, par[0]); |
1693 | } else { | |
1694 | tcg_gen_qemu_ld_tl(cpu_R[arg[0]], addr, dc->cring, par[0]); | |
9fb40342 MF |
1695 | if (par[1]) { |
1696 | tcg_gen_mb(TCG_BAR_LDAQ | TCG_MO_ALL); | |
1697 | } | |
168c12b0 MF |
1698 | } |
1699 | tcg_temp_free(addr); | |
1700 | } | |
1701 | } | |
1702 | ||
1703 | static void translate_l32r(DisasContext *dc, const uint32_t arg[], | |
1704 | const uint32_t par[]) | |
1705 | { | |
1706 | if (gen_window_check1(dc, arg[0])) { | |
5b9b2763 | 1707 | TCGv_i32 tmp; |
168c12b0 MF |
1708 | |
1709 | if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) { | |
5b9b2763 MF |
1710 | tmp = tcg_const_i32(dc->raw_arg[1] - 1); |
1711 | tcg_gen_add_i32(tmp, cpu_SR[LITBASE], tmp); | |
1712 | } else { | |
1713 | tmp = tcg_const_i32(arg[1]); | |
168c12b0 MF |
1714 | } |
1715 | tcg_gen_qemu_ld32u(cpu_R[arg[0]], tmp, dc->cring); | |
1716 | tcg_temp_free(tmp); | |
1717 | } | |
1718 | } | |
1719 | ||
1720 | static void translate_loop(DisasContext *dc, const uint32_t arg[], | |
1721 | const uint32_t par[]) | |
1722 | { | |
1723 | if (gen_window_check1(dc, arg[0])) { | |
1724 | uint32_t lend = arg[1]; | |
1725 | TCGv_i32 tmp = tcg_const_i32(lend); | |
1726 | ||
1727 | tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_R[arg[0]], 1); | |
1728 | tcg_gen_movi_i32(cpu_SR[LBEG], dc->next_pc); | |
1729 | gen_helper_wsr_lend(cpu_env, tmp); | |
1730 | tcg_temp_free(tmp); | |
1731 | ||
1732 | if (par[0] != TCG_COND_NEVER) { | |
1733 | TCGLabel *label = gen_new_label(); | |
1734 | tcg_gen_brcondi_i32(par[0], cpu_R[arg[0]], 0, label); | |
1735 | gen_jumpi(dc, lend, 1); | |
1736 | gen_set_label(label); | |
1737 | } | |
1738 | ||
1739 | gen_jumpi(dc, dc->next_pc, 0); | |
1740 | } | |
1741 | } | |
1742 | ||
1743 | enum { | |
1744 | MAC16_UMUL, | |
1745 | MAC16_MUL, | |
1746 | MAC16_MULA, | |
1747 | MAC16_MULS, | |
1748 | MAC16_NONE, | |
1749 | }; | |
1750 | ||
1751 | enum { | |
1752 | MAC16_LL, | |
1753 | MAC16_HL, | |
1754 | MAC16_LH, | |
1755 | MAC16_HH, | |
1756 | ||
1757 | MAC16_HX = 0x1, | |
1758 | MAC16_XH = 0x2, | |
1759 | }; | |
1760 | ||
1761 | enum { | |
1762 | MAC16_AA, | |
1763 | MAC16_AD, | |
1764 | MAC16_DA, | |
1765 | MAC16_DD, | |
1766 | ||
1767 | MAC16_XD = 0x1, | |
1768 | MAC16_DX = 0x2, | |
1769 | }; | |
1770 | ||
1771 | static void translate_mac16(DisasContext *dc, const uint32_t arg[], | |
1772 | const uint32_t par[]) | |
1773 | { | |
1774 | int op = par[0]; | |
1775 | bool is_m1_sr = par[1] & MAC16_DX; | |
1776 | bool is_m2_sr = par[1] & MAC16_XD; | |
1777 | unsigned half = par[2]; | |
1778 | uint32_t ld_offset = par[3]; | |
1779 | unsigned off = ld_offset ? 2 : 0; | |
1780 | uint32_t ar[3] = {0}; | |
1781 | unsigned n_ar = 0; | |
1782 | ||
1783 | if (op != MAC16_NONE) { | |
1784 | if (!is_m1_sr) { | |
1785 | ar[n_ar++] = arg[off]; | |
1786 | } | |
1787 | if (!is_m2_sr) { | |
1788 | ar[n_ar++] = arg[off + 1]; | |
1789 | } | |
1790 | } | |
1791 | ||
1792 | if (ld_offset) { | |
1793 | ar[n_ar++] = arg[1]; | |
1794 | } | |
1795 | ||
1796 | if (gen_window_check3(dc, ar[0], ar[1], ar[2])) { | |
1797 | TCGv_i32 vaddr = tcg_temp_new_i32(); | |
1798 | TCGv_i32 mem32 = tcg_temp_new_i32(); | |
1799 | ||
1800 | if (ld_offset) { | |
1801 | tcg_gen_addi_i32(vaddr, cpu_R[arg[1]], ld_offset); | |
1802 | gen_load_store_alignment(dc, 2, vaddr, false); | |
1803 | tcg_gen_qemu_ld32u(mem32, vaddr, dc->cring); | |
1804 | } | |
1805 | if (op != MAC16_NONE) { | |
1806 | TCGv_i32 m1 = gen_mac16_m(is_m1_sr ? | |
1807 | cpu_SR[MR + arg[off]] : | |
1808 | cpu_R[arg[off]], | |
1809 | half & MAC16_HX, op == MAC16_UMUL); | |
1810 | TCGv_i32 m2 = gen_mac16_m(is_m2_sr ? | |
1811 | cpu_SR[MR + arg[off + 1]] : | |
1812 | cpu_R[arg[off + 1]], | |
1813 | half & MAC16_XH, op == MAC16_UMUL); | |
1814 | ||
1815 | if (op == MAC16_MUL || op == MAC16_UMUL) { | |
1816 | tcg_gen_mul_i32(cpu_SR[ACCLO], m1, m2); | |
1817 | if (op == MAC16_UMUL) { | |
1818 | tcg_gen_movi_i32(cpu_SR[ACCHI], 0); | |
1819 | } else { | |
1820 | tcg_gen_sari_i32(cpu_SR[ACCHI], cpu_SR[ACCLO], 31); | |
1821 | } | |
1822 | } else { | |
1823 | TCGv_i32 lo = tcg_temp_new_i32(); | |
1824 | TCGv_i32 hi = tcg_temp_new_i32(); | |
1825 | ||
1826 | tcg_gen_mul_i32(lo, m1, m2); | |
1827 | tcg_gen_sari_i32(hi, lo, 31); | |
1828 | if (op == MAC16_MULA) { | |
1829 | tcg_gen_add2_i32(cpu_SR[ACCLO], cpu_SR[ACCHI], | |
1830 | cpu_SR[ACCLO], cpu_SR[ACCHI], | |
1831 | lo, hi); | |
1832 | } else { | |
1833 | tcg_gen_sub2_i32(cpu_SR[ACCLO], cpu_SR[ACCHI], | |
1834 | cpu_SR[ACCLO], cpu_SR[ACCHI], | |
1835 | lo, hi); | |
1836 | } | |
1837 | tcg_gen_ext8s_i32(cpu_SR[ACCHI], cpu_SR[ACCHI]); | |
1838 | ||
1839 | tcg_temp_free_i32(lo); | |
1840 | tcg_temp_free_i32(hi); | |
1841 | } | |
1842 | tcg_temp_free(m1); | |
1843 | tcg_temp_free(m2); | |
1844 | } | |
1845 | if (ld_offset) { | |
1846 | tcg_gen_mov_i32(cpu_R[arg[1]], vaddr); | |
1847 | tcg_gen_mov_i32(cpu_SR[MR + arg[0]], mem32); | |
1848 | } | |
1849 | tcg_temp_free(vaddr); | |
1850 | tcg_temp_free(mem32); | |
1851 | } | |
1852 | } | |
1853 | ||
9fb40342 MF |
1854 | static void translate_memw(DisasContext *dc, const uint32_t arg[], |
1855 | const uint32_t par[]) | |
1856 | { | |
1857 | tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL); | |
1858 | } | |
1859 | ||
426afc3b RH |
1860 | static void translate_smin(DisasContext *dc, const uint32_t arg[], |
1861 | const uint32_t par[]) | |
168c12b0 MF |
1862 | { |
1863 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
426afc3b RH |
1864 | tcg_gen_smin_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); |
1865 | } | |
1866 | } | |
1867 | ||
1868 | static void translate_umin(DisasContext *dc, const uint32_t arg[], | |
1869 | const uint32_t par[]) | |
1870 | { | |
1871 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
1872 | tcg_gen_umin_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); | |
1873 | } | |
1874 | } | |
1875 | ||
1876 | static void translate_smax(DisasContext *dc, const uint32_t arg[], | |
1877 | const uint32_t par[]) | |
1878 | { | |
1879 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
1880 | tcg_gen_smax_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); | |
1881 | } | |
1882 | } | |
1883 | ||
1884 | static void translate_umax(DisasContext *dc, const uint32_t arg[], | |
1885 | const uint32_t par[]) | |
1886 | { | |
1887 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
1888 | tcg_gen_umax_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); | |
168c12b0 MF |
1889 | } |
1890 | } | |
1891 | ||
1892 | static void translate_mov(DisasContext *dc, const uint32_t arg[], | |
1893 | const uint32_t par[]) | |
1894 | { | |
1895 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
1896 | tcg_gen_mov_i32(cpu_R[arg[0]], cpu_R[arg[1]]); | |
1897 | } | |
1898 | } | |
1899 | ||
1900 | static void translate_movcond(DisasContext *dc, const uint32_t arg[], | |
1901 | const uint32_t par[]) | |
1902 | { | |
1903 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
1904 | TCGv_i32 zero = tcg_const_i32(0); | |
1905 | ||
1906 | tcg_gen_movcond_i32(par[0], cpu_R[arg[0]], | |
1907 | cpu_R[arg[2]], zero, cpu_R[arg[1]], cpu_R[arg[0]]); | |
1908 | tcg_temp_free(zero); | |
1909 | } | |
1910 | } | |
1911 | ||
1912 | static void translate_movi(DisasContext *dc, const uint32_t arg[], | |
1913 | const uint32_t par[]) | |
1914 | { | |
1915 | if (gen_window_check1(dc, arg[0])) { | |
1916 | tcg_gen_movi_i32(cpu_R[arg[0]], arg[1]); | |
1917 | } | |
1918 | } | |
1919 | ||
1920 | static void translate_movp(DisasContext *dc, const uint32_t arg[], | |
1921 | const uint32_t par[]) | |
1922 | { | |
1923 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
1924 | TCGv_i32 zero = tcg_const_i32(0); | |
1925 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
1926 | ||
1927 | tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[2]); | |
1928 | tcg_gen_movcond_i32(par[0], | |
1929 | cpu_R[arg[0]], tmp, zero, | |
1930 | cpu_R[arg[1]], cpu_R[arg[0]]); | |
1931 | tcg_temp_free(tmp); | |
1932 | tcg_temp_free(zero); | |
1933 | } | |
1934 | } | |
1935 | ||
1936 | static void translate_movsp(DisasContext *dc, const uint32_t arg[], | |
1937 | const uint32_t par[]) | |
1938 | { | |
1939 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
1940 | TCGv_i32 pc = tcg_const_i32(dc->pc); | |
1941 | gen_helper_movsp(cpu_env, pc); | |
1942 | tcg_gen_mov_i32(cpu_R[arg[0]], cpu_R[arg[1]]); | |
1943 | tcg_temp_free(pc); | |
1944 | } | |
1945 | } | |
1946 | ||
1947 | static void translate_mul16(DisasContext *dc, const uint32_t arg[], | |
1948 | const uint32_t par[]) | |
1949 | { | |
1950 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
1951 | TCGv_i32 v1 = tcg_temp_new_i32(); | |
1952 | TCGv_i32 v2 = tcg_temp_new_i32(); | |
1953 | ||
1954 | if (par[0]) { | |
1955 | tcg_gen_ext16s_i32(v1, cpu_R[arg[1]]); | |
1956 | tcg_gen_ext16s_i32(v2, cpu_R[arg[2]]); | |
1957 | } else { | |
1958 | tcg_gen_ext16u_i32(v1, cpu_R[arg[1]]); | |
1959 | tcg_gen_ext16u_i32(v2, cpu_R[arg[2]]); | |
1960 | } | |
1961 | tcg_gen_mul_i32(cpu_R[arg[0]], v1, v2); | |
1962 | tcg_temp_free(v2); | |
1963 | tcg_temp_free(v1); | |
1964 | } | |
1965 | } | |
1966 | ||
1967 | static void translate_mull(DisasContext *dc, const uint32_t arg[], | |
1968 | const uint32_t par[]) | |
1969 | { | |
1970 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
1971 | tcg_gen_mul_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); | |
1972 | } | |
1973 | } | |
1974 | ||
1975 | static void translate_mulh(DisasContext *dc, const uint32_t arg[], | |
1976 | const uint32_t par[]) | |
1977 | { | |
1978 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
1979 | TCGv_i32 lo = tcg_temp_new(); | |
1980 | ||
1981 | if (par[0]) { | |
1982 | tcg_gen_muls2_i32(lo, cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); | |
1983 | } else { | |
1984 | tcg_gen_mulu2_i32(lo, cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); | |
1985 | } | |
1986 | tcg_temp_free(lo); | |
1987 | } | |
1988 | } | |
1989 | ||
1990 | static void translate_neg(DisasContext *dc, const uint32_t arg[], | |
1991 | const uint32_t par[]) | |
1992 | { | |
1993 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
1994 | tcg_gen_neg_i32(cpu_R[arg[0]], cpu_R[arg[1]]); | |
1995 | } | |
1996 | } | |
1997 | ||
1998 | static void translate_nop(DisasContext *dc, const uint32_t arg[], | |
1999 | const uint32_t par[]) | |
2000 | { | |
2001 | } | |
2002 | ||
2003 | static void translate_nsa(DisasContext *dc, const uint32_t arg[], | |
2004 | const uint32_t par[]) | |
2005 | { | |
2006 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
2007 | tcg_gen_clrsb_i32(cpu_R[arg[0]], cpu_R[arg[1]]); | |
2008 | } | |
2009 | } | |
2010 | ||
2011 | static void translate_nsau(DisasContext *dc, const uint32_t arg[], | |
2012 | const uint32_t par[]) | |
2013 | { | |
2014 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
2015 | tcg_gen_clzi_i32(cpu_R[arg[0]], cpu_R[arg[1]], 32); | |
2016 | } | |
2017 | } | |
2018 | ||
2019 | static void translate_or(DisasContext *dc, const uint32_t arg[], | |
2020 | const uint32_t par[]) | |
2021 | { | |
2022 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
2023 | tcg_gen_or_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); | |
2024 | } | |
2025 | } | |
2026 | ||
2027 | static void translate_ptlb(DisasContext *dc, const uint32_t arg[], | |
2028 | const uint32_t par[]) | |
2029 | { | |
2030 | if (gen_check_privilege(dc) && | |
2031 | gen_window_check2(dc, arg[0], arg[1])) { | |
ba7651fb | 2032 | #ifndef CONFIG_USER_ONLY |
168c12b0 MF |
2033 | TCGv_i32 dtlb = tcg_const_i32(par[0]); |
2034 | ||
2035 | tcg_gen_movi_i32(cpu_pc, dc->pc); | |
2036 | gen_helper_ptlb(cpu_R[arg[0]], cpu_env, cpu_R[arg[1]], dtlb); | |
2037 | tcg_temp_free(dtlb); | |
ba7651fb | 2038 | #endif |
168c12b0 MF |
2039 | } |
2040 | } | |
2041 | ||
2042 | static void gen_zero_check(DisasContext *dc, const uint32_t arg[]) | |
2043 | { | |
2044 | TCGLabel *label = gen_new_label(); | |
2045 | ||
2046 | tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[2]], 0, label); | |
2047 | gen_exception_cause(dc, INTEGER_DIVIDE_BY_ZERO_CAUSE); | |
2048 | gen_set_label(label); | |
2049 | } | |
2050 | ||
2051 | static void translate_quos(DisasContext *dc, const uint32_t arg[], | |
2052 | const uint32_t par[]) | |
2053 | { | |
2054 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
2055 | TCGLabel *label1 = gen_new_label(); | |
2056 | TCGLabel *label2 = gen_new_label(); | |
2057 | ||
2058 | gen_zero_check(dc, arg); | |
2059 | ||
2060 | tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[1]], 0x80000000, | |
2061 | label1); | |
2062 | tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[2]], 0xffffffff, | |
2063 | label1); | |
2064 | tcg_gen_movi_i32(cpu_R[arg[0]], | |
2065 | par[0] ? 0x80000000 : 0); | |
2066 | tcg_gen_br(label2); | |
2067 | gen_set_label(label1); | |
2068 | if (par[0]) { | |
2069 | tcg_gen_div_i32(cpu_R[arg[0]], | |
2070 | cpu_R[arg[1]], cpu_R[arg[2]]); | |
2071 | } else { | |
2072 | tcg_gen_rem_i32(cpu_R[arg[0]], | |
2073 | cpu_R[arg[1]], cpu_R[arg[2]]); | |
2074 | } | |
2075 | gen_set_label(label2); | |
2076 | } | |
2077 | } | |
2078 | ||
2079 | static void translate_quou(DisasContext *dc, const uint32_t arg[], | |
2080 | const uint32_t par[]) | |
2081 | { | |
2082 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
2083 | gen_zero_check(dc, arg); | |
2084 | if (par[0]) { | |
2085 | tcg_gen_divu_i32(cpu_R[arg[0]], | |
2086 | cpu_R[arg[1]], cpu_R[arg[2]]); | |
2087 | } else { | |
2088 | tcg_gen_remu_i32(cpu_R[arg[0]], | |
2089 | cpu_R[arg[1]], cpu_R[arg[2]]); | |
2090 | } | |
2091 | } | |
2092 | } | |
2093 | ||
e9872741 MF |
2094 | static void translate_read_impwire(DisasContext *dc, const uint32_t arg[], |
2095 | const uint32_t par[]) | |
2096 | { | |
2097 | if (gen_window_check1(dc, arg[0])) { | |
2098 | /* TODO: GPIO32 may be a part of coprocessor */ | |
2099 | tcg_gen_movi_i32(cpu_R[arg[0]], 0); | |
2100 | } | |
2101 | } | |
2102 | ||
168c12b0 MF |
2103 | static void translate_rer(DisasContext *dc, const uint32_t arg[], |
2104 | const uint32_t par[]) | |
2105 | { | |
2106 | if (gen_check_privilege(dc) && | |
2107 | gen_window_check2(dc, arg[0], arg[1])) { | |
2108 | gen_helper_rer(cpu_R[arg[0]], cpu_env, cpu_R[arg[1]]); | |
2109 | } | |
2110 | } | |
2111 | ||
2112 | static void translate_ret(DisasContext *dc, const uint32_t arg[], | |
2113 | const uint32_t par[]) | |
2114 | { | |
2115 | gen_jump(dc, cpu_R[0]); | |
2116 | } | |
2117 | ||
2118 | static void translate_retw(DisasContext *dc, const uint32_t arg[], | |
2119 | const uint32_t par[]) | |
2120 | { | |
2121 | TCGv_i32 tmp = tcg_const_i32(dc->pc); | |
2122 | gen_helper_retw(tmp, cpu_env, tmp); | |
2123 | gen_jump(dc, tmp); | |
2124 | tcg_temp_free(tmp); | |
2125 | } | |
2126 | ||
2127 | static void translate_rfde(DisasContext *dc, const uint32_t arg[], | |
2128 | const uint32_t par[]) | |
2129 | { | |
2130 | if (gen_check_privilege(dc)) { | |
2131 | gen_jump(dc, cpu_SR[dc->config->ndepc ? DEPC : EPC1]); | |
2132 | } | |
2133 | } | |
2134 | ||
2135 | static void translate_rfe(DisasContext *dc, const uint32_t arg[], | |
2136 | const uint32_t par[]) | |
2137 | { | |
2138 | if (gen_check_privilege(dc)) { | |
2139 | tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM); | |
2140 | gen_check_interrupts(dc); | |
2141 | gen_jump(dc, cpu_SR[EPC1]); | |
2142 | } | |
2143 | } | |
2144 | ||
2145 | static void translate_rfi(DisasContext *dc, const uint32_t arg[], | |
2146 | const uint32_t par[]) | |
2147 | { | |
2148 | if (gen_check_privilege(dc)) { | |
2149 | tcg_gen_mov_i32(cpu_SR[PS], cpu_SR[EPS2 + arg[0] - 2]); | |
2150 | gen_check_interrupts(dc); | |
2151 | gen_jump(dc, cpu_SR[EPC1 + arg[0] - 1]); | |
2152 | } | |
2153 | } | |
2154 | ||
2155 | static void translate_rfw(DisasContext *dc, const uint32_t arg[], | |
2156 | const uint32_t par[]) | |
2157 | { | |
2158 | if (gen_check_privilege(dc)) { | |
2159 | TCGv_i32 tmp = tcg_const_i32(1); | |
2160 | ||
2161 | tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM); | |
2162 | tcg_gen_shl_i32(tmp, tmp, cpu_SR[WINDOW_BASE]); | |
2163 | ||
2164 | if (par[0]) { | |
2165 | tcg_gen_andc_i32(cpu_SR[WINDOW_START], | |
2166 | cpu_SR[WINDOW_START], tmp); | |
2167 | } else { | |
2168 | tcg_gen_or_i32(cpu_SR[WINDOW_START], | |
2169 | cpu_SR[WINDOW_START], tmp); | |
2170 | } | |
2171 | ||
2172 | gen_helper_restore_owb(cpu_env); | |
2173 | gen_check_interrupts(dc); | |
2174 | gen_jump(dc, cpu_SR[EPC1]); | |
2175 | ||
2176 | tcg_temp_free(tmp); | |
2177 | } | |
2178 | } | |
2179 | ||
2180 | static void translate_rotw(DisasContext *dc, const uint32_t arg[], | |
2181 | const uint32_t par[]) | |
2182 | { | |
2183 | if (gen_check_privilege(dc)) { | |
2184 | TCGv_i32 tmp = tcg_const_i32(arg[0]); | |
2185 | gen_helper_rotw(cpu_env, tmp); | |
2186 | tcg_temp_free(tmp); | |
2187 | /* This can change tb->flags, so exit tb */ | |
2188 | gen_jumpi_check_loop_end(dc, -1); | |
2189 | } | |
2190 | } | |
2191 | ||
2192 | static void translate_rsil(DisasContext *dc, const uint32_t arg[], | |
2193 | const uint32_t par[]) | |
2194 | { | |
2195 | if (gen_check_privilege(dc) && | |
2196 | gen_window_check1(dc, arg[0])) { | |
2197 | tcg_gen_mov_i32(cpu_R[arg[0]], cpu_SR[PS]); | |
2198 | tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL); | |
2199 | tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], arg[1]); | |
2200 | gen_check_interrupts(dc); | |
2201 | gen_jumpi_check_loop_end(dc, 0); | |
2202 | } | |
2203 | } | |
2204 | ||
2205 | static void translate_rsr(DisasContext *dc, const uint32_t arg[], | |
2206 | const uint32_t par[]) | |
2207 | { | |
2208 | if (gen_check_sr(dc, par[0], SR_R) && | |
2209 | (par[0] < 64 || gen_check_privilege(dc)) && | |
2210 | gen_window_check1(dc, arg[0])) { | |
2211 | if (gen_rsr(dc, cpu_R[arg[0]], par[0])) { | |
2212 | gen_jumpi_check_loop_end(dc, 0); | |
2213 | } | |
2214 | } | |
2215 | } | |
2216 | ||
2217 | static void translate_rtlb(DisasContext *dc, const uint32_t arg[], | |
2218 | const uint32_t par[]) | |
2219 | { | |
2220 | static void (* const helper[])(TCGv_i32 r, TCGv_env env, TCGv_i32 a1, | |
2221 | TCGv_i32 a2) = { | |
ba7651fb | 2222 | #ifndef CONFIG_USER_ONLY |
168c12b0 MF |
2223 | gen_helper_rtlb0, |
2224 | gen_helper_rtlb1, | |
ba7651fb | 2225 | #endif |
168c12b0 MF |
2226 | }; |
2227 | ||
2228 | if (gen_check_privilege(dc) && | |
2229 | gen_window_check2(dc, arg[0], arg[1])) { | |
2230 | TCGv_i32 dtlb = tcg_const_i32(par[0]); | |
2231 | ||
2232 | helper[par[1]](cpu_R[arg[0]], cpu_env, cpu_R[arg[1]], dtlb); | |
2233 | tcg_temp_free(dtlb); | |
2234 | } | |
2235 | } | |
2236 | ||
2237 | static void translate_rur(DisasContext *dc, const uint32_t arg[], | |
2238 | const uint32_t par[]) | |
2239 | { | |
2240 | if (gen_window_check1(dc, arg[0])) { | |
2241 | if (uregnames[par[0]].name) { | |
2242 | tcg_gen_mov_i32(cpu_R[arg[0]], cpu_UR[par[0]]); | |
2243 | } else { | |
8e96f594 | 2244 | qemu_log_mask(LOG_UNIMP, "RUR %d not implemented\n", par[0]); |
168c12b0 MF |
2245 | } |
2246 | } | |
2247 | } | |
2248 | ||
e9872741 MF |
2249 | static void translate_setb_expstate(DisasContext *dc, const uint32_t arg[], |
2250 | const uint32_t par[]) | |
2251 | { | |
2252 | /* TODO: GPIO32 may be a part of coprocessor */ | |
2253 | tcg_gen_ori_i32(cpu_UR[EXPSTATE], cpu_UR[EXPSTATE], 1u << arg[0]); | |
2254 | } | |
2255 | ||
9fb40342 MF |
2256 | #ifdef CONFIG_USER_ONLY |
2257 | static void gen_check_atomctl(DisasContext *dc, TCGv_i32 addr) | |
2258 | { | |
2259 | } | |
2260 | #else | |
2261 | static void gen_check_atomctl(DisasContext *dc, TCGv_i32 addr) | |
2262 | { | |
2263 | TCGv_i32 tpc = tcg_const_i32(dc->pc); | |
2264 | ||
2265 | gen_helper_check_atomctl(cpu_env, tpc, addr); | |
2266 | tcg_temp_free(tpc); | |
2267 | } | |
2268 | #endif | |
2269 | ||
168c12b0 MF |
2270 | static void translate_s32c1i(DisasContext *dc, const uint32_t arg[], |
2271 | const uint32_t par[]) | |
2272 | { | |
2273 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
168c12b0 MF |
2274 | TCGv_i32 tmp = tcg_temp_local_new_i32(); |
2275 | TCGv_i32 addr = tcg_temp_local_new_i32(); | |
168c12b0 MF |
2276 | |
2277 | tcg_gen_mov_i32(tmp, cpu_R[arg[0]]); | |
2278 | tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); | |
2279 | gen_load_store_alignment(dc, 2, addr, true); | |
9fb40342 MF |
2280 | gen_check_atomctl(dc, addr); |
2281 | tcg_gen_atomic_cmpxchg_i32(cpu_R[arg[0]], addr, cpu_SR[SCOMPARE1], | |
2282 | tmp, dc->cring, MO_32); | |
168c12b0 MF |
2283 | tcg_temp_free(addr); |
2284 | tcg_temp_free(tmp); | |
2285 | } | |
2286 | } | |
2287 | ||
2288 | static void translate_s32e(DisasContext *dc, const uint32_t arg[], | |
2289 | const uint32_t par[]) | |
2290 | { | |
2291 | if (gen_check_privilege(dc) && | |
2292 | gen_window_check2(dc, arg[0], arg[1])) { | |
2293 | TCGv_i32 addr = tcg_temp_new_i32(); | |
2294 | ||
2295 | tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); | |
2296 | gen_load_store_alignment(dc, 2, addr, false); | |
2297 | tcg_gen_qemu_st_tl(cpu_R[arg[0]], addr, dc->ring, MO_TEUL); | |
2298 | tcg_temp_free(addr); | |
2299 | } | |
2300 | } | |
2301 | ||
d1e9b006 MF |
2302 | static void translate_salt(DisasContext *dc, const uint32_t arg[], |
2303 | const uint32_t par[]) | |
2304 | { | |
2305 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
2306 | tcg_gen_setcond_i32(par[0], | |
2307 | cpu_R[arg[0]], | |
2308 | cpu_R[arg[1]], cpu_R[arg[2]]); | |
2309 | } | |
2310 | } | |
2311 | ||
168c12b0 MF |
2312 | static void translate_sext(DisasContext *dc, const uint32_t arg[], |
2313 | const uint32_t par[]) | |
2314 | { | |
2315 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
2316 | int shift = 31 - arg[2]; | |
2317 | ||
2318 | if (shift == 24) { | |
2319 | tcg_gen_ext8s_i32(cpu_R[arg[0]], cpu_R[arg[1]]); | |
2320 | } else if (shift == 16) { | |
2321 | tcg_gen_ext16s_i32(cpu_R[arg[0]], cpu_R[arg[1]]); | |
2322 | } else { | |
2323 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
2324 | tcg_gen_shli_i32(tmp, cpu_R[arg[1]], shift); | |
2325 | tcg_gen_sari_i32(cpu_R[arg[0]], tmp, shift); | |
2326 | tcg_temp_free(tmp); | |
2327 | } | |
2328 | } | |
2329 | } | |
2330 | ||
2331 | static void translate_simcall(DisasContext *dc, const uint32_t arg[], | |
2332 | const uint32_t par[]) | |
2333 | { | |
ba7651fb | 2334 | #ifndef CONFIG_USER_ONLY |
168c12b0 MF |
2335 | if (semihosting_enabled()) { |
2336 | if (gen_check_privilege(dc)) { | |
2337 | gen_helper_simcall(cpu_env); | |
2338 | } | |
ba7651fb MF |
2339 | } else |
2340 | #endif | |
2341 | { | |
168c12b0 MF |
2342 | qemu_log_mask(LOG_GUEST_ERROR, "SIMCALL but semihosting is disabled\n"); |
2343 | gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); | |
2344 | } | |
2345 | } | |
2346 | ||
2347 | /* | |
2348 | * Note: 64 bit ops are used here solely because SAR values | |
2349 | * have range 0..63 | |
2350 | */ | |
2351 | #define gen_shift_reg(cmd, reg) do { \ | |
2352 | TCGv_i64 tmp = tcg_temp_new_i64(); \ | |
2353 | tcg_gen_extu_i32_i64(tmp, reg); \ | |
2354 | tcg_gen_##cmd##_i64(v, v, tmp); \ | |
2355 | tcg_gen_extrl_i64_i32(cpu_R[arg[0]], v); \ | |
2356 | tcg_temp_free_i64(v); \ | |
2357 | tcg_temp_free_i64(tmp); \ | |
2358 | } while (0) | |
2359 | ||
2360 | #define gen_shift(cmd) gen_shift_reg(cmd, cpu_SR[SAR]) | |
2361 | ||
2362 | static void translate_sll(DisasContext *dc, const uint32_t arg[], | |
2363 | const uint32_t par[]) | |
2364 | { | |
2365 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
2366 | if (dc->sar_m32_5bit) { | |
2367 | tcg_gen_shl_i32(cpu_R[arg[0]], cpu_R[arg[1]], dc->sar_m32); | |
2368 | } else { | |
2369 | TCGv_i64 v = tcg_temp_new_i64(); | |
2370 | TCGv_i32 s = tcg_const_i32(32); | |
2371 | tcg_gen_sub_i32(s, s, cpu_SR[SAR]); | |
2372 | tcg_gen_andi_i32(s, s, 0x3f); | |
2373 | tcg_gen_extu_i32_i64(v, cpu_R[arg[1]]); | |
2374 | gen_shift_reg(shl, s); | |
2375 | tcg_temp_free(s); | |
2376 | } | |
2377 | } | |
2378 | } | |
2379 | ||
2380 | static void translate_slli(DisasContext *dc, const uint32_t arg[], | |
2381 | const uint32_t par[]) | |
2382 | { | |
2383 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
2384 | if (arg[2] == 32) { | |
8e96f594 | 2385 | qemu_log_mask(LOG_GUEST_ERROR, "slli a%d, a%d, 32 is undefined\n", |
168c12b0 MF |
2386 | arg[0], arg[1]); |
2387 | } | |
2388 | tcg_gen_shli_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2] & 0x1f); | |
2389 | } | |
2390 | } | |
2391 | ||
2392 | static void translate_sra(DisasContext *dc, const uint32_t arg[], | |
2393 | const uint32_t par[]) | |
2394 | { | |
2395 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
2396 | if (dc->sar_m32_5bit) { | |
2397 | tcg_gen_sar_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_SR[SAR]); | |
2398 | } else { | |
2399 | TCGv_i64 v = tcg_temp_new_i64(); | |
2400 | tcg_gen_ext_i32_i64(v, cpu_R[arg[1]]); | |
2401 | gen_shift(sar); | |
2402 | } | |
2403 | } | |
2404 | } | |
2405 | ||
2406 | static void translate_srai(DisasContext *dc, const uint32_t arg[], | |
2407 | const uint32_t par[]) | |
2408 | { | |
2409 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
2410 | tcg_gen_sari_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]); | |
2411 | } | |
2412 | } | |
2413 | ||
2414 | static void translate_src(DisasContext *dc, const uint32_t arg[], | |
2415 | const uint32_t par[]) | |
2416 | { | |
2417 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
2418 | TCGv_i64 v = tcg_temp_new_i64(); | |
2419 | tcg_gen_concat_i32_i64(v, cpu_R[arg[2]], cpu_R[arg[1]]); | |
2420 | gen_shift(shr); | |
2421 | } | |
2422 | } | |
2423 | ||
2424 | static void translate_srl(DisasContext *dc, const uint32_t arg[], | |
2425 | const uint32_t par[]) | |
2426 | { | |
2427 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
2428 | if (dc->sar_m32_5bit) { | |
2429 | tcg_gen_shr_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_SR[SAR]); | |
2430 | } else { | |
2431 | TCGv_i64 v = tcg_temp_new_i64(); | |
2432 | tcg_gen_extu_i32_i64(v, cpu_R[arg[1]]); | |
2433 | gen_shift(shr); | |
2434 | } | |
2435 | } | |
2436 | } | |
2437 | ||
2438 | #undef gen_shift | |
2439 | #undef gen_shift_reg | |
2440 | ||
2441 | static void translate_srli(DisasContext *dc, const uint32_t arg[], | |
2442 | const uint32_t par[]) | |
2443 | { | |
2444 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
2445 | tcg_gen_shri_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]); | |
2446 | } | |
2447 | } | |
2448 | ||
2449 | static void translate_ssa8b(DisasContext *dc, const uint32_t arg[], | |
2450 | const uint32_t par[]) | |
2451 | { | |
2452 | if (gen_window_check1(dc, arg[0])) { | |
2453 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
2454 | tcg_gen_shli_i32(tmp, cpu_R[arg[0]], 3); | |
2455 | gen_left_shift_sar(dc, tmp); | |
2456 | tcg_temp_free(tmp); | |
2457 | } | |
2458 | } | |
2459 | ||
2460 | static void translate_ssa8l(DisasContext *dc, const uint32_t arg[], | |
2461 | const uint32_t par[]) | |
2462 | { | |
2463 | if (gen_window_check1(dc, arg[0])) { | |
2464 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
2465 | tcg_gen_shli_i32(tmp, cpu_R[arg[0]], 3); | |
2466 | gen_right_shift_sar(dc, tmp); | |
2467 | tcg_temp_free(tmp); | |
2468 | } | |
2469 | } | |
2470 | ||
2471 | static void translate_ssai(DisasContext *dc, const uint32_t arg[], | |
2472 | const uint32_t par[]) | |
2473 | { | |
2474 | TCGv_i32 tmp = tcg_const_i32(arg[0]); | |
2475 | gen_right_shift_sar(dc, tmp); | |
2476 | tcg_temp_free(tmp); | |
2477 | } | |
2478 | ||
2479 | static void translate_ssl(DisasContext *dc, const uint32_t arg[], | |
2480 | const uint32_t par[]) | |
2481 | { | |
2482 | if (gen_window_check1(dc, arg[0])) { | |
2483 | gen_left_shift_sar(dc, cpu_R[arg[0]]); | |
2484 | } | |
2485 | } | |
2486 | ||
2487 | static void translate_ssr(DisasContext *dc, const uint32_t arg[], | |
2488 | const uint32_t par[]) | |
2489 | { | |
2490 | if (gen_window_check1(dc, arg[0])) { | |
2491 | gen_right_shift_sar(dc, cpu_R[arg[0]]); | |
2492 | } | |
2493 | } | |
2494 | ||
2495 | static void translate_sub(DisasContext *dc, const uint32_t arg[], | |
2496 | const uint32_t par[]) | |
2497 | { | |
2498 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
2499 | tcg_gen_sub_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); | |
2500 | } | |
2501 | } | |
2502 | ||
2503 | static void translate_subx(DisasContext *dc, const uint32_t arg[], | |
2504 | const uint32_t par[]) | |
2505 | { | |
2506 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
2507 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
2508 | tcg_gen_shli_i32(tmp, cpu_R[arg[1]], par[0]); | |
2509 | tcg_gen_sub_i32(cpu_R[arg[0]], tmp, cpu_R[arg[2]]); | |
2510 | tcg_temp_free(tmp); | |
2511 | } | |
2512 | } | |
2513 | ||
2514 | static void translate_syscall(DisasContext *dc, const uint32_t arg[], | |
2515 | const uint32_t par[]) | |
2516 | { | |
2517 | gen_exception_cause(dc, SYSCALL_CAUSE); | |
2518 | } | |
2519 | ||
2520 | static void translate_waiti(DisasContext *dc, const uint32_t arg[], | |
2521 | const uint32_t par[]) | |
2522 | { | |
2523 | if (gen_check_privilege(dc)) { | |
ba7651fb | 2524 | #ifndef CONFIG_USER_ONLY |
168c12b0 | 2525 | gen_waiti(dc, arg[0]); |
ba7651fb | 2526 | #endif |
168c12b0 MF |
2527 | } |
2528 | } | |
2529 | ||
2530 | static void translate_wtlb(DisasContext *dc, const uint32_t arg[], | |
2531 | const uint32_t par[]) | |
2532 | { | |
2533 | if (gen_check_privilege(dc) && | |
2534 | gen_window_check2(dc, arg[0], arg[1])) { | |
ba7651fb | 2535 | #ifndef CONFIG_USER_ONLY |
168c12b0 MF |
2536 | TCGv_i32 dtlb = tcg_const_i32(par[0]); |
2537 | ||
2538 | gen_helper_wtlb(cpu_env, cpu_R[arg[0]], cpu_R[arg[1]], dtlb); | |
2539 | /* This could change memory mapping, so exit tb */ | |
2540 | gen_jumpi_check_loop_end(dc, -1); | |
2541 | tcg_temp_free(dtlb); | |
ba7651fb | 2542 | #endif |
168c12b0 MF |
2543 | } |
2544 | } | |
2545 | ||
2546 | static void translate_wer(DisasContext *dc, const uint32_t arg[], | |
2547 | const uint32_t par[]) | |
2548 | { | |
2549 | if (gen_check_privilege(dc) && | |
2550 | gen_window_check2(dc, arg[0], arg[1])) { | |
2551 | gen_helper_wer(cpu_env, cpu_R[arg[0]], cpu_R[arg[1]]); | |
2552 | } | |
2553 | } | |
2554 | ||
e9872741 MF |
2555 | static void translate_wrmsk_expstate(DisasContext *dc, const uint32_t arg[], |
2556 | const uint32_t par[]) | |
2557 | { | |
2558 | if (gen_window_check2(dc, arg[0], arg[1])) { | |
2559 | /* TODO: GPIO32 may be a part of coprocessor */ | |
2560 | tcg_gen_and_i32(cpu_UR[EXPSTATE], cpu_R[arg[0]], cpu_R[arg[1]]); | |
2561 | } | |
2562 | } | |
2563 | ||
168c12b0 MF |
2564 | static void translate_wsr(DisasContext *dc, const uint32_t arg[], |
2565 | const uint32_t par[]) | |
2566 | { | |
2567 | if (gen_check_sr(dc, par[0], SR_W) && | |
2568 | (par[0] < 64 || gen_check_privilege(dc)) && | |
2569 | gen_window_check1(dc, arg[0])) { | |
2570 | gen_wsr(dc, par[0], cpu_R[arg[0]]); | |
2571 | } | |
2572 | } | |
2573 | ||
2574 | static void translate_wur(DisasContext *dc, const uint32_t arg[], | |
2575 | const uint32_t par[]) | |
2576 | { | |
2577 | if (gen_window_check1(dc, arg[0])) { | |
2578 | if (uregnames[par[0]].name) { | |
2579 | gen_wur(par[0], cpu_R[arg[0]]); | |
2580 | } else { | |
8e96f594 | 2581 | qemu_log_mask(LOG_UNIMP, "WUR %d not implemented\n", par[0]); |
168c12b0 MF |
2582 | } |
2583 | } | |
2584 | } | |
2585 | ||
2586 | static void translate_xor(DisasContext *dc, const uint32_t arg[], | |
2587 | const uint32_t par[]) | |
2588 | { | |
2589 | if (gen_window_check3(dc, arg[0], arg[1], arg[2])) { | |
2590 | tcg_gen_xor_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]); | |
2591 | } | |
2592 | } | |
2593 | ||
2594 | static void translate_xsr(DisasContext *dc, const uint32_t arg[], | |
2595 | const uint32_t par[]) | |
2596 | { | |
2597 | if (gen_check_sr(dc, par[0], SR_X) && | |
2598 | (par[0] < 64 || gen_check_privilege(dc)) && | |
2599 | gen_window_check1(dc, arg[0])) { | |
2600 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
2601 | bool rsr_end, wsr_end; | |
2602 | ||
2603 | tcg_gen_mov_i32(tmp, cpu_R[arg[0]]); | |
2604 | rsr_end = gen_rsr(dc, cpu_R[arg[0]], par[0]); | |
2605 | wsr_end = gen_wsr(dc, par[0], tmp); | |
2606 | tcg_temp_free(tmp); | |
2607 | if (rsr_end && !wsr_end) { | |
2608 | gen_jumpi_check_loop_end(dc, 0); | |
2609 | } | |
2610 | } | |
2611 | } | |
2612 | ||
2613 | static const XtensaOpcodeOps core_ops[] = { | |
2614 | { | |
2615 | .name = "abs", | |
2616 | .translate = translate_abs, | |
2617 | }, { | |
2618 | .name = "add", | |
2619 | .translate = translate_add, | |
2620 | }, { | |
2621 | .name = "add.n", | |
2622 | .translate = translate_add, | |
2623 | }, { | |
2624 | .name = "addi", | |
2625 | .translate = translate_addi, | |
2626 | }, { | |
2627 | .name = "addi.n", | |
2628 | .translate = translate_addi, | |
2629 | }, { | |
2630 | .name = "addmi", | |
2631 | .translate = translate_addi, | |
2632 | }, { | |
2633 | .name = "addx2", | |
2634 | .translate = translate_addx, | |
2635 | .par = (const uint32_t[]){1}, | |
2636 | }, { | |
2637 | .name = "addx4", | |
2638 | .translate = translate_addx, | |
2639 | .par = (const uint32_t[]){2}, | |
2640 | }, { | |
2641 | .name = "addx8", | |
2642 | .translate = translate_addx, | |
2643 | .par = (const uint32_t[]){3}, | |
2644 | }, { | |
2645 | .name = "all4", | |
2646 | .translate = translate_all, | |
2647 | .par = (const uint32_t[]){true, 4}, | |
2648 | }, { | |
2649 | .name = "all8", | |
2650 | .translate = translate_all, | |
2651 | .par = (const uint32_t[]){true, 8}, | |
2652 | }, { | |
2653 | .name = "and", | |
2654 | .translate = translate_and, | |
2655 | }, { | |
2656 | .name = "andb", | |
2657 | .translate = translate_boolean, | |
2658 | .par = (const uint32_t[]){BOOLEAN_AND}, | |
2659 | }, { | |
2660 | .name = "andbc", | |
2661 | .translate = translate_boolean, | |
2662 | .par = (const uint32_t[]){BOOLEAN_ANDC}, | |
2663 | }, { | |
2664 | .name = "any4", | |
2665 | .translate = translate_all, | |
2666 | .par = (const uint32_t[]){false, 4}, | |
2667 | }, { | |
2668 | .name = "any8", | |
2669 | .translate = translate_all, | |
2670 | .par = (const uint32_t[]){false, 8}, | |
2671 | }, { | |
2672 | .name = "ball", | |
2673 | .translate = translate_ball, | |
2674 | .par = (const uint32_t[]){TCG_COND_EQ}, | |
2675 | }, { | |
2676 | .name = "bany", | |
2677 | .translate = translate_bany, | |
2678 | .par = (const uint32_t[]){TCG_COND_NE}, | |
2679 | }, { | |
2680 | .name = "bbc", | |
2681 | .translate = translate_bb, | |
2682 | .par = (const uint32_t[]){TCG_COND_EQ}, | |
2683 | }, { | |
2684 | .name = "bbci", | |
2685 | .translate = translate_bbi, | |
2686 | .par = (const uint32_t[]){TCG_COND_EQ}, | |
2687 | }, { | |
2688 | .name = "bbs", | |
2689 | .translate = translate_bb, | |
2690 | .par = (const uint32_t[]){TCG_COND_NE}, | |
2691 | }, { | |
2692 | .name = "bbsi", | |
2693 | .translate = translate_bbi, | |
2694 | .par = (const uint32_t[]){TCG_COND_NE}, | |
2695 | }, { | |
2696 | .name = "beq", | |
2697 | .translate = translate_b, | |
2698 | .par = (const uint32_t[]){TCG_COND_EQ}, | |
2699 | }, { | |
2700 | .name = "beqi", | |
2701 | .translate = translate_bi, | |
2702 | .par = (const uint32_t[]){TCG_COND_EQ}, | |
2703 | }, { | |
2704 | .name = "beqz", | |
2705 | .translate = translate_bz, | |
2706 | .par = (const uint32_t[]){TCG_COND_EQ}, | |
2707 | }, { | |
2708 | .name = "beqz.n", | |
2709 | .translate = translate_bz, | |
2710 | .par = (const uint32_t[]){TCG_COND_EQ}, | |
2711 | }, { | |
2712 | .name = "bf", | |
2713 | .translate = translate_bp, | |
2714 | .par = (const uint32_t[]){TCG_COND_EQ}, | |
2715 | }, { | |
2716 | .name = "bge", | |
2717 | .translate = translate_b, | |
2718 | .par = (const uint32_t[]){TCG_COND_GE}, | |
2719 | }, { | |
2720 | .name = "bgei", | |
2721 | .translate = translate_bi, | |
2722 | .par = (const uint32_t[]){TCG_COND_GE}, | |
2723 | }, { | |
2724 | .name = "bgeu", | |
2725 | .translate = translate_b, | |
2726 | .par = (const uint32_t[]){TCG_COND_GEU}, | |
2727 | }, { | |
2728 | .name = "bgeui", | |
2729 | .translate = translate_bi, | |
2730 | .par = (const uint32_t[]){TCG_COND_GEU}, | |
2731 | }, { | |
2732 | .name = "bgez", | |
2733 | .translate = translate_bz, | |
2734 | .par = (const uint32_t[]){TCG_COND_GE}, | |
2735 | }, { | |
2736 | .name = "blt", | |
2737 | .translate = translate_b, | |
2738 | .par = (const uint32_t[]){TCG_COND_LT}, | |
2739 | }, { | |
2740 | .name = "blti", | |
2741 | .translate = translate_bi, | |
2742 | .par = (const uint32_t[]){TCG_COND_LT}, | |
2743 | }, { | |
2744 | .name = "bltu", | |
2745 | .translate = translate_b, | |
2746 | .par = (const uint32_t[]){TCG_COND_LTU}, | |
2747 | }, { | |
2748 | .name = "bltui", | |
2749 | .translate = translate_bi, | |
2750 | .par = (const uint32_t[]){TCG_COND_LTU}, | |
2751 | }, { | |
2752 | .name = "bltz", | |
2753 | .translate = translate_bz, | |
2754 | .par = (const uint32_t[]){TCG_COND_LT}, | |
2755 | }, { | |
2756 | .name = "bnall", | |
2757 | .translate = translate_ball, | |
2758 | .par = (const uint32_t[]){TCG_COND_NE}, | |
2759 | }, { | |
2760 | .name = "bne", | |
2761 | .translate = translate_b, | |
2762 | .par = (const uint32_t[]){TCG_COND_NE}, | |
2763 | }, { | |
2764 | .name = "bnei", | |
2765 | .translate = translate_bi, | |
2766 | .par = (const uint32_t[]){TCG_COND_NE}, | |
2767 | }, { | |
2768 | .name = "bnez", | |
2769 | .translate = translate_bz, | |
2770 | .par = (const uint32_t[]){TCG_COND_NE}, | |
2771 | }, { | |
2772 | .name = "bnez.n", | |
2773 | .translate = translate_bz, | |
2774 | .par = (const uint32_t[]){TCG_COND_NE}, | |
2775 | }, { | |
2776 | .name = "bnone", | |
2777 | .translate = translate_bany, | |
2778 | .par = (const uint32_t[]){TCG_COND_EQ}, | |
2779 | }, { | |
2780 | .name = "break", | |
2781 | .translate = translate_break, | |
2782 | .par = (const uint32_t[]){DEBUGCAUSE_BI}, | |
2783 | }, { | |
2784 | .name = "break.n", | |
2785 | .translate = translate_break, | |
2786 | .par = (const uint32_t[]){DEBUGCAUSE_BN}, | |
2787 | }, { | |
2788 | .name = "bt", | |
2789 | .translate = translate_bp, | |
2790 | .par = (const uint32_t[]){TCG_COND_NE}, | |
2791 | }, { | |
2792 | .name = "call0", | |
2793 | .translate = translate_call0, | |
2794 | }, { | |
2795 | .name = "call12", | |
2796 | .translate = translate_callw, | |
2797 | .par = (const uint32_t[]){3}, | |
2798 | }, { | |
2799 | .name = "call4", | |
2800 | .translate = translate_callw, | |
2801 | .par = (const uint32_t[]){1}, | |
2802 | }, { | |
2803 | .name = "call8", | |
2804 | .translate = translate_callw, | |
2805 | .par = (const uint32_t[]){2}, | |
2806 | }, { | |
2807 | .name = "callx0", | |
2808 | .translate = translate_callx0, | |
2809 | }, { | |
2810 | .name = "callx12", | |
2811 | .translate = translate_callxw, | |
2812 | .par = (const uint32_t[]){3}, | |
2813 | }, { | |
2814 | .name = "callx4", | |
2815 | .translate = translate_callxw, | |
2816 | .par = (const uint32_t[]){1}, | |
2817 | }, { | |
2818 | .name = "callx8", | |
2819 | .translate = translate_callxw, | |
2820 | .par = (const uint32_t[]){2}, | |
2821 | }, { | |
2822 | .name = "clamps", | |
2823 | .translate = translate_clamps, | |
e9872741 MF |
2824 | }, { |
2825 | .name = "clrb_expstate", | |
2826 | .translate = translate_clrb_expstate, | |
c5ac936e MF |
2827 | }, { |
2828 | .name = "const16", | |
2829 | .translate = translate_const16, | |
168c12b0 MF |
2830 | }, { |
2831 | .name = "depbits", | |
2832 | .translate = translate_depbits, | |
2833 | }, { | |
2834 | .name = "dhi", | |
2835 | .translate = translate_dcache, | |
2836 | .par = (const uint32_t[]){true, true}, | |
2837 | }, { | |
2838 | .name = "dhu", | |
2839 | .translate = translate_dcache, | |
2840 | .par = (const uint32_t[]){true, true}, | |
2841 | }, { | |
2842 | .name = "dhwb", | |
2843 | .translate = translate_dcache, | |
2844 | .par = (const uint32_t[]){false, true}, | |
2845 | }, { | |
2846 | .name = "dhwbi", | |
2847 | .translate = translate_dcache, | |
2848 | .par = (const uint32_t[]){false, true}, | |
2849 | }, { | |
2850 | .name = "dii", | |
2851 | .translate = translate_dcache, | |
2852 | .par = (const uint32_t[]){true, false}, | |
2853 | }, { | |
2854 | .name = "diu", | |
2855 | .translate = translate_dcache, | |
2856 | .par = (const uint32_t[]){true, false}, | |
2857 | }, { | |
2858 | .name = "diwb", | |
2859 | .translate = translate_dcache, | |
2860 | .par = (const uint32_t[]){true, false}, | |
2861 | }, { | |
2862 | .name = "diwbi", | |
2863 | .translate = translate_dcache, | |
2864 | .par = (const uint32_t[]){true, false}, | |
2865 | }, { | |
2866 | .name = "dpfl", | |
2867 | .translate = translate_dcache, | |
2868 | .par = (const uint32_t[]){true, true}, | |
2869 | }, { | |
2870 | .name = "dpfr", | |
2871 | .translate = translate_dcache, | |
2872 | .par = (const uint32_t[]){false, false}, | |
2873 | }, { | |
2874 | .name = "dpfro", | |
2875 | .translate = translate_dcache, | |
2876 | .par = (const uint32_t[]){false, false}, | |
2877 | }, { | |
2878 | .name = "dpfw", | |
2879 | .translate = translate_dcache, | |
2880 | .par = (const uint32_t[]){false, false}, | |
2881 | }, { | |
2882 | .name = "dpfwo", | |
2883 | .translate = translate_dcache, | |
2884 | .par = (const uint32_t[]){false, false}, | |
2885 | }, { | |
2886 | .name = "dsync", | |
2887 | .translate = translate_nop, | |
2888 | }, { | |
2889 | .name = "entry", | |
2890 | .translate = translate_entry, | |
2891 | }, { | |
2892 | .name = "esync", | |
2893 | .translate = translate_nop, | |
2894 | }, { | |
2895 | .name = "excw", | |
2896 | .translate = translate_nop, | |
2897 | }, { | |
2898 | .name = "extui", | |
2899 | .translate = translate_extui, | |
2900 | }, { | |
2901 | .name = "extw", | |
9fb40342 | 2902 | .translate = translate_memw, |
13f6a7cd MF |
2903 | }, { |
2904 | .name = "hwwdtlba", | |
2905 | .translate = translate_ill, | |
2906 | }, { | |
2907 | .name = "hwwitlba", | |
2908 | .translate = translate_ill, | |
168c12b0 MF |
2909 | }, { |
2910 | .name = "idtlb", | |
2911 | .translate = translate_itlb, | |
2912 | .par = (const uint32_t[]){true}, | |
2913 | }, { | |
2914 | .name = "ihi", | |
2915 | .translate = translate_icache, | |
2916 | .par = (const uint32_t[]){false, true}, | |
2917 | }, { | |
2918 | .name = "ihu", | |
2919 | .translate = translate_icache, | |
2920 | .par = (const uint32_t[]){true, true}, | |
2921 | }, { | |
2922 | .name = "iii", | |
2923 | .translate = translate_icache, | |
2924 | .par = (const uint32_t[]){true, false}, | |
2925 | }, { | |
2926 | .name = "iitlb", | |
2927 | .translate = translate_itlb, | |
2928 | .par = (const uint32_t[]){false}, | |
2929 | }, { | |
2930 | .name = "iiu", | |
2931 | .translate = translate_icache, | |
2932 | .par = (const uint32_t[]){true, false}, | |
2933 | }, { | |
2934 | .name = "ill", | |
2935 | .translate = translate_ill, | |
2936 | }, { | |
2937 | .name = "ill.n", | |
2938 | .translate = translate_ill, | |
2939 | }, { | |
2940 | .name = "ipf", | |
2941 | .translate = translate_icache, | |
2942 | .par = (const uint32_t[]){false, false}, | |
2943 | }, { | |
2944 | .name = "ipfl", | |
2945 | .translate = translate_icache, | |
2946 | .par = (const uint32_t[]){true, true}, | |
2947 | }, { | |
2948 | .name = "isync", | |
2949 | .translate = translate_nop, | |
2950 | }, { | |
2951 | .name = "j", | |
2952 | .translate = translate_j, | |
2953 | }, { | |
2954 | .name = "jx", | |
2955 | .translate = translate_jx, | |
2956 | }, { | |
2957 | .name = "l16si", | |
2958 | .translate = translate_ldst, | |
2959 | .par = (const uint32_t[]){MO_TESW, false, false}, | |
2960 | }, { | |
2961 | .name = "l16ui", | |
2962 | .translate = translate_ldst, | |
2963 | .par = (const uint32_t[]){MO_TEUW, false, false}, | |
2964 | }, { | |
2965 | .name = "l32ai", | |
2966 | .translate = translate_ldst, | |
2967 | .par = (const uint32_t[]){MO_TEUL, true, false}, | |
2968 | }, { | |
2969 | .name = "l32e", | |
2970 | .translate = translate_l32e, | |
2971 | }, { | |
2972 | .name = "l32i", | |
2973 | .translate = translate_ldst, | |
2974 | .par = (const uint32_t[]){MO_TEUL, false, false}, | |
2975 | }, { | |
2976 | .name = "l32i.n", | |
2977 | .translate = translate_ldst, | |
2978 | .par = (const uint32_t[]){MO_TEUL, false, false}, | |
2979 | }, { | |
2980 | .name = "l32r", | |
2981 | .translate = translate_l32r, | |
2982 | }, { | |
2983 | .name = "l8ui", | |
2984 | .translate = translate_ldst, | |
2985 | .par = (const uint32_t[]){MO_UB, false, false}, | |
2986 | }, { | |
2987 | .name = "lddec", | |
2988 | .translate = translate_mac16, | |
2989 | .par = (const uint32_t[]){MAC16_NONE, 0, 0, -4}, | |
2990 | }, { | |
2991 | .name = "ldinc", | |
2992 | .translate = translate_mac16, | |
2993 | .par = (const uint32_t[]){MAC16_NONE, 0, 0, 4}, | |
13f6a7cd MF |
2994 | }, { |
2995 | .name = "ldpte", | |
2996 | .translate = translate_ill, | |
168c12b0 MF |
2997 | }, { |
2998 | .name = "loop", | |
2999 | .translate = translate_loop, | |
3000 | .par = (const uint32_t[]){TCG_COND_NEVER}, | |
3001 | }, { | |
3002 | .name = "loopgtz", | |
3003 | .translate = translate_loop, | |
3004 | .par = (const uint32_t[]){TCG_COND_GT}, | |
3005 | }, { | |
3006 | .name = "loopnez", | |
3007 | .translate = translate_loop, | |
3008 | .par = (const uint32_t[]){TCG_COND_NE}, | |
3009 | }, { | |
3010 | .name = "max", | |
426afc3b | 3011 | .translate = translate_smax, |
168c12b0 MF |
3012 | }, { |
3013 | .name = "maxu", | |
426afc3b | 3014 | .translate = translate_umax, |
168c12b0 MF |
3015 | }, { |
3016 | .name = "memw", | |
9fb40342 | 3017 | .translate = translate_memw, |
168c12b0 MF |
3018 | }, { |
3019 | .name = "min", | |
426afc3b | 3020 | .translate = translate_smin, |
168c12b0 MF |
3021 | }, { |
3022 | .name = "minu", | |
426afc3b | 3023 | .translate = translate_umin, |
168c12b0 MF |
3024 | }, { |
3025 | .name = "mov", | |
3026 | .translate = translate_mov, | |
3027 | }, { | |
3028 | .name = "mov.n", | |
3029 | .translate = translate_mov, | |
3030 | }, { | |
3031 | .name = "moveqz", | |
3032 | .translate = translate_movcond, | |
3033 | .par = (const uint32_t[]){TCG_COND_EQ}, | |
3034 | }, { | |
3035 | .name = "movf", | |
3036 | .translate = translate_movp, | |
3037 | .par = (const uint32_t[]){TCG_COND_EQ}, | |
3038 | }, { | |
3039 | .name = "movgez", | |
3040 | .translate = translate_movcond, | |
3041 | .par = (const uint32_t[]){TCG_COND_GE}, | |
3042 | }, { | |
3043 | .name = "movi", | |
3044 | .translate = translate_movi, | |
3045 | }, { | |
3046 | .name = "movi.n", | |
3047 | .translate = translate_movi, | |
3048 | }, { | |
3049 | .name = "movltz", | |
3050 | .translate = translate_movcond, | |
3051 | .par = (const uint32_t[]){TCG_COND_LT}, | |
3052 | }, { | |
3053 | .name = "movnez", | |
3054 | .translate = translate_movcond, | |
3055 | .par = (const uint32_t[]){TCG_COND_NE}, | |
3056 | }, { | |
3057 | .name = "movsp", | |
3058 | .translate = translate_movsp, | |
3059 | }, { | |
3060 | .name = "movt", | |
3061 | .translate = translate_movp, | |
3062 | .par = (const uint32_t[]){TCG_COND_NE}, | |
3063 | }, { | |
3064 | .name = "mul.aa.hh", | |
3065 | .translate = translate_mac16, | |
3066 | .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_HH, 0}, | |
3067 | }, { | |
3068 | .name = "mul.aa.hl", | |
3069 | .translate = translate_mac16, | |
3070 | .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_HL, 0}, | |
3071 | }, { | |
3072 | .name = "mul.aa.lh", | |
3073 | .translate = translate_mac16, | |
3074 | .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_LH, 0}, | |
3075 | }, { | |
3076 | .name = "mul.aa.ll", | |
3077 | .translate = translate_mac16, | |
3078 | .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_LL, 0}, | |
3079 | }, { | |
3080 | .name = "mul.ad.hh", | |
3081 | .translate = translate_mac16, | |
3082 | .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_HH, 0}, | |
3083 | }, { | |
3084 | .name = "mul.ad.hl", | |
3085 | .translate = translate_mac16, | |
3086 | .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_HL, 0}, | |
3087 | }, { | |
3088 | .name = "mul.ad.lh", | |
3089 | .translate = translate_mac16, | |
3090 | .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_LH, 0}, | |
3091 | }, { | |
3092 | .name = "mul.ad.ll", | |
3093 | .translate = translate_mac16, | |
3094 | .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_LL, 0}, | |
3095 | }, { | |
3096 | .name = "mul.da.hh", | |
3097 | .translate = translate_mac16, | |
3098 | .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_HH, 0}, | |
3099 | }, { | |
3100 | .name = "mul.da.hl", | |
3101 | .translate = translate_mac16, | |
3102 | .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_HL, 0}, | |
3103 | }, { | |
3104 | .name = "mul.da.lh", | |
3105 | .translate = translate_mac16, | |
3106 | .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_LH, 0}, | |
3107 | }, { | |
3108 | .name = "mul.da.ll", | |
3109 | .translate = translate_mac16, | |
3110 | .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_LL, 0}, | |
3111 | }, { | |
3112 | .name = "mul.dd.hh", | |
3113 | .translate = translate_mac16, | |
3114 | .par = (const uint32_t[]){MAC16_MUL, MAC16_DD, MAC16_HH, 0}, | |
3115 | }, { | |
3116 | .name = "mul.dd.hl", | |
3117 | .translate = translate_mac16, | |
3118 | .par = (const uint32_t[]){MAC16_MUL, MAC16_DD, MAC16_HL, 0}, | |
3119 | }, { | |
3120 | .name = "mul.dd.lh", | |
3121 | .translate = translate_mac16, | |
3122 | .par = (const uint32_t[]){MAC16_MUL, MAC16_DD, MAC16_LH, 0}, | |
3123 | }, { | |
3124 | .name = "mul.dd.ll", | |
3125 | .translate = translate_mac16, | |
3126 | .par = (const uint32_t[]){MAC16_MUL, MAC16_DD, MAC16_LL, 0}, | |
3127 | }, { | |
3128 | .name = "mul16s", | |
3129 | .translate = translate_mul16, | |
3130 | .par = (const uint32_t[]){true}, | |
3131 | }, { | |
3132 | .name = "mul16u", | |
3133 | .translate = translate_mul16, | |
3134 | .par = (const uint32_t[]){false}, | |
3135 | }, { | |
3136 | .name = "mula.aa.hh", | |
3137 | .translate = translate_mac16, | |
3138 | .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_HH, 0}, | |
3139 | }, { | |
3140 | .name = "mula.aa.hl", | |
3141 | .translate = translate_mac16, | |
3142 | .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_HL, 0}, | |
3143 | }, { | |
3144 | .name = "mula.aa.lh", | |
3145 | .translate = translate_mac16, | |
3146 | .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_LH, 0}, | |
3147 | }, { | |
3148 | .name = "mula.aa.ll", | |
3149 | .translate = translate_mac16, | |
3150 | .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_LL, 0}, | |
3151 | }, { | |
3152 | .name = "mula.ad.hh", | |
3153 | .translate = translate_mac16, | |
3154 | .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_HH, 0}, | |
3155 | }, { | |
3156 | .name = "mula.ad.hl", | |
3157 | .translate = translate_mac16, | |
3158 | .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_HL, 0}, | |
3159 | }, { | |
3160 | .name = "mula.ad.lh", | |
3161 | .translate = translate_mac16, | |
3162 | .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_LH, 0}, | |
3163 | }, { | |
3164 | .name = "mula.ad.ll", | |
3165 | .translate = translate_mac16, | |
3166 | .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_LL, 0}, | |
3167 | }, { | |
3168 | .name = "mula.da.hh", | |
3169 | .translate = translate_mac16, | |
3170 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HH, 0}, | |
3171 | }, { | |
3172 | .name = "mula.da.hh.lddec", | |
3173 | .translate = translate_mac16, | |
3174 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HH, -4}, | |
3175 | }, { | |
3176 | .name = "mula.da.hh.ldinc", | |
3177 | .translate = translate_mac16, | |
3178 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HH, 4}, | |
3179 | }, { | |
3180 | .name = "mula.da.hl", | |
3181 | .translate = translate_mac16, | |
3182 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HL, 0}, | |
3183 | }, { | |
3184 | .name = "mula.da.hl.lddec", | |
3185 | .translate = translate_mac16, | |
3186 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HL, -4}, | |
3187 | }, { | |
3188 | .name = "mula.da.hl.ldinc", | |
3189 | .translate = translate_mac16, | |
3190 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HL, 4}, | |
3191 | }, { | |
3192 | .name = "mula.da.lh", | |
3193 | .translate = translate_mac16, | |
3194 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LH, 0}, | |
3195 | }, { | |
3196 | .name = "mula.da.lh.lddec", | |
3197 | .translate = translate_mac16, | |
3198 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LH, -4}, | |
3199 | }, { | |
3200 | .name = "mula.da.lh.ldinc", | |
3201 | .translate = translate_mac16, | |
3202 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LH, 4}, | |
3203 | }, { | |
3204 | .name = "mula.da.ll", | |
3205 | .translate = translate_mac16, | |
3206 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LL, 0}, | |
3207 | }, { | |
3208 | .name = "mula.da.ll.lddec", | |
3209 | .translate = translate_mac16, | |
3210 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LL, -4}, | |
3211 | }, { | |
3212 | .name = "mula.da.ll.ldinc", | |
3213 | .translate = translate_mac16, | |
3214 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LL, 4}, | |
3215 | }, { | |
3216 | .name = "mula.dd.hh", | |
3217 | .translate = translate_mac16, | |
3218 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HH, 0}, | |
3219 | }, { | |
3220 | .name = "mula.dd.hh.lddec", | |
3221 | .translate = translate_mac16, | |
3222 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HH, -4}, | |
3223 | }, { | |
3224 | .name = "mula.dd.hh.ldinc", | |
3225 | .translate = translate_mac16, | |
3226 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HH, 4}, | |
3227 | }, { | |
3228 | .name = "mula.dd.hl", | |
3229 | .translate = translate_mac16, | |
3230 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HL, 0}, | |
3231 | }, { | |
3232 | .name = "mula.dd.hl.lddec", | |
3233 | .translate = translate_mac16, | |
3234 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HL, -4}, | |
3235 | }, { | |
3236 | .name = "mula.dd.hl.ldinc", | |
3237 | .translate = translate_mac16, | |
3238 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HL, 4}, | |
3239 | }, { | |
3240 | .name = "mula.dd.lh", | |
3241 | .translate = translate_mac16, | |
3242 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LH, 0}, | |
3243 | }, { | |
3244 | .name = "mula.dd.lh.lddec", | |
3245 | .translate = translate_mac16, | |
3246 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LH, -4}, | |
3247 | }, { | |
3248 | .name = "mula.dd.lh.ldinc", | |
3249 | .translate = translate_mac16, | |
3250 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LH, 4}, | |
3251 | }, { | |
3252 | .name = "mula.dd.ll", | |
3253 | .translate = translate_mac16, | |
3254 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LL, 0}, | |
3255 | }, { | |
3256 | .name = "mula.dd.ll.lddec", | |
3257 | .translate = translate_mac16, | |
3258 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LL, -4}, | |
3259 | }, { | |
3260 | .name = "mula.dd.ll.ldinc", | |
3261 | .translate = translate_mac16, | |
3262 | .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LL, 4}, | |
3263 | }, { | |
3264 | .name = "mull", | |
3265 | .translate = translate_mull, | |
3266 | }, { | |
3267 | .name = "muls.aa.hh", | |
3268 | .translate = translate_mac16, | |
3269 | .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_HH, 0}, | |
3270 | }, { | |
3271 | .name = "muls.aa.hl", | |
3272 | .translate = translate_mac16, | |
3273 | .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_HL, 0}, | |
3274 | }, { | |
3275 | .name = "muls.aa.lh", | |
3276 | .translate = translate_mac16, | |
3277 | .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_LH, 0}, | |
3278 | }, { | |
3279 | .name = "muls.aa.ll", | |
3280 | .translate = translate_mac16, | |
3281 | .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_LL, 0}, | |
3282 | }, { | |
3283 | .name = "muls.ad.hh", | |
3284 | .translate = translate_mac16, | |
3285 | .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_HH, 0}, | |
3286 | }, { | |
3287 | .name = "muls.ad.hl", | |
3288 | .translate = translate_mac16, | |
3289 | .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_HL, 0}, | |
3290 | }, { | |
3291 | .name = "muls.ad.lh", | |
3292 | .translate = translate_mac16, | |
3293 | .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_LH, 0}, | |
3294 | }, { | |
3295 | .name = "muls.ad.ll", | |
3296 | .translate = translate_mac16, | |
3297 | .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_LL, 0}, | |
3298 | }, { | |
3299 | .name = "muls.da.hh", | |
3300 | .translate = translate_mac16, | |
3301 | .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_HH, 0}, | |
3302 | }, { | |
3303 | .name = "muls.da.hl", | |
3304 | .translate = translate_mac16, | |
3305 | .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_HL, 0}, | |
3306 | }, { | |
3307 | .name = "muls.da.lh", | |
3308 | .translate = translate_mac16, | |
3309 | .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_LH, 0}, | |
3310 | }, { | |
3311 | .name = "muls.da.ll", | |
3312 | .translate = translate_mac16, | |
3313 | .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_LL, 0}, | |
3314 | }, { | |
3315 | .name = "muls.dd.hh", | |
3316 | .translate = translate_mac16, | |
3317 | .par = (const uint32_t[]){MAC16_MULS, MAC16_DD, MAC16_HH, 0}, | |
3318 | }, { | |
3319 | .name = "muls.dd.hl", | |
3320 | .translate = translate_mac16, | |
3321 | .par = (const uint32_t[]){MAC16_MULS, MAC16_DD, MAC16_HL, 0}, | |
3322 | }, { | |
3323 | .name = "muls.dd.lh", | |
3324 | .translate = translate_mac16, | |
3325 | .par = (const uint32_t[]){MAC16_MULS, MAC16_DD, MAC16_LH, 0}, | |
3326 | }, { | |
3327 | .name = "muls.dd.ll", | |
3328 | .translate = translate_mac16, | |
3329 | .par = (const uint32_t[]){MAC16_MULS, MAC16_DD, MAC16_LL, 0}, | |
3330 | }, { | |
3331 | .name = "mulsh", | |
3332 | .translate = translate_mulh, | |
3333 | .par = (const uint32_t[]){true}, | |
3334 | }, { | |
3335 | .name = "muluh", | |
3336 | .translate = translate_mulh, | |
3337 | .par = (const uint32_t[]){false}, | |
3338 | }, { | |
3339 | .name = "neg", | |
3340 | .translate = translate_neg, | |
3341 | }, { | |
3342 | .name = "nop", | |
3343 | .translate = translate_nop, | |
3344 | }, { | |
3345 | .name = "nop.n", | |
3346 | .translate = translate_nop, | |
3347 | }, { | |
3348 | .name = "nsa", | |
3349 | .translate = translate_nsa, | |
3350 | }, { | |
3351 | .name = "nsau", | |
3352 | .translate = translate_nsau, | |
3353 | }, { | |
3354 | .name = "or", | |
3355 | .translate = translate_or, | |
3356 | }, { | |
3357 | .name = "orb", | |
3358 | .translate = translate_boolean, | |
3359 | .par = (const uint32_t[]){BOOLEAN_OR}, | |
3360 | }, { | |
3361 | .name = "orbc", | |
3362 | .translate = translate_boolean, | |
3363 | .par = (const uint32_t[]){BOOLEAN_ORC}, | |
3364 | }, { | |
3365 | .name = "pdtlb", | |
3366 | .translate = translate_ptlb, | |
3367 | .par = (const uint32_t[]){true}, | |
3368 | }, { | |
3369 | .name = "pitlb", | |
3370 | .translate = translate_ptlb, | |
3371 | .par = (const uint32_t[]){false}, | |
3372 | }, { | |
3373 | .name = "quos", | |
3374 | .translate = translate_quos, | |
3375 | .par = (const uint32_t[]){true}, | |
3376 | }, { | |
3377 | .name = "quou", | |
3378 | .translate = translate_quou, | |
3379 | .par = (const uint32_t[]){true}, | |
3380 | }, { | |
3381 | .name = "rdtlb0", | |
3382 | .translate = translate_rtlb, | |
3383 | .par = (const uint32_t[]){true, 0}, | |
3384 | }, { | |
3385 | .name = "rdtlb1", | |
3386 | .translate = translate_rtlb, | |
3387 | .par = (const uint32_t[]){true, 1}, | |
e9872741 MF |
3388 | }, { |
3389 | .name = "read_impwire", | |
3390 | .translate = translate_read_impwire, | |
168c12b0 MF |
3391 | }, { |
3392 | .name = "rems", | |
3393 | .translate = translate_quos, | |
3394 | .par = (const uint32_t[]){false}, | |
3395 | }, { | |
3396 | .name = "remu", | |
3397 | .translate = translate_quou, | |
3398 | .par = (const uint32_t[]){false}, | |
3399 | }, { | |
3400 | .name = "rer", | |
3401 | .translate = translate_rer, | |
3402 | }, { | |
3403 | .name = "ret", | |
3404 | .translate = translate_ret, | |
3405 | }, { | |
3406 | .name = "ret.n", | |
3407 | .translate = translate_ret, | |
3408 | }, { | |
3409 | .name = "retw", | |
3410 | .translate = translate_retw, | |
3411 | }, { | |
3412 | .name = "retw.n", | |
3413 | .translate = translate_retw, | |
13f6a7cd MF |
3414 | }, { |
3415 | .name = "rfdd", | |
3416 | .translate = translate_ill, | |
168c12b0 MF |
3417 | }, { |
3418 | .name = "rfde", | |
3419 | .translate = translate_rfde, | |
13f6a7cd MF |
3420 | }, { |
3421 | .name = "rfdo", | |
3422 | .translate = translate_ill, | |
168c12b0 MF |
3423 | }, { |
3424 | .name = "rfe", | |
3425 | .translate = translate_rfe, | |
3426 | }, { | |
3427 | .name = "rfi", | |
3428 | .translate = translate_rfi, | |
3429 | }, { | |
3430 | .name = "rfwo", | |
3431 | .translate = translate_rfw, | |
3432 | .par = (const uint32_t[]){true}, | |
3433 | }, { | |
3434 | .name = "rfwu", | |
3435 | .translate = translate_rfw, | |
3436 | .par = (const uint32_t[]){false}, | |
3437 | }, { | |
3438 | .name = "ritlb0", | |
3439 | .translate = translate_rtlb, | |
3440 | .par = (const uint32_t[]){false, 0}, | |
3441 | }, { | |
3442 | .name = "ritlb1", | |
3443 | .translate = translate_rtlb, | |
3444 | .par = (const uint32_t[]){false, 1}, | |
3445 | }, { | |
3446 | .name = "rotw", | |
3447 | .translate = translate_rotw, | |
3448 | }, { | |
3449 | .name = "rsil", | |
3450 | .translate = translate_rsil, | |
3451 | }, { | |
3452 | .name = "rsr.176", | |
3453 | .translate = translate_rsr, | |
3454 | .par = (const uint32_t[]){176}, | |
3455 | }, { | |
3456 | .name = "rsr.208", | |
3457 | .translate = translate_rsr, | |
3458 | .par = (const uint32_t[]){208}, | |
3459 | }, { | |
3460 | .name = "rsr.acchi", | |
3461 | .translate = translate_rsr, | |
3462 | .par = (const uint32_t[]){ACCHI}, | |
3463 | }, { | |
3464 | .name = "rsr.acclo", | |
3465 | .translate = translate_rsr, | |
3466 | .par = (const uint32_t[]){ACCLO}, | |
3467 | }, { | |
3468 | .name = "rsr.atomctl", | |
3469 | .translate = translate_rsr, | |
3470 | .par = (const uint32_t[]){ATOMCTL}, | |
3471 | }, { | |
3472 | .name = "rsr.br", | |
3473 | .translate = translate_rsr, | |
3474 | .par = (const uint32_t[]){BR}, | |
3475 | }, { | |
3476 | .name = "rsr.cacheattr", | |
3477 | .translate = translate_rsr, | |
3478 | .par = (const uint32_t[]){CACHEATTR}, | |
3479 | }, { | |
3480 | .name = "rsr.ccompare0", | |
3481 | .translate = translate_rsr, | |
3482 | .par = (const uint32_t[]){CCOMPARE}, | |
3483 | }, { | |
3484 | .name = "rsr.ccompare1", | |
3485 | .translate = translate_rsr, | |
3486 | .par = (const uint32_t[]){CCOMPARE + 1}, | |
3487 | }, { | |
3488 | .name = "rsr.ccompare2", | |
3489 | .translate = translate_rsr, | |
3490 | .par = (const uint32_t[]){CCOMPARE + 2}, | |
3491 | }, { | |
3492 | .name = "rsr.ccount", | |
3493 | .translate = translate_rsr, | |
3494 | .par = (const uint32_t[]){CCOUNT}, | |
3495 | }, { | |
3496 | .name = "rsr.configid0", | |
3497 | .translate = translate_rsr, | |
3498 | .par = (const uint32_t[]){CONFIGID0}, | |
3499 | }, { | |
3500 | .name = "rsr.configid1", | |
3501 | .translate = translate_rsr, | |
3502 | .par = (const uint32_t[]){CONFIGID1}, | |
3503 | }, { | |
3504 | .name = "rsr.cpenable", | |
3505 | .translate = translate_rsr, | |
3506 | .par = (const uint32_t[]){CPENABLE}, | |
3507 | }, { | |
3508 | .name = "rsr.dbreaka0", | |
3509 | .translate = translate_rsr, | |
3510 | .par = (const uint32_t[]){DBREAKA}, | |
3511 | }, { | |
3512 | .name = "rsr.dbreaka1", | |
3513 | .translate = translate_rsr, | |
3514 | .par = (const uint32_t[]){DBREAKA + 1}, | |
3515 | }, { | |
3516 | .name = "rsr.dbreakc0", | |
3517 | .translate = translate_rsr, | |
3518 | .par = (const uint32_t[]){DBREAKC}, | |
3519 | }, { | |
3520 | .name = "rsr.dbreakc1", | |
3521 | .translate = translate_rsr, | |
3522 | .par = (const uint32_t[]){DBREAKC + 1}, | |
13f6a7cd MF |
3523 | }, { |
3524 | .name = "rsr.ddr", | |
3525 | .translate = translate_rsr, | |
3526 | .par = (const uint32_t[]){DDR}, | |
168c12b0 MF |
3527 | }, { |
3528 | .name = "rsr.debugcause", | |
3529 | .translate = translate_rsr, | |
3530 | .par = (const uint32_t[]){DEBUGCAUSE}, | |
3531 | }, { | |
3532 | .name = "rsr.depc", | |
3533 | .translate = translate_rsr, | |
3534 | .par = (const uint32_t[]){DEPC}, | |
3535 | }, { | |
3536 | .name = "rsr.dtlbcfg", | |
3537 | .translate = translate_rsr, | |
3538 | .par = (const uint32_t[]){DTLBCFG}, | |
3539 | }, { | |
3540 | .name = "rsr.epc1", | |
3541 | .translate = translate_rsr, | |
3542 | .par = (const uint32_t[]){EPC1}, | |
3543 | }, { | |
3544 | .name = "rsr.epc2", | |
3545 | .translate = translate_rsr, | |
3546 | .par = (const uint32_t[]){EPC1 + 1}, | |
3547 | }, { | |
3548 | .name = "rsr.epc3", | |
3549 | .translate = translate_rsr, | |
3550 | .par = (const uint32_t[]){EPC1 + 2}, | |
3551 | }, { | |
3552 | .name = "rsr.epc4", | |
3553 | .translate = translate_rsr, | |
3554 | .par = (const uint32_t[]){EPC1 + 3}, | |
3555 | }, { | |
3556 | .name = "rsr.epc5", | |
3557 | .translate = translate_rsr, | |
3558 | .par = (const uint32_t[]){EPC1 + 4}, | |
3559 | }, { | |
3560 | .name = "rsr.epc6", | |
3561 | .translate = translate_rsr, | |
3562 | .par = (const uint32_t[]){EPC1 + 5}, | |
3563 | }, { | |
3564 | .name = "rsr.epc7", | |
3565 | .translate = translate_rsr, | |
3566 | .par = (const uint32_t[]){EPC1 + 6}, | |
3567 | }, { | |
3568 | .name = "rsr.eps2", | |
3569 | .translate = translate_rsr, | |
3570 | .par = (const uint32_t[]){EPS2}, | |
3571 | }, { | |
3572 | .name = "rsr.eps3", | |
3573 | .translate = translate_rsr, | |
3574 | .par = (const uint32_t[]){EPS2 + 1}, | |
3575 | }, { | |
3576 | .name = "rsr.eps4", | |
3577 | .translate = translate_rsr, | |
3578 | .par = (const uint32_t[]){EPS2 + 2}, | |
3579 | }, { | |
3580 | .name = "rsr.eps5", | |
3581 | .translate = translate_rsr, | |
3582 | .par = (const uint32_t[]){EPS2 + 3}, | |
3583 | }, { | |
3584 | .name = "rsr.eps6", | |
3585 | .translate = translate_rsr, | |
3586 | .par = (const uint32_t[]){EPS2 + 4}, | |
3587 | }, { | |
3588 | .name = "rsr.eps7", | |
3589 | .translate = translate_rsr, | |
3590 | .par = (const uint32_t[]){EPS2 + 5}, | |
3591 | }, { | |
3592 | .name = "rsr.exccause", | |
3593 | .translate = translate_rsr, | |
3594 | .par = (const uint32_t[]){EXCCAUSE}, | |
3595 | }, { | |
3596 | .name = "rsr.excsave1", | |
3597 | .translate = translate_rsr, | |
3598 | .par = (const uint32_t[]){EXCSAVE1}, | |
3599 | }, { | |
3600 | .name = "rsr.excsave2", | |
3601 | .translate = translate_rsr, | |
3602 | .par = (const uint32_t[]){EXCSAVE1 + 1}, | |
3603 | }, { | |
3604 | .name = "rsr.excsave3", | |
3605 | .translate = translate_rsr, | |
3606 | .par = (const uint32_t[]){EXCSAVE1 + 2}, | |
3607 | }, { | |
3608 | .name = "rsr.excsave4", | |
3609 | .translate = translate_rsr, | |
3610 | .par = (const uint32_t[]){EXCSAVE1 + 3}, | |
3611 | }, { | |
3612 | .name = "rsr.excsave5", | |
3613 | .translate = translate_rsr, | |
3614 | .par = (const uint32_t[]){EXCSAVE1 + 4}, | |
3615 | }, { | |
3616 | .name = "rsr.excsave6", | |
3617 | .translate = translate_rsr, | |
3618 | .par = (const uint32_t[]){EXCSAVE1 + 5}, | |
3619 | }, { | |
3620 | .name = "rsr.excsave7", | |
3621 | .translate = translate_rsr, | |
3622 | .par = (const uint32_t[]){EXCSAVE1 + 6}, | |
3623 | }, { | |
3624 | .name = "rsr.excvaddr", | |
3625 | .translate = translate_rsr, | |
3626 | .par = (const uint32_t[]){EXCVADDR}, | |
3627 | }, { | |
3628 | .name = "rsr.ibreaka0", | |
3629 | .translate = translate_rsr, | |
3630 | .par = (const uint32_t[]){IBREAKA}, | |
3631 | }, { | |
3632 | .name = "rsr.ibreaka1", | |
3633 | .translate = translate_rsr, | |
3634 | .par = (const uint32_t[]){IBREAKA + 1}, | |
3635 | }, { | |
3636 | .name = "rsr.ibreakenable", | |
3637 | .translate = translate_rsr, | |
3638 | .par = (const uint32_t[]){IBREAKENABLE}, | |
3639 | }, { | |
3640 | .name = "rsr.icount", | |
3641 | .translate = translate_rsr, | |
3642 | .par = (const uint32_t[]){ICOUNT}, | |
3643 | }, { | |
3644 | .name = "rsr.icountlevel", | |
3645 | .translate = translate_rsr, | |
3646 | .par = (const uint32_t[]){ICOUNTLEVEL}, | |
3647 | }, { | |
3648 | .name = "rsr.intclear", | |
3649 | .translate = translate_rsr, | |
3650 | .par = (const uint32_t[]){INTCLEAR}, | |
3651 | }, { | |
3652 | .name = "rsr.intenable", | |
3653 | .translate = translate_rsr, | |
3654 | .par = (const uint32_t[]){INTENABLE}, | |
3655 | }, { | |
3656 | .name = "rsr.interrupt", | |
3657 | .translate = translate_rsr, | |
3658 | .par = (const uint32_t[]){INTSET}, | |
3659 | }, { | |
3660 | .name = "rsr.intset", | |
3661 | .translate = translate_rsr, | |
3662 | .par = (const uint32_t[]){INTSET}, | |
3663 | }, { | |
3664 | .name = "rsr.itlbcfg", | |
3665 | .translate = translate_rsr, | |
3666 | .par = (const uint32_t[]){ITLBCFG}, | |
3667 | }, { | |
3668 | .name = "rsr.lbeg", | |
3669 | .translate = translate_rsr, | |
3670 | .par = (const uint32_t[]){LBEG}, | |
3671 | }, { | |
3672 | .name = "rsr.lcount", | |
3673 | .translate = translate_rsr, | |
3674 | .par = (const uint32_t[]){LCOUNT}, | |
3675 | }, { | |
3676 | .name = "rsr.lend", | |
3677 | .translate = translate_rsr, | |
3678 | .par = (const uint32_t[]){LEND}, | |
3679 | }, { | |
3680 | .name = "rsr.litbase", | |
3681 | .translate = translate_rsr, | |
3682 | .par = (const uint32_t[]){LITBASE}, | |
3683 | }, { | |
3684 | .name = "rsr.m0", | |
3685 | .translate = translate_rsr, | |
3686 | .par = (const uint32_t[]){MR}, | |
3687 | }, { | |
3688 | .name = "rsr.m1", | |
3689 | .translate = translate_rsr, | |
3690 | .par = (const uint32_t[]){MR + 1}, | |
3691 | }, { | |
3692 | .name = "rsr.m2", | |
3693 | .translate = translate_rsr, | |
3694 | .par = (const uint32_t[]){MR + 2}, | |
3695 | }, { | |
3696 | .name = "rsr.m3", | |
3697 | .translate = translate_rsr, | |
3698 | .par = (const uint32_t[]){MR + 3}, | |
3699 | }, { | |
3700 | .name = "rsr.memctl", | |
3701 | .translate = translate_rsr, | |
3702 | .par = (const uint32_t[]){MEMCTL}, | |
3703 | }, { | |
3704 | .name = "rsr.misc0", | |
3705 | .translate = translate_rsr, | |
3706 | .par = (const uint32_t[]){MISC}, | |
3707 | }, { | |
3708 | .name = "rsr.misc1", | |
3709 | .translate = translate_rsr, | |
3710 | .par = (const uint32_t[]){MISC + 1}, | |
3711 | }, { | |
3712 | .name = "rsr.misc2", | |
3713 | .translate = translate_rsr, | |
3714 | .par = (const uint32_t[]){MISC + 2}, | |
3715 | }, { | |
3716 | .name = "rsr.misc3", | |
3717 | .translate = translate_rsr, | |
3718 | .par = (const uint32_t[]){MISC + 3}, | |
3719 | }, { | |
3720 | .name = "rsr.prid", | |
3721 | .translate = translate_rsr, | |
3722 | .par = (const uint32_t[]){PRID}, | |
3723 | }, { | |
3724 | .name = "rsr.ps", | |
3725 | .translate = translate_rsr, | |
3726 | .par = (const uint32_t[]){PS}, | |
3727 | }, { | |
3728 | .name = "rsr.ptevaddr", | |
3729 | .translate = translate_rsr, | |
3730 | .par = (const uint32_t[]){PTEVADDR}, | |
3731 | }, { | |
3732 | .name = "rsr.rasid", | |
3733 | .translate = translate_rsr, | |
3734 | .par = (const uint32_t[]){RASID}, | |
3735 | }, { | |
3736 | .name = "rsr.sar", | |
3737 | .translate = translate_rsr, | |
3738 | .par = (const uint32_t[]){SAR}, | |
3739 | }, { | |
3740 | .name = "rsr.scompare1", | |
3741 | .translate = translate_rsr, | |
3742 | .par = (const uint32_t[]){SCOMPARE1}, | |
3743 | }, { | |
3744 | .name = "rsr.vecbase", | |
3745 | .translate = translate_rsr, | |
3746 | .par = (const uint32_t[]){VECBASE}, | |
3747 | }, { | |
3748 | .name = "rsr.windowbase", | |
3749 | .translate = translate_rsr, | |
3750 | .par = (const uint32_t[]){WINDOW_BASE}, | |
3751 | }, { | |
3752 | .name = "rsr.windowstart", | |
3753 | .translate = translate_rsr, | |
3754 | .par = (const uint32_t[]){WINDOW_START}, | |
3755 | }, { | |
3756 | .name = "rsync", | |
3757 | .translate = translate_nop, | |
e9872741 MF |
3758 | }, { |
3759 | .name = "rur.expstate", | |
3760 | .translate = translate_rur, | |
3761 | .par = (const uint32_t[]){EXPSTATE}, | |
168c12b0 MF |
3762 | }, { |
3763 | .name = "rur.fcr", | |
3764 | .translate = translate_rur, | |
3765 | .par = (const uint32_t[]){FCR}, | |
3766 | }, { | |
3767 | .name = "rur.fsr", | |
3768 | .translate = translate_rur, | |
3769 | .par = (const uint32_t[]){FSR}, | |
3770 | }, { | |
3771 | .name = "rur.threadptr", | |
3772 | .translate = translate_rur, | |
3773 | .par = (const uint32_t[]){THREADPTR}, | |
3774 | }, { | |
3775 | .name = "s16i", | |
3776 | .translate = translate_ldst, | |
3777 | .par = (const uint32_t[]){MO_TEUW, false, true}, | |
3778 | }, { | |
3779 | .name = "s32c1i", | |
3780 | .translate = translate_s32c1i, | |
3781 | }, { | |
3782 | .name = "s32e", | |
3783 | .translate = translate_s32e, | |
3784 | }, { | |
3785 | .name = "s32i", | |
3786 | .translate = translate_ldst, | |
3787 | .par = (const uint32_t[]){MO_TEUL, false, true}, | |
3788 | }, { | |
3789 | .name = "s32i.n", | |
3790 | .translate = translate_ldst, | |
3791 | .par = (const uint32_t[]){MO_TEUL, false, true}, | |
3792 | }, { | |
3793 | .name = "s32nb", | |
3794 | .translate = translate_ldst, | |
3795 | .par = (const uint32_t[]){MO_TEUL, false, true}, | |
3796 | }, { | |
3797 | .name = "s32ri", | |
3798 | .translate = translate_ldst, | |
3799 | .par = (const uint32_t[]){MO_TEUL, true, true}, | |
3800 | }, { | |
3801 | .name = "s8i", | |
3802 | .translate = translate_ldst, | |
3803 | .par = (const uint32_t[]){MO_UB, false, true}, | |
d1e9b006 MF |
3804 | }, { |
3805 | .name = "salt", | |
3806 | .translate = translate_salt, | |
3807 | .par = (const uint32_t[]){TCG_COND_LT}, | |
3808 | }, { | |
3809 | .name = "saltu", | |
3810 | .translate = translate_salt, | |
3811 | .par = (const uint32_t[]){TCG_COND_LTU}, | |
e9872741 MF |
3812 | }, { |
3813 | .name = "setb_expstate", | |
3814 | .translate = translate_setb_expstate, | |
168c12b0 MF |
3815 | }, { |
3816 | .name = "sext", | |
3817 | .translate = translate_sext, | |
3818 | }, { | |
3819 | .name = "simcall", | |
3820 | .translate = translate_simcall, | |
3821 | }, { | |
3822 | .name = "sll", | |
3823 | .translate = translate_sll, | |
3824 | }, { | |
3825 | .name = "slli", | |
3826 | .translate = translate_slli, | |
3827 | }, { | |
3828 | .name = "sra", | |
3829 | .translate = translate_sra, | |
3830 | }, { | |
3831 | .name = "srai", | |
3832 | .translate = translate_srai, | |
3833 | }, { | |
3834 | .name = "src", | |
3835 | .translate = translate_src, | |
3836 | }, { | |
3837 | .name = "srl", | |
3838 | .translate = translate_srl, | |
3839 | }, { | |
3840 | .name = "srli", | |
3841 | .translate = translate_srli, | |
3842 | }, { | |
3843 | .name = "ssa8b", | |
3844 | .translate = translate_ssa8b, | |
3845 | }, { | |
3846 | .name = "ssa8l", | |
3847 | .translate = translate_ssa8l, | |
3848 | }, { | |
3849 | .name = "ssai", | |
3850 | .translate = translate_ssai, | |
3851 | }, { | |
3852 | .name = "ssl", | |
3853 | .translate = translate_ssl, | |
3854 | }, { | |
3855 | .name = "ssr", | |
3856 | .translate = translate_ssr, | |
3857 | }, { | |
3858 | .name = "sub", | |
3859 | .translate = translate_sub, | |
3860 | }, { | |
3861 | .name = "subx2", | |
3862 | .translate = translate_subx, | |
3863 | .par = (const uint32_t[]){1}, | |
3864 | }, { | |
3865 | .name = "subx4", | |
3866 | .translate = translate_subx, | |
3867 | .par = (const uint32_t[]){2}, | |
3868 | }, { | |
3869 | .name = "subx8", | |
3870 | .translate = translate_subx, | |
3871 | .par = (const uint32_t[]){3}, | |
3872 | }, { | |
3873 | .name = "syscall", | |
3874 | .translate = translate_syscall, | |
3875 | }, { | |
3876 | .name = "umul.aa.hh", | |
3877 | .translate = translate_mac16, | |
3878 | .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_HH, 0}, | |
3879 | }, { | |
3880 | .name = "umul.aa.hl", | |
3881 | .translate = translate_mac16, | |
3882 | .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_HL, 0}, | |
3883 | }, { | |
3884 | .name = "umul.aa.lh", | |
3885 | .translate = translate_mac16, | |
3886 | .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_LH, 0}, | |
3887 | }, { | |
3888 | .name = "umul.aa.ll", | |
3889 | .translate = translate_mac16, | |
3890 | .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_LL, 0}, | |
3891 | }, { | |
3892 | .name = "waiti", | |
3893 | .translate = translate_waiti, | |
3894 | }, { | |
3895 | .name = "wdtlb", | |
3896 | .translate = translate_wtlb, | |
3897 | .par = (const uint32_t[]){true}, | |
3898 | }, { | |
3899 | .name = "wer", | |
3900 | .translate = translate_wer, | |
3901 | }, { | |
3902 | .name = "witlb", | |
3903 | .translate = translate_wtlb, | |
3904 | .par = (const uint32_t[]){false}, | |
e9872741 MF |
3905 | }, { |
3906 | .name = "wrmsk_expstate", | |
3907 | .translate = translate_wrmsk_expstate, | |
168c12b0 MF |
3908 | }, { |
3909 | .name = "wsr.176", | |
3910 | .translate = translate_wsr, | |
3911 | .par = (const uint32_t[]){176}, | |
3912 | }, { | |
3913 | .name = "wsr.208", | |
3914 | .translate = translate_wsr, | |
3915 | .par = (const uint32_t[]){208}, | |
3916 | }, { | |
3917 | .name = "wsr.acchi", | |
3918 | .translate = translate_wsr, | |
3919 | .par = (const uint32_t[]){ACCHI}, | |
3920 | }, { | |
3921 | .name = "wsr.acclo", | |
3922 | .translate = translate_wsr, | |
3923 | .par = (const uint32_t[]){ACCLO}, | |
3924 | }, { | |
3925 | .name = "wsr.atomctl", | |
3926 | .translate = translate_wsr, | |
3927 | .par = (const uint32_t[]){ATOMCTL}, | |
3928 | }, { | |
3929 | .name = "wsr.br", | |
3930 | .translate = translate_wsr, | |
3931 | .par = (const uint32_t[]){BR}, | |
3932 | }, { | |
3933 | .name = "wsr.cacheattr", | |
3934 | .translate = translate_wsr, | |
3935 | .par = (const uint32_t[]){CACHEATTR}, | |
3936 | }, { | |
3937 | .name = "wsr.ccompare0", | |
3938 | .translate = translate_wsr, | |
3939 | .par = (const uint32_t[]){CCOMPARE}, | |
3940 | }, { | |
3941 | .name = "wsr.ccompare1", | |
3942 | .translate = translate_wsr, | |
3943 | .par = (const uint32_t[]){CCOMPARE + 1}, | |
3944 | }, { | |
3945 | .name = "wsr.ccompare2", | |
3946 | .translate = translate_wsr, | |
3947 | .par = (const uint32_t[]){CCOMPARE + 2}, | |
3948 | }, { | |
3949 | .name = "wsr.ccount", | |
3950 | .translate = translate_wsr, | |
3951 | .par = (const uint32_t[]){CCOUNT}, | |
3952 | }, { | |
3953 | .name = "wsr.configid0", | |
3954 | .translate = translate_wsr, | |
3955 | .par = (const uint32_t[]){CONFIGID0}, | |
3956 | }, { | |
3957 | .name = "wsr.configid1", | |
3958 | .translate = translate_wsr, | |
3959 | .par = (const uint32_t[]){CONFIGID1}, | |
3960 | }, { | |
3961 | .name = "wsr.cpenable", | |
3962 | .translate = translate_wsr, | |
3963 | .par = (const uint32_t[]){CPENABLE}, | |
3964 | }, { | |
3965 | .name = "wsr.dbreaka0", | |
3966 | .translate = translate_wsr, | |
3967 | .par = (const uint32_t[]){DBREAKA}, | |
3968 | }, { | |
3969 | .name = "wsr.dbreaka1", | |
3970 | .translate = translate_wsr, | |
3971 | .par = (const uint32_t[]){DBREAKA + 1}, | |
3972 | }, { | |
3973 | .name = "wsr.dbreakc0", | |
3974 | .translate = translate_wsr, | |
3975 | .par = (const uint32_t[]){DBREAKC}, | |
3976 | }, { | |
3977 | .name = "wsr.dbreakc1", | |
3978 | .translate = translate_wsr, | |
3979 | .par = (const uint32_t[]){DBREAKC + 1}, | |
13f6a7cd MF |
3980 | }, { |
3981 | .name = "wsr.ddr", | |
3982 | .translate = translate_wsr, | |
3983 | .par = (const uint32_t[]){DDR}, | |
168c12b0 MF |
3984 | }, { |
3985 | .name = "wsr.debugcause", | |
3986 | .translate = translate_wsr, | |
3987 | .par = (const uint32_t[]){DEBUGCAUSE}, | |
3988 | }, { | |
3989 | .name = "wsr.depc", | |
3990 | .translate = translate_wsr, | |
3991 | .par = (const uint32_t[]){DEPC}, | |
3992 | }, { | |
3993 | .name = "wsr.dtlbcfg", | |
3994 | .translate = translate_wsr, | |
3995 | .par = (const uint32_t[]){DTLBCFG}, | |
3996 | }, { | |
3997 | .name = "wsr.epc1", | |
3998 | .translate = translate_wsr, | |
3999 | .par = (const uint32_t[]){EPC1}, | |
4000 | }, { | |
4001 | .name = "wsr.epc2", | |
4002 | .translate = translate_wsr, | |
4003 | .par = (const uint32_t[]){EPC1 + 1}, | |
4004 | }, { | |
4005 | .name = "wsr.epc3", | |
4006 | .translate = translate_wsr, | |
4007 | .par = (const uint32_t[]){EPC1 + 2}, | |
4008 | }, { | |
4009 | .name = "wsr.epc4", | |
4010 | .translate = translate_wsr, | |
4011 | .par = (const uint32_t[]){EPC1 + 3}, | |
4012 | }, { | |
4013 | .name = "wsr.epc5", | |
4014 | .translate = translate_wsr, | |
4015 | .par = (const uint32_t[]){EPC1 + 4}, | |
4016 | }, { | |
4017 | .name = "wsr.epc6", | |
4018 | .translate = translate_wsr, | |
4019 | .par = (const uint32_t[]){EPC1 + 5}, | |
4020 | }, { | |
4021 | .name = "wsr.epc7", | |
4022 | .translate = translate_wsr, | |
4023 | .par = (const uint32_t[]){EPC1 + 6}, | |
4024 | }, { | |
4025 | .name = "wsr.eps2", | |
4026 | .translate = translate_wsr, | |
4027 | .par = (const uint32_t[]){EPS2}, | |
4028 | }, { | |
4029 | .name = "wsr.eps3", | |
4030 | .translate = translate_wsr, | |
4031 | .par = (const uint32_t[]){EPS2 + 1}, | |
4032 | }, { | |
4033 | .name = "wsr.eps4", | |
4034 | .translate = translate_wsr, | |
4035 | .par = (const uint32_t[]){EPS2 + 2}, | |
4036 | }, { | |
4037 | .name = "wsr.eps5", | |
4038 | .translate = translate_wsr, | |
4039 | .par = (const uint32_t[]){EPS2 + 3}, | |
4040 | }, { | |
4041 | .name = "wsr.eps6", | |
4042 | .translate = translate_wsr, | |
4043 | .par = (const uint32_t[]){EPS2 + 4}, | |
4044 | }, { | |
4045 | .name = "wsr.eps7", | |
4046 | .translate = translate_wsr, | |
4047 | .par = (const uint32_t[]){EPS2 + 5}, | |
4048 | }, { | |
4049 | .name = "wsr.exccause", | |
4050 | .translate = translate_wsr, | |
4051 | .par = (const uint32_t[]){EXCCAUSE}, | |
4052 | }, { | |
4053 | .name = "wsr.excsave1", | |
4054 | .translate = translate_wsr, | |
4055 | .par = (const uint32_t[]){EXCSAVE1}, | |
4056 | }, { | |
4057 | .name = "wsr.excsave2", | |
4058 | .translate = translate_wsr, | |
4059 | .par = (const uint32_t[]){EXCSAVE1 + 1}, | |
4060 | }, { | |
4061 | .name = "wsr.excsave3", | |
4062 | .translate = translate_wsr, | |
4063 | .par = (const uint32_t[]){EXCSAVE1 + 2}, | |
4064 | }, { | |
4065 | .name = "wsr.excsave4", | |
4066 | .translate = translate_wsr, | |
4067 | .par = (const uint32_t[]){EXCSAVE1 + 3}, | |
4068 | }, { | |
4069 | .name = "wsr.excsave5", | |
4070 | .translate = translate_wsr, | |
4071 | .par = (const uint32_t[]){EXCSAVE1 + 4}, | |
4072 | }, { | |
4073 | .name = "wsr.excsave6", | |
4074 | .translate = translate_wsr, | |
4075 | .par = (const uint32_t[]){EXCSAVE1 + 5}, | |
4076 | }, { | |
4077 | .name = "wsr.excsave7", | |
4078 | .translate = translate_wsr, | |
4079 | .par = (const uint32_t[]){EXCSAVE1 + 6}, | |
4080 | }, { | |
4081 | .name = "wsr.excvaddr", | |
4082 | .translate = translate_wsr, | |
4083 | .par = (const uint32_t[]){EXCVADDR}, | |
4084 | }, { | |
4085 | .name = "wsr.ibreaka0", | |
4086 | .translate = translate_wsr, | |
4087 | .par = (const uint32_t[]){IBREAKA}, | |
4088 | }, { | |
4089 | .name = "wsr.ibreaka1", | |
4090 | .translate = translate_wsr, | |
4091 | .par = (const uint32_t[]){IBREAKA + 1}, | |
4092 | }, { | |
4093 | .name = "wsr.ibreakenable", | |
4094 | .translate = translate_wsr, | |
4095 | .par = (const uint32_t[]){IBREAKENABLE}, | |
4096 | }, { | |
4097 | .name = "wsr.icount", | |
4098 | .translate = translate_wsr, | |
4099 | .par = (const uint32_t[]){ICOUNT}, | |
4100 | }, { | |
4101 | .name = "wsr.icountlevel", | |
4102 | .translate = translate_wsr, | |
4103 | .par = (const uint32_t[]){ICOUNTLEVEL}, | |
4104 | }, { | |
4105 | .name = "wsr.intclear", | |
4106 | .translate = translate_wsr, | |
4107 | .par = (const uint32_t[]){INTCLEAR}, | |
4108 | }, { | |
4109 | .name = "wsr.intenable", | |
4110 | .translate = translate_wsr, | |
4111 | .par = (const uint32_t[]){INTENABLE}, | |
4112 | }, { | |
4113 | .name = "wsr.interrupt", | |
4114 | .translate = translate_wsr, | |
4115 | .par = (const uint32_t[]){INTSET}, | |
4116 | }, { | |
4117 | .name = "wsr.intset", | |
4118 | .translate = translate_wsr, | |
4119 | .par = (const uint32_t[]){INTSET}, | |
4120 | }, { | |
4121 | .name = "wsr.itlbcfg", | |
4122 | .translate = translate_wsr, | |
4123 | .par = (const uint32_t[]){ITLBCFG}, | |
4124 | }, { | |
4125 | .name = "wsr.lbeg", | |
4126 | .translate = translate_wsr, | |
4127 | .par = (const uint32_t[]){LBEG}, | |
4128 | }, { | |
4129 | .name = "wsr.lcount", | |
4130 | .translate = translate_wsr, | |
4131 | .par = (const uint32_t[]){LCOUNT}, | |
4132 | }, { | |
4133 | .name = "wsr.lend", | |
4134 | .translate = translate_wsr, | |
4135 | .par = (const uint32_t[]){LEND}, | |
4136 | }, { | |
4137 | .name = "wsr.litbase", | |
4138 | .translate = translate_wsr, | |
4139 | .par = (const uint32_t[]){LITBASE}, | |
4140 | }, { | |
4141 | .name = "wsr.m0", | |
4142 | .translate = translate_wsr, | |
4143 | .par = (const uint32_t[]){MR}, | |
4144 | }, { | |
4145 | .name = "wsr.m1", | |
4146 | .translate = translate_wsr, | |
4147 | .par = (const uint32_t[]){MR + 1}, | |
4148 | }, { | |
4149 | .name = "wsr.m2", | |
4150 | .translate = translate_wsr, | |
4151 | .par = (const uint32_t[]){MR + 2}, | |
4152 | }, { | |
4153 | .name = "wsr.m3", | |
4154 | .translate = translate_wsr, | |
4155 | .par = (const uint32_t[]){MR + 3}, | |
4156 | }, { | |
4157 | .name = "wsr.memctl", | |
4158 | .translate = translate_wsr, | |
4159 | .par = (const uint32_t[]){MEMCTL}, | |
4160 | }, { | |
4161 | .name = "wsr.misc0", | |
4162 | .translate = translate_wsr, | |
4163 | .par = (const uint32_t[]){MISC}, | |
4164 | }, { | |
4165 | .name = "wsr.misc1", | |
4166 | .translate = translate_wsr, | |
4167 | .par = (const uint32_t[]){MISC + 1}, | |
4168 | }, { | |
4169 | .name = "wsr.misc2", | |
4170 | .translate = translate_wsr, | |
4171 | .par = (const uint32_t[]){MISC + 2}, | |
4172 | }, { | |
4173 | .name = "wsr.misc3", | |
4174 | .translate = translate_wsr, | |
4175 | .par = (const uint32_t[]){MISC + 3}, | |
13f6a7cd MF |
4176 | }, { |
4177 | .name = "wsr.mmid", | |
4178 | .translate = translate_wsr, | |
4179 | .par = (const uint32_t[]){MMID}, | |
168c12b0 MF |
4180 | }, { |
4181 | .name = "wsr.prid", | |
4182 | .translate = translate_wsr, | |
4183 | .par = (const uint32_t[]){PRID}, | |
4184 | }, { | |
4185 | .name = "wsr.ps", | |
4186 | .translate = translate_wsr, | |
4187 | .par = (const uint32_t[]){PS}, | |
4188 | }, { | |
4189 | .name = "wsr.ptevaddr", | |
4190 | .translate = translate_wsr, | |
4191 | .par = (const uint32_t[]){PTEVADDR}, | |
4192 | }, { | |
4193 | .name = "wsr.rasid", | |
4194 | .translate = translate_wsr, | |
4195 | .par = (const uint32_t[]){RASID}, | |
4196 | }, { | |
4197 | .name = "wsr.sar", | |
4198 | .translate = translate_wsr, | |
4199 | .par = (const uint32_t[]){SAR}, | |
4200 | }, { | |
4201 | .name = "wsr.scompare1", | |
4202 | .translate = translate_wsr, | |
4203 | .par = (const uint32_t[]){SCOMPARE1}, | |
4204 | }, { | |
4205 | .name = "wsr.vecbase", | |
4206 | .translate = translate_wsr, | |
4207 | .par = (const uint32_t[]){VECBASE}, | |
4208 | }, { | |
4209 | .name = "wsr.windowbase", | |
4210 | .translate = translate_wsr, | |
4211 | .par = (const uint32_t[]){WINDOW_BASE}, | |
4212 | }, { | |
4213 | .name = "wsr.windowstart", | |
4214 | .translate = translate_wsr, | |
4215 | .par = (const uint32_t[]){WINDOW_START}, | |
e9872741 MF |
4216 | }, { |
4217 | .name = "wur.expstate", | |
4218 | .translate = translate_wur, | |
4219 | .par = (const uint32_t[]){EXPSTATE}, | |
168c12b0 MF |
4220 | }, { |
4221 | .name = "wur.fcr", | |
4222 | .translate = translate_wur, | |
4223 | .par = (const uint32_t[]){FCR}, | |
4224 | }, { | |
4225 | .name = "wur.fsr", | |
4226 | .translate = translate_wur, | |
4227 | .par = (const uint32_t[]){FSR}, | |
4228 | }, { | |
4229 | .name = "wur.threadptr", | |
4230 | .translate = translate_wur, | |
4231 | .par = (const uint32_t[]){THREADPTR}, | |
4232 | }, { | |
4233 | .name = "xor", | |
4234 | .translate = translate_xor, | |
4235 | }, { | |
4236 | .name = "xorb", | |
4237 | .translate = translate_boolean, | |
4238 | .par = (const uint32_t[]){BOOLEAN_XOR}, | |
4239 | }, { | |
4240 | .name = "xsr.176", | |
4241 | .translate = translate_xsr, | |
4242 | .par = (const uint32_t[]){176}, | |
4243 | }, { | |
4244 | .name = "xsr.208", | |
4245 | .translate = translate_xsr, | |
4246 | .par = (const uint32_t[]){208}, | |
4247 | }, { | |
4248 | .name = "xsr.acchi", | |
4249 | .translate = translate_xsr, | |
4250 | .par = (const uint32_t[]){ACCHI}, | |
4251 | }, { | |
4252 | .name = "xsr.acclo", | |
4253 | .translate = translate_xsr, | |
4254 | .par = (const uint32_t[]){ACCLO}, | |
4255 | }, { | |
4256 | .name = "xsr.atomctl", | |
4257 | .translate = translate_xsr, | |
4258 | .par = (const uint32_t[]){ATOMCTL}, | |
4259 | }, { | |
4260 | .name = "xsr.br", | |
4261 | .translate = translate_xsr, | |
4262 | .par = (const uint32_t[]){BR}, | |
4263 | }, { | |
4264 | .name = "xsr.cacheattr", | |
4265 | .translate = translate_xsr, | |
4266 | .par = (const uint32_t[]){CACHEATTR}, | |
4267 | }, { | |
4268 | .name = "xsr.ccompare0", | |
4269 | .translate = translate_xsr, | |
4270 | .par = (const uint32_t[]){CCOMPARE}, | |
4271 | }, { | |
4272 | .name = "xsr.ccompare1", | |
4273 | .translate = translate_xsr, | |
4274 | .par = (const uint32_t[]){CCOMPARE + 1}, | |
4275 | }, { | |
4276 | .name = "xsr.ccompare2", | |
4277 | .translate = translate_xsr, | |
4278 | .par = (const uint32_t[]){CCOMPARE + 2}, | |
4279 | }, { | |
4280 | .name = "xsr.ccount", | |
4281 | .translate = translate_xsr, | |
4282 | .par = (const uint32_t[]){CCOUNT}, | |
4283 | }, { | |
4284 | .name = "xsr.configid0", | |
4285 | .translate = translate_xsr, | |
4286 | .par = (const uint32_t[]){CONFIGID0}, | |
4287 | }, { | |
4288 | .name = "xsr.configid1", | |
4289 | .translate = translate_xsr, | |
4290 | .par = (const uint32_t[]){CONFIGID1}, | |
4291 | }, { | |
4292 | .name = "xsr.cpenable", | |
4293 | .translate = translate_xsr, | |
4294 | .par = (const uint32_t[]){CPENABLE}, | |
4295 | }, { | |
4296 | .name = "xsr.dbreaka0", | |
4297 | .translate = translate_xsr, | |
4298 | .par = (const uint32_t[]){DBREAKA}, | |
4299 | }, { | |
4300 | .name = "xsr.dbreaka1", | |
4301 | .translate = translate_xsr, | |
4302 | .par = (const uint32_t[]){DBREAKA + 1}, | |
4303 | }, { | |
4304 | .name = "xsr.dbreakc0", | |
4305 | .translate = translate_xsr, | |
4306 | .par = (const uint32_t[]){DBREAKC}, | |
4307 | }, { | |
4308 | .name = "xsr.dbreakc1", | |
4309 | .translate = translate_xsr, | |
4310 | .par = (const uint32_t[]){DBREAKC + 1}, | |
13f6a7cd MF |
4311 | }, { |
4312 | .name = "xsr.ddr", | |
4313 | .translate = translate_xsr, | |
4314 | .par = (const uint32_t[]){DDR}, | |
168c12b0 MF |
4315 | }, { |
4316 | .name = "xsr.debugcause", | |
4317 | .translate = translate_xsr, | |
4318 | .par = (const uint32_t[]){DEBUGCAUSE}, | |
4319 | }, { | |
4320 | .name = "xsr.depc", | |
4321 | .translate = translate_xsr, | |
4322 | .par = (const uint32_t[]){DEPC}, | |
4323 | }, { | |
4324 | .name = "xsr.dtlbcfg", | |
4325 | .translate = translate_xsr, | |
4326 | .par = (const uint32_t[]){DTLBCFG}, | |
4327 | }, { | |
4328 | .name = "xsr.epc1", | |
4329 | .translate = translate_xsr, | |
4330 | .par = (const uint32_t[]){EPC1}, | |
4331 | }, { | |
4332 | .name = "xsr.epc2", | |
4333 | .translate = translate_xsr, | |
4334 | .par = (const uint32_t[]){EPC1 + 1}, | |
4335 | }, { | |
4336 | .name = "xsr.epc3", | |
4337 | .translate = translate_xsr, | |
4338 | .par = (const uint32_t[]){EPC1 + 2}, | |
4339 | }, { | |
4340 | .name = "xsr.epc4", | |
4341 | .translate = translate_xsr, | |
4342 | .par = (const uint32_t[]){EPC1 + 3}, | |
4343 | }, { | |
4344 | .name = "xsr.epc5", | |
4345 | .translate = translate_xsr, | |
4346 | .par = (const uint32_t[]){EPC1 + 4}, | |
4347 | }, { | |
4348 | .name = "xsr.epc6", | |
4349 | .translate = translate_xsr, | |
4350 | .par = (const uint32_t[]){EPC1 + 5}, | |
4351 | }, { | |
4352 | .name = "xsr.epc7", | |
4353 | .translate = translate_xsr, | |
4354 | .par = (const uint32_t[]){EPC1 + 6}, | |
4355 | }, { | |
4356 | .name = "xsr.eps2", | |
4357 | .translate = translate_xsr, | |
4358 | .par = (const uint32_t[]){EPS2}, | |
4359 | }, { | |
4360 | .name = "xsr.eps3", | |
4361 | .translate = translate_xsr, | |
4362 | .par = (const uint32_t[]){EPS2 + 1}, | |
4363 | }, { | |
4364 | .name = "xsr.eps4", | |
4365 | .translate = translate_xsr, | |
4366 | .par = (const uint32_t[]){EPS2 + 2}, | |
4367 | }, { | |
4368 | .name = "xsr.eps5", | |
4369 | .translate = translate_xsr, | |
4370 | .par = (const uint32_t[]){EPS2 + 3}, | |
4371 | }, { | |
4372 | .name = "xsr.eps6", | |
4373 | .translate = translate_xsr, | |
4374 | .par = (const uint32_t[]){EPS2 + 4}, | |
4375 | }, { | |
4376 | .name = "xsr.eps7", | |
4377 | .translate = translate_xsr, | |
4378 | .par = (const uint32_t[]){EPS2 + 5}, | |
4379 | }, { | |
4380 | .name = "xsr.exccause", | |
4381 | .translate = translate_xsr, | |
4382 | .par = (const uint32_t[]){EXCCAUSE}, | |
4383 | }, { | |
4384 | .name = "xsr.excsave1", | |
4385 | .translate = translate_xsr, | |
4386 | .par = (const uint32_t[]){EXCSAVE1}, | |
4387 | }, { | |
4388 | .name = "xsr.excsave2", | |
4389 | .translate = translate_xsr, | |
4390 | .par = (const uint32_t[]){EXCSAVE1 + 1}, | |
4391 | }, { | |
4392 | .name = "xsr.excsave3", | |
4393 | .translate = translate_xsr, | |
4394 | .par = (const uint32_t[]){EXCSAVE1 + 2}, | |
4395 | }, { | |
4396 | .name = "xsr.excsave4", | |
4397 | .translate = translate_xsr, | |
4398 | .par = (const uint32_t[]){EXCSAVE1 + 3}, | |
4399 | }, { | |
4400 | .name = "xsr.excsave5", | |
4401 | .translate = translate_xsr, | |
4402 | .par = (const uint32_t[]){EXCSAVE1 + 4}, | |
4403 | }, { | |
4404 | .name = "xsr.excsave6", | |
4405 | .translate = translate_xsr, | |
4406 | .par = (const uint32_t[]){EXCSAVE1 + 5}, | |
4407 | }, { | |
4408 | .name = "xsr.excsave7", | |
4409 | .translate = translate_xsr, | |
4410 | .par = (const uint32_t[]){EXCSAVE1 + 6}, | |
4411 | }, { | |
4412 | .name = "xsr.excvaddr", | |
4413 | .translate = translate_xsr, | |
4414 | .par = (const uint32_t[]){EXCVADDR}, | |
4415 | }, { | |
4416 | .name = "xsr.ibreaka0", | |
4417 | .translate = translate_xsr, | |
4418 | .par = (const uint32_t[]){IBREAKA}, | |
4419 | }, { | |
4420 | .name = "xsr.ibreaka1", | |
4421 | .translate = translate_xsr, | |
4422 | .par = (const uint32_t[]){IBREAKA + 1}, | |
4423 | }, { | |
4424 | .name = "xsr.ibreakenable", | |
4425 | .translate = translate_xsr, | |
4426 | .par = (const uint32_t[]){IBREAKENABLE}, | |
4427 | }, { | |
4428 | .name = "xsr.icount", | |
4429 | .translate = translate_xsr, | |
4430 | .par = (const uint32_t[]){ICOUNT}, | |
4431 | }, { | |
4432 | .name = "xsr.icountlevel", | |
4433 | .translate = translate_xsr, | |
4434 | .par = (const uint32_t[]){ICOUNTLEVEL}, | |
4435 | }, { | |
4436 | .name = "xsr.intclear", | |
4437 | .translate = translate_xsr, | |
4438 | .par = (const uint32_t[]){INTCLEAR}, | |
4439 | }, { | |
4440 | .name = "xsr.intenable", | |
4441 | .translate = translate_xsr, | |
4442 | .par = (const uint32_t[]){INTENABLE}, | |
4443 | }, { | |
4444 | .name = "xsr.interrupt", | |
4445 | .translate = translate_xsr, | |
4446 | .par = (const uint32_t[]){INTSET}, | |
4447 | }, { | |
4448 | .name = "xsr.intset", | |
4449 | .translate = translate_xsr, | |
4450 | .par = (const uint32_t[]){INTSET}, | |
4451 | }, { | |
4452 | .name = "xsr.itlbcfg", | |
4453 | .translate = translate_xsr, | |
4454 | .par = (const uint32_t[]){ITLBCFG}, | |
4455 | }, { | |
4456 | .name = "xsr.lbeg", | |
4457 | .translate = translate_xsr, | |
4458 | .par = (const uint32_t[]){LBEG}, | |
4459 | }, { | |
4460 | .name = "xsr.lcount", | |
4461 | .translate = translate_xsr, | |
4462 | .par = (const uint32_t[]){LCOUNT}, | |
4463 | }, { | |
4464 | .name = "xsr.lend", | |
4465 | .translate = translate_xsr, | |
4466 | .par = (const uint32_t[]){LEND}, | |
4467 | }, { | |
4468 | .name = "xsr.litbase", | |
4469 | .translate = translate_xsr, | |
4470 | .par = (const uint32_t[]){LITBASE}, | |
4471 | }, { | |
4472 | .name = "xsr.m0", | |
4473 | .translate = translate_xsr, | |
4474 | .par = (const uint32_t[]){MR}, | |
4475 | }, { | |
4476 | .name = "xsr.m1", | |
4477 | .translate = translate_xsr, | |
4478 | .par = (const uint32_t[]){MR + 1}, | |
4479 | }, { | |
4480 | .name = "xsr.m2", | |
4481 | .translate = translate_xsr, | |
4482 | .par = (const uint32_t[]){MR + 2}, | |
4483 | }, { | |
4484 | .name = "xsr.m3", | |
4485 | .translate = translate_xsr, | |
4486 | .par = (const uint32_t[]){MR + 3}, | |
4487 | }, { | |
4488 | .name = "xsr.memctl", | |
4489 | .translate = translate_xsr, | |
4490 | .par = (const uint32_t[]){MEMCTL}, | |
4491 | }, { | |
4492 | .name = "xsr.misc0", | |
4493 | .translate = translate_xsr, | |
4494 | .par = (const uint32_t[]){MISC}, | |
4495 | }, { | |
4496 | .name = "xsr.misc1", | |
4497 | .translate = translate_xsr, | |
4498 | .par = (const uint32_t[]){MISC + 1}, | |
4499 | }, { | |
4500 | .name = "xsr.misc2", | |
4501 | .translate = translate_xsr, | |
4502 | .par = (const uint32_t[]){MISC + 2}, | |
4503 | }, { | |
4504 | .name = "xsr.misc3", | |
4505 | .translate = translate_xsr, | |
4506 | .par = (const uint32_t[]){MISC + 3}, | |
4507 | }, { | |
4508 | .name = "xsr.prid", | |
4509 | .translate = translate_xsr, | |
4510 | .par = (const uint32_t[]){PRID}, | |
4511 | }, { | |
4512 | .name = "xsr.ps", | |
4513 | .translate = translate_xsr, | |
4514 | .par = (const uint32_t[]){PS}, | |
4515 | }, { | |
4516 | .name = "xsr.ptevaddr", | |
4517 | .translate = translate_xsr, | |
4518 | .par = (const uint32_t[]){PTEVADDR}, | |
4519 | }, { | |
4520 | .name = "xsr.rasid", | |
4521 | .translate = translate_xsr, | |
4522 | .par = (const uint32_t[]){RASID}, | |
4523 | }, { | |
4524 | .name = "xsr.sar", | |
4525 | .translate = translate_xsr, | |
4526 | .par = (const uint32_t[]){SAR}, | |
4527 | }, { | |
4528 | .name = "xsr.scompare1", | |
4529 | .translate = translate_xsr, | |
4530 | .par = (const uint32_t[]){SCOMPARE1}, | |
4531 | }, { | |
4532 | .name = "xsr.vecbase", | |
4533 | .translate = translate_xsr, | |
4534 | .par = (const uint32_t[]){VECBASE}, | |
4535 | }, { | |
4536 | .name = "xsr.windowbase", | |
4537 | .translate = translate_xsr, | |
4538 | .par = (const uint32_t[]){WINDOW_BASE}, | |
4539 | }, { | |
4540 | .name = "xsr.windowstart", | |
4541 | .translate = translate_xsr, | |
4542 | .par = (const uint32_t[]){WINDOW_START}, | |
4543 | }, | |
4544 | }; | |
4545 | ||
4546 | const XtensaOpcodeTranslators xtensa_core_opcodes = { | |
4547 | .num_opcodes = ARRAY_SIZE(core_ops), | |
4548 | .opcode = core_ops, | |
4549 | }; | |
c04e1692 MF |
4550 | |
4551 | ||
4552 | static void translate_abs_s(DisasContext *dc, const uint32_t arg[], | |
4553 | const uint32_t par[]) | |
4554 | { | |
4555 | if (gen_check_cpenable(dc, 0)) { | |
4556 | gen_helper_abs_s(cpu_FR[arg[0]], cpu_FR[arg[1]]); | |
4557 | } | |
4558 | } | |
4559 | ||
4560 | static void translate_add_s(DisasContext *dc, const uint32_t arg[], | |
4561 | const uint32_t par[]) | |
4562 | { | |
4563 | if (gen_check_cpenable(dc, 0)) { | |
4564 | gen_helper_add_s(cpu_FR[arg[0]], cpu_env, | |
4565 | cpu_FR[arg[1]], cpu_FR[arg[2]]); | |
4566 | } | |
4567 | } | |
4568 | ||
4569 | enum { | |
4570 | COMPARE_UN, | |
4571 | COMPARE_OEQ, | |
4572 | COMPARE_UEQ, | |
4573 | COMPARE_OLT, | |
4574 | COMPARE_ULT, | |
4575 | COMPARE_OLE, | |
4576 | COMPARE_ULE, | |
4577 | }; | |
4578 | ||
4579 | static void translate_compare_s(DisasContext *dc, const uint32_t arg[], | |
4580 | const uint32_t par[]) | |
4581 | { | |
4582 | static void (* const helper[])(TCGv_env env, TCGv_i32 bit, | |
4583 | TCGv_i32 s, TCGv_i32 t) = { | |
4584 | [COMPARE_UN] = gen_helper_un_s, | |
4585 | [COMPARE_OEQ] = gen_helper_oeq_s, | |
4586 | [COMPARE_UEQ] = gen_helper_ueq_s, | |
4587 | [COMPARE_OLT] = gen_helper_olt_s, | |
4588 | [COMPARE_ULT] = gen_helper_ult_s, | |
4589 | [COMPARE_OLE] = gen_helper_ole_s, | |
4590 | [COMPARE_ULE] = gen_helper_ule_s, | |
4591 | }; | |
4592 | ||
4593 | if (gen_check_cpenable(dc, 0)) { | |
4594 | TCGv_i32 bit = tcg_const_i32(1 << arg[0]); | |
4595 | ||
4596 | helper[par[0]](cpu_env, bit, cpu_FR[arg[1]], cpu_FR[arg[2]]); | |
4597 | tcg_temp_free(bit); | |
4598 | } | |
4599 | } | |
4600 | ||
4601 | static void translate_float_s(DisasContext *dc, const uint32_t arg[], | |
4602 | const uint32_t par[]) | |
4603 | { | |
4604 | if (gen_window_check1(dc, arg[1]) && gen_check_cpenable(dc, 0)) { | |
4605 | TCGv_i32 scale = tcg_const_i32(-arg[2]); | |
4606 | ||
4607 | if (par[0]) { | |
4608 | gen_helper_uitof(cpu_FR[arg[0]], cpu_env, cpu_R[arg[1]], scale); | |
4609 | } else { | |
4610 | gen_helper_itof(cpu_FR[arg[0]], cpu_env, cpu_R[arg[1]], scale); | |
4611 | } | |
4612 | tcg_temp_free(scale); | |
4613 | } | |
4614 | } | |
4615 | ||
4616 | static void translate_ftoi_s(DisasContext *dc, const uint32_t arg[], | |
4617 | const uint32_t par[]) | |
4618 | { | |
4619 | if (gen_window_check1(dc, arg[0]) && gen_check_cpenable(dc, 0)) { | |
4620 | TCGv_i32 rounding_mode = tcg_const_i32(par[0]); | |
4621 | TCGv_i32 scale = tcg_const_i32(arg[2]); | |
4622 | ||
4623 | if (par[1]) { | |
4624 | gen_helper_ftoui(cpu_R[arg[0]], cpu_FR[arg[1]], | |
4625 | rounding_mode, scale); | |
4626 | } else { | |
4627 | gen_helper_ftoi(cpu_R[arg[0]], cpu_FR[arg[1]], | |
4628 | rounding_mode, scale); | |
4629 | } | |
4630 | tcg_temp_free(rounding_mode); | |
4631 | tcg_temp_free(scale); | |
4632 | } | |
4633 | } | |
4634 | ||
4635 | static void translate_ldsti(DisasContext *dc, const uint32_t arg[], | |
4636 | const uint32_t par[]) | |
4637 | { | |
4638 | if (gen_window_check1(dc, arg[1]) && gen_check_cpenable(dc, 0)) { | |
4639 | TCGv_i32 addr = tcg_temp_new_i32(); | |
4640 | ||
4641 | tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]); | |
4642 | gen_load_store_alignment(dc, 2, addr, false); | |
4643 | if (par[0]) { | |
4644 | tcg_gen_qemu_st32(cpu_FR[arg[0]], addr, dc->cring); | |
4645 | } else { | |
4646 | tcg_gen_qemu_ld32u(cpu_FR[arg[0]], addr, dc->cring); | |
4647 | } | |
4648 | if (par[1]) { | |
4649 | tcg_gen_mov_i32(cpu_R[arg[1]], addr); | |
4650 | } | |
4651 | tcg_temp_free(addr); | |
4652 | } | |
4653 | } | |
4654 | ||
4655 | static void translate_ldstx(DisasContext *dc, const uint32_t arg[], | |
4656 | const uint32_t par[]) | |
4657 | { | |
4658 | if (gen_window_check2(dc, arg[1], arg[2]) && gen_check_cpenable(dc, 0)) { | |
4659 | TCGv_i32 addr = tcg_temp_new_i32(); | |
4660 | ||
4661 | tcg_gen_add_i32(addr, cpu_R[arg[1]], cpu_R[arg[2]]); | |
4662 | gen_load_store_alignment(dc, 2, addr, false); | |
4663 | if (par[0]) { | |
4664 | tcg_gen_qemu_st32(cpu_FR[arg[0]], addr, dc->cring); | |
4665 | } else { | |
4666 | tcg_gen_qemu_ld32u(cpu_FR[arg[0]], addr, dc->cring); | |
4667 | } | |
4668 | if (par[1]) { | |
4669 | tcg_gen_mov_i32(cpu_R[arg[1]], addr); | |
4670 | } | |
4671 | tcg_temp_free(addr); | |
4672 | } | |
4673 | } | |
4674 | ||
4675 | static void translate_madd_s(DisasContext *dc, const uint32_t arg[], | |
4676 | const uint32_t par[]) | |
4677 | { | |
4678 | if (gen_check_cpenable(dc, 0)) { | |
4679 | gen_helper_madd_s(cpu_FR[arg[0]], cpu_env, | |
4680 | cpu_FR[arg[0]], cpu_FR[arg[1]], cpu_FR[arg[2]]); | |
4681 | } | |
4682 | } | |
4683 | ||
4684 | static void translate_mov_s(DisasContext *dc, const uint32_t arg[], | |
4685 | const uint32_t par[]) | |
4686 | { | |
4687 | if (gen_check_cpenable(dc, 0)) { | |
4688 | tcg_gen_mov_i32(cpu_FR[arg[0]], cpu_FR[arg[1]]); | |
4689 | } | |
4690 | } | |
4691 | ||
4692 | static void translate_movcond_s(DisasContext *dc, const uint32_t arg[], | |
4693 | const uint32_t par[]) | |
4694 | { | |
4695 | if (gen_window_check1(dc, arg[2]) && gen_check_cpenable(dc, 0)) { | |
4696 | TCGv_i32 zero = tcg_const_i32(0); | |
4697 | ||
4698 | tcg_gen_movcond_i32(par[0], cpu_FR[arg[0]], | |
4699 | cpu_R[arg[2]], zero, | |
4700 | cpu_FR[arg[1]], cpu_FR[arg[2]]); | |
4701 | tcg_temp_free(zero); | |
4702 | } | |
4703 | } | |
4704 | ||
4705 | static void translate_movp_s(DisasContext *dc, const uint32_t arg[], | |
4706 | const uint32_t par[]) | |
4707 | { | |
4708 | if (gen_check_cpenable(dc, 0)) { | |
4709 | TCGv_i32 zero = tcg_const_i32(0); | |
4710 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
4711 | ||
4712 | tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[2]); | |
4713 | tcg_gen_movcond_i32(par[0], | |
4714 | cpu_FR[arg[0]], tmp, zero, | |
4715 | cpu_FR[arg[1]], cpu_FR[arg[0]]); | |
4716 | tcg_temp_free(tmp); | |
4717 | tcg_temp_free(zero); | |
4718 | } | |
4719 | } | |
4720 | ||
4721 | static void translate_mul_s(DisasContext *dc, const uint32_t arg[], | |
4722 | const uint32_t par[]) | |
4723 | { | |
4724 | if (gen_check_cpenable(dc, 0)) { | |
4725 | gen_helper_mul_s(cpu_FR[arg[0]], cpu_env, | |
4726 | cpu_FR[arg[1]], cpu_FR[arg[2]]); | |
4727 | } | |
4728 | } | |
4729 | ||
4730 | static void translate_msub_s(DisasContext *dc, const uint32_t arg[], | |
4731 | const uint32_t par[]) | |
4732 | { | |
4733 | if (gen_check_cpenable(dc, 0)) { | |
4734 | gen_helper_msub_s(cpu_FR[arg[0]], cpu_env, | |
4735 | cpu_FR[arg[0]], cpu_FR[arg[1]], cpu_FR[arg[2]]); | |
4736 | } | |
4737 | } | |
4738 | ||
4739 | static void translate_neg_s(DisasContext *dc, const uint32_t arg[], | |
4740 | const uint32_t par[]) | |
4741 | { | |
4742 | if (gen_check_cpenable(dc, 0)) { | |
4743 | gen_helper_neg_s(cpu_FR[arg[0]], cpu_FR[arg[1]]); | |
4744 | } | |
4745 | } | |
4746 | ||
4747 | static void translate_rfr_s(DisasContext *dc, const uint32_t arg[], | |
4748 | const uint32_t par[]) | |
4749 | { | |
4750 | if (gen_window_check1(dc, arg[0]) && | |
4751 | gen_check_cpenable(dc, 0)) { | |
4752 | tcg_gen_mov_i32(cpu_R[arg[0]], cpu_FR[arg[1]]); | |
4753 | } | |
4754 | } | |
4755 | ||
4756 | static void translate_sub_s(DisasContext *dc, const uint32_t arg[], | |
4757 | const uint32_t par[]) | |
4758 | { | |
4759 | if (gen_check_cpenable(dc, 0)) { | |
4760 | gen_helper_sub_s(cpu_FR[arg[0]], cpu_env, | |
4761 | cpu_FR[arg[1]], cpu_FR[arg[2]]); | |
4762 | } | |
4763 | } | |
4764 | ||
4765 | static void translate_wfr_s(DisasContext *dc, const uint32_t arg[], | |
4766 | const uint32_t par[]) | |
4767 | { | |
4768 | if (gen_window_check1(dc, arg[1]) && | |
4769 | gen_check_cpenable(dc, 0)) { | |
4770 | tcg_gen_mov_i32(cpu_FR[arg[0]], cpu_R[arg[1]]); | |
4771 | } | |
4772 | } | |
4773 | ||
4774 | static const XtensaOpcodeOps fpu2000_ops[] = { | |
4775 | { | |
4776 | .name = "abs.s", | |
4777 | .translate = translate_abs_s, | |
4778 | }, { | |
4779 | .name = "add.s", | |
4780 | .translate = translate_add_s, | |
4781 | }, { | |
4782 | .name = "ceil.s", | |
4783 | .translate = translate_ftoi_s, | |
4784 | .par = (const uint32_t[]){float_round_up, false}, | |
4785 | }, { | |
4786 | .name = "float.s", | |
4787 | .translate = translate_float_s, | |
4788 | .par = (const uint32_t[]){false}, | |
4789 | }, { | |
4790 | .name = "floor.s", | |
4791 | .translate = translate_ftoi_s, | |
4792 | .par = (const uint32_t[]){float_round_down, false}, | |
4793 | }, { | |
4794 | .name = "lsi", | |
4795 | .translate = translate_ldsti, | |
4796 | .par = (const uint32_t[]){false, false}, | |
4797 | }, { | |
4798 | .name = "lsiu", | |
4799 | .translate = translate_ldsti, | |
4800 | .par = (const uint32_t[]){false, true}, | |
4801 | }, { | |
4802 | .name = "lsx", | |
4803 | .translate = translate_ldstx, | |
4804 | .par = (const uint32_t[]){false, false}, | |
4805 | }, { | |
4806 | .name = "lsxu", | |
4807 | .translate = translate_ldstx, | |
4808 | .par = (const uint32_t[]){false, true}, | |
4809 | }, { | |
4810 | .name = "madd.s", | |
4811 | .translate = translate_madd_s, | |
4812 | }, { | |
4813 | .name = "mov.s", | |
4814 | .translate = translate_mov_s, | |
4815 | }, { | |
4816 | .name = "moveqz.s", | |
4817 | .translate = translate_movcond_s, | |
4818 | .par = (const uint32_t[]){TCG_COND_EQ}, | |
4819 | }, { | |
4820 | .name = "movf.s", | |
4821 | .translate = translate_movp_s, | |
4822 | .par = (const uint32_t[]){TCG_COND_EQ}, | |
4823 | }, { | |
4824 | .name = "movgez.s", | |
4825 | .translate = translate_movcond_s, | |
4826 | .par = (const uint32_t[]){TCG_COND_GE}, | |
4827 | }, { | |
4828 | .name = "movltz.s", | |
4829 | .translate = translate_movcond_s, | |
4830 | .par = (const uint32_t[]){TCG_COND_LT}, | |
4831 | }, { | |
4832 | .name = "movnez.s", | |
4833 | .translate = translate_movcond_s, | |
4834 | .par = (const uint32_t[]){TCG_COND_NE}, | |
4835 | }, { | |
4836 | .name = "movt.s", | |
4837 | .translate = translate_movp_s, | |
4838 | .par = (const uint32_t[]){TCG_COND_NE}, | |
4839 | }, { | |
4840 | .name = "msub.s", | |
4841 | .translate = translate_msub_s, | |
4842 | }, { | |
4843 | .name = "mul.s", | |
4844 | .translate = translate_mul_s, | |
4845 | }, { | |
4846 | .name = "neg.s", | |
4847 | .translate = translate_neg_s, | |
4848 | }, { | |
4849 | .name = "oeq.s", | |
4850 | .translate = translate_compare_s, | |
4851 | .par = (const uint32_t[]){COMPARE_OEQ}, | |
4852 | }, { | |
4853 | .name = "ole.s", | |
4854 | .translate = translate_compare_s, | |
4855 | .par = (const uint32_t[]){COMPARE_OLE}, | |
4856 | }, { | |
4857 | .name = "olt.s", | |
4858 | .translate = translate_compare_s, | |
4859 | .par = (const uint32_t[]){COMPARE_OLT}, | |
4860 | }, { | |
4861 | .name = "rfr.s", | |
4862 | .translate = translate_rfr_s, | |
4863 | }, { | |
4864 | .name = "round.s", | |
4865 | .translate = translate_ftoi_s, | |
4866 | .par = (const uint32_t[]){float_round_nearest_even, false}, | |
4867 | }, { | |
4868 | .name = "ssi", | |
4869 | .translate = translate_ldsti, | |
4870 | .par = (const uint32_t[]){true, false}, | |
4871 | }, { | |
4872 | .name = "ssiu", | |
4873 | .translate = translate_ldsti, | |
4874 | .par = (const uint32_t[]){true, true}, | |
4875 | }, { | |
4876 | .name = "ssx", | |
4877 | .translate = translate_ldstx, | |
4878 | .par = (const uint32_t[]){true, false}, | |
4879 | }, { | |
4880 | .name = "ssxu", | |
4881 | .translate = translate_ldstx, | |
4882 | .par = (const uint32_t[]){true, true}, | |
4883 | }, { | |
4884 | .name = "sub.s", | |
4885 | .translate = translate_sub_s, | |
4886 | }, { | |
4887 | .name = "trunc.s", | |
4888 | .translate = translate_ftoi_s, | |
4889 | .par = (const uint32_t[]){float_round_to_zero, false}, | |
4890 | }, { | |
4891 | .name = "ueq.s", | |
4892 | .translate = translate_compare_s, | |
4893 | .par = (const uint32_t[]){COMPARE_UEQ}, | |
4894 | }, { | |
4895 | .name = "ufloat.s", | |
4896 | .translate = translate_float_s, | |
4897 | .par = (const uint32_t[]){true}, | |
4898 | }, { | |
4899 | .name = "ule.s", | |
4900 | .translate = translate_compare_s, | |
4901 | .par = (const uint32_t[]){COMPARE_ULE}, | |
4902 | }, { | |
4903 | .name = "ult.s", | |
4904 | .translate = translate_compare_s, | |
4905 | .par = (const uint32_t[]){COMPARE_ULT}, | |
4906 | }, { | |
4907 | .name = "un.s", | |
4908 | .translate = translate_compare_s, | |
4909 | .par = (const uint32_t[]){COMPARE_UN}, | |
4910 | }, { | |
4911 | .name = "utrunc.s", | |
4912 | .translate = translate_ftoi_s, | |
4913 | .par = (const uint32_t[]){float_round_to_zero, true}, | |
4914 | }, { | |
4915 | .name = "wfr.s", | |
4916 | .translate = translate_wfr_s, | |
4917 | }, | |
4918 | }; | |
4919 | ||
4920 | const XtensaOpcodeTranslators xtensa_fpu2000_opcodes = { | |
4921 | .num_opcodes = ARRAY_SIZE(fpu2000_ops), | |
4922 | .opcode = fpu2000_ops, | |
4923 | }; |