]> git.proxmox.com Git - qemu.git/blame - target-xtensa/translate.c
target-xtensa: restrict available SRs by enabled options
[qemu.git] / target-xtensa / translate.c
CommitLineData
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
31#include <stdio.h>
32
33#include "cpu.h"
34#include "exec-all.h"
35#include "disas.h"
36#include "tcg-op.h"
37#include "qemu-log.h"
1ddeaa5d 38#include "sysemu.h"
2328826b 39
16c1deae 40#include "helper.h"
dedc5eae 41#define GEN_HELPER 1
16c1deae 42#include "helper.h"
dedc5eae
MF
43
44typedef struct DisasContext {
45 const XtensaConfig *config;
46 TranslationBlock *tb;
47 uint32_t pc;
48 uint32_t next_pc;
f0a548b9
MF
49 int cring;
50 int ring;
797d780b
MF
51 uint32_t lbeg;
52 uint32_t lend;
6ad6dbf7 53 TCGv_i32 litbase;
dedc5eae
MF
54 int is_jmp;
55 int singlestep_enabled;
3580ecad
MF
56
57 bool sar_5bit;
58 bool sar_m32_5bit;
59 bool sar_m32_allocated;
60 TCGv_i32 sar_m32;
b994e91b
MF
61
62 uint32_t ccount_delta;
772177c1 63 unsigned used_window;
e61dc8f7
MF
64
65 bool debug;
35b5c044
MF
66 bool icount;
67 TCGv_i32 next_icount;
ef04a846
MF
68
69 unsigned cpenable;
dedc5eae
MF
70} DisasContext;
71
72static TCGv_ptr cpu_env;
73static TCGv_i32 cpu_pc;
74static TCGv_i32 cpu_R[16];
dd519cbe 75static TCGv_i32 cpu_FR[16];
2af3da91
MF
76static TCGv_i32 cpu_SR[256];
77static TCGv_i32 cpu_UR[256];
dedc5eae
MF
78
79#include "gen-icount.h"
2328826b 80
fe0bd475
MF
81typedef struct XtensaReg {
82 const char *name;
83 uint64_t opt_bits;
84} XtensaReg;
85
86#define XTENSA_REG(regname, opt) { \
87 .name = (regname), \
88 .opt_bits = XTENSA_OPTION_BIT(opt), \
89 }
90
91#define XTENSA_REG_BITS(regname, opt) { \
92 .name = (regname), \
93 .opt_bits = (opt), \
94 }
95
96static const XtensaReg sregnames[256] = {
97 [LBEG] = XTENSA_REG("LBEG", XTENSA_OPTION_LOOP),
98 [LEND] = XTENSA_REG("LEND", XTENSA_OPTION_LOOP),
99 [LCOUNT] = XTENSA_REG("LCOUNT", XTENSA_OPTION_LOOP),
100 [SAR] = XTENSA_REG_BITS("SAR", XTENSA_OPTION_ALL),
101 [BR] = XTENSA_REG("BR", XTENSA_OPTION_BOOLEAN),
102 [LITBASE] = XTENSA_REG("LITBASE", XTENSA_OPTION_EXTENDED_L32R),
103 [SCOMPARE1] = XTENSA_REG("SCOMPARE1", XTENSA_OPTION_CONDITIONAL_STORE),
104 [ACCLO] = XTENSA_REG("ACCLO", XTENSA_OPTION_MAC16),
105 [ACCHI] = XTENSA_REG("ACCHI", XTENSA_OPTION_MAC16),
106 [MR] = XTENSA_REG("MR0", XTENSA_OPTION_MAC16),
107 [MR + 1] = XTENSA_REG("MR1", XTENSA_OPTION_MAC16),
108 [MR + 2] = XTENSA_REG("MR2", XTENSA_OPTION_MAC16),
109 [MR + 3] = XTENSA_REG("MR3", XTENSA_OPTION_MAC16),
110 [WINDOW_BASE] = XTENSA_REG("WINDOW_BASE", XTENSA_OPTION_WINDOWED_REGISTER),
111 [WINDOW_START] = XTENSA_REG("WINDOW_START",
112 XTENSA_OPTION_WINDOWED_REGISTER),
113 [PTEVADDR] = XTENSA_REG("PTEVADDR", XTENSA_OPTION_MMU),
114 [RASID] = XTENSA_REG("RASID", XTENSA_OPTION_MMU),
115 [ITLBCFG] = XTENSA_REG("ITLBCFG", XTENSA_OPTION_MMU),
116 [DTLBCFG] = XTENSA_REG("DTLBCFG", XTENSA_OPTION_MMU),
117 [IBREAKENABLE] = XTENSA_REG("IBREAKENABLE", XTENSA_OPTION_DEBUG),
118 [CACHEATTR] = XTENSA_REG("CACHEATTR", XTENSA_OPTION_CACHEATTR),
119 [ATOMCTL] = XTENSA_REG("ATOMCTL", XTENSA_OPTION_ATOMCTL),
120 [IBREAKA] = XTENSA_REG("IBREAKA0", XTENSA_OPTION_DEBUG),
121 [IBREAKA + 1] = XTENSA_REG("IBREAKA1", XTENSA_OPTION_DEBUG),
122 [DBREAKA] = XTENSA_REG("DBREAKA0", XTENSA_OPTION_DEBUG),
123 [DBREAKA + 1] = XTENSA_REG("DBREAKA1", XTENSA_OPTION_DEBUG),
124 [DBREAKC] = XTENSA_REG("DBREAKC0", XTENSA_OPTION_DEBUG),
125 [DBREAKC + 1] = XTENSA_REG("DBREAKC1", XTENSA_OPTION_DEBUG),
126 [EPC1] = XTENSA_REG("EPC1", XTENSA_OPTION_EXCEPTION),
127 [EPC1 + 1] = XTENSA_REG("EPC2", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
128 [EPC1 + 2] = XTENSA_REG("EPC3", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
129 [EPC1 + 3] = XTENSA_REG("EPC4", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
130 [EPC1 + 4] = XTENSA_REG("EPC5", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
131 [EPC1 + 5] = XTENSA_REG("EPC6", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
132 [EPC1 + 6] = XTENSA_REG("EPC7", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
133 [DEPC] = XTENSA_REG("DEPC", XTENSA_OPTION_EXCEPTION),
134 [EPS2] = XTENSA_REG("EPS2", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
135 [EPS2 + 1] = XTENSA_REG("EPS3", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
136 [EPS2 + 2] = XTENSA_REG("EPS4", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
137 [EPS2 + 3] = XTENSA_REG("EPS5", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
138 [EPS2 + 4] = XTENSA_REG("EPS6", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
139 [EPS2 + 5] = XTENSA_REG("EPS7", XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
140 [EXCSAVE1] = XTENSA_REG("EXCSAVE1", XTENSA_OPTION_EXCEPTION),
141 [EXCSAVE1 + 1] = XTENSA_REG("EXCSAVE2",
142 XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
143 [EXCSAVE1 + 2] = XTENSA_REG("EXCSAVE3",
144 XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
145 [EXCSAVE1 + 3] = XTENSA_REG("EXCSAVE4",
146 XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
147 [EXCSAVE1 + 4] = XTENSA_REG("EXCSAVE5",
148 XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
149 [EXCSAVE1 + 5] = XTENSA_REG("EXCSAVE6",
150 XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
151 [EXCSAVE1 + 6] = XTENSA_REG("EXCSAVE7",
152 XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT),
153 [CPENABLE] = XTENSA_REG("CPENABLE", XTENSA_OPTION_COPROCESSOR),
154 [INTSET] = XTENSA_REG("INTSET", XTENSA_OPTION_INTERRUPT),
155 [INTCLEAR] = XTENSA_REG("INTCLEAR", XTENSA_OPTION_INTERRUPT),
156 [INTENABLE] = XTENSA_REG("INTENABLE", XTENSA_OPTION_INTERRUPT),
157 [PS] = XTENSA_REG_BITS("PS", XTENSA_OPTION_ALL),
158 [VECBASE] = XTENSA_REG("VECBASE", XTENSA_OPTION_RELOCATABLE_VECTOR),
159 [EXCCAUSE] = XTENSA_REG("EXCCAUSE", XTENSA_OPTION_EXCEPTION),
160 [DEBUGCAUSE] = XTENSA_REG("DEBUGCAUSE", XTENSA_OPTION_DEBUG),
161 [CCOUNT] = XTENSA_REG("CCOUNT", XTENSA_OPTION_TIMER_INTERRUPT),
162 [PRID] = XTENSA_REG("PRID", XTENSA_OPTION_PROCESSOR_ID),
163 [ICOUNT] = XTENSA_REG("ICOUNT", XTENSA_OPTION_DEBUG),
164 [ICOUNTLEVEL] = XTENSA_REG("ICOUNTLEVEL", XTENSA_OPTION_DEBUG),
165 [EXCVADDR] = XTENSA_REG("EXCVADDR", XTENSA_OPTION_EXCEPTION),
166 [CCOMPARE] = XTENSA_REG("CCOMPARE0", XTENSA_OPTION_TIMER_INTERRUPT),
167 [CCOMPARE + 1] = XTENSA_REG("CCOMPARE1",
168 XTENSA_OPTION_TIMER_INTERRUPT),
169 [CCOMPARE + 2] = XTENSA_REG("CCOMPARE2",
170 XTENSA_OPTION_TIMER_INTERRUPT),
2af3da91
MF
171};
172
fe0bd475
MF
173static const XtensaReg uregnames[256] = {
174 [THREADPTR] = XTENSA_REG("THREADPTR", XTENSA_OPTION_THREAD_POINTER),
175 [FCR] = XTENSA_REG("FCR", XTENSA_OPTION_FP_COPROCESSOR),
176 [FSR] = XTENSA_REG("FSR", XTENSA_OPTION_FP_COPROCESSOR),
2af3da91
MF
177};
178
2328826b
MF
179void xtensa_translate_init(void)
180{
dedc5eae
MF
181 static const char * const regnames[] = {
182 "ar0", "ar1", "ar2", "ar3",
183 "ar4", "ar5", "ar6", "ar7",
184 "ar8", "ar9", "ar10", "ar11",
185 "ar12", "ar13", "ar14", "ar15",
186 };
dd519cbe
MF
187 static const char * const fregnames[] = {
188 "f0", "f1", "f2", "f3",
189 "f4", "f5", "f6", "f7",
190 "f8", "f9", "f10", "f11",
191 "f12", "f13", "f14", "f15",
192 };
dedc5eae
MF
193 int i;
194
195 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
196 cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
97129ac8 197 offsetof(CPUXtensaState, pc), "pc");
dedc5eae
MF
198
199 for (i = 0; i < 16; i++) {
200 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
97129ac8 201 offsetof(CPUXtensaState, regs[i]),
dedc5eae
MF
202 regnames[i]);
203 }
2af3da91 204
dd519cbe
MF
205 for (i = 0; i < 16; i++) {
206 cpu_FR[i] = tcg_global_mem_new_i32(TCG_AREG0,
207 offsetof(CPUXtensaState, fregs[i]),
208 fregnames[i]);
209 }
210
2af3da91 211 for (i = 0; i < 256; ++i) {
fe0bd475 212 if (sregnames[i].name) {
2af3da91 213 cpu_SR[i] = tcg_global_mem_new_i32(TCG_AREG0,
97129ac8 214 offsetof(CPUXtensaState, sregs[i]),
fe0bd475 215 sregnames[i].name);
2af3da91
MF
216 }
217 }
218
219 for (i = 0; i < 256; ++i) {
fe0bd475 220 if (uregnames[i].name) {
2af3da91 221 cpu_UR[i] = tcg_global_mem_new_i32(TCG_AREG0,
97129ac8 222 offsetof(CPUXtensaState, uregs[i]),
fe0bd475 223 uregnames[i].name);
2af3da91
MF
224 }
225 }
dedc5eae 226#define GEN_HELPER 2
16c1deae 227#include "helper.h"
dedc5eae
MF
228}
229
b67ea0cd
MF
230static inline bool option_bits_enabled(DisasContext *dc, uint64_t opt)
231{
232 return xtensa_option_bits_enabled(dc->config, opt);
233}
234
dedc5eae
MF
235static inline bool option_enabled(DisasContext *dc, int opt)
236{
237 return xtensa_option_enabled(dc->config, opt);
238}
239
6ad6dbf7
MF
240static void init_litbase(DisasContext *dc)
241{
242 if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) {
243 dc->litbase = tcg_temp_local_new_i32();
244 tcg_gen_andi_i32(dc->litbase, cpu_SR[LITBASE], 0xfffff000);
245 }
246}
247
248static void reset_litbase(DisasContext *dc)
249{
250 if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) {
251 tcg_temp_free(dc->litbase);
252 }
253}
254
3580ecad
MF
255static void init_sar_tracker(DisasContext *dc)
256{
257 dc->sar_5bit = false;
258 dc->sar_m32_5bit = false;
259 dc->sar_m32_allocated = false;
260}
261
262static void reset_sar_tracker(DisasContext *dc)
263{
264 if (dc->sar_m32_allocated) {
265 tcg_temp_free(dc->sar_m32);
266 }
267}
268
269static void gen_right_shift_sar(DisasContext *dc, TCGv_i32 sa)
270{
271 tcg_gen_andi_i32(cpu_SR[SAR], sa, 0x1f);
272 if (dc->sar_m32_5bit) {
273 tcg_gen_discard_i32(dc->sar_m32);
274 }
275 dc->sar_5bit = true;
276 dc->sar_m32_5bit = false;
277}
278
279static void gen_left_shift_sar(DisasContext *dc, TCGv_i32 sa)
280{
281 TCGv_i32 tmp = tcg_const_i32(32);
282 if (!dc->sar_m32_allocated) {
283 dc->sar_m32 = tcg_temp_local_new_i32();
284 dc->sar_m32_allocated = true;
285 }
286 tcg_gen_andi_i32(dc->sar_m32, sa, 0x1f);
287 tcg_gen_sub_i32(cpu_SR[SAR], tmp, dc->sar_m32);
288 dc->sar_5bit = false;
289 dc->sar_m32_5bit = true;
290 tcg_temp_free(tmp);
291}
292
b994e91b
MF
293static void gen_advance_ccount(DisasContext *dc)
294{
295 if (dc->ccount_delta > 0) {
296 TCGv_i32 tmp = tcg_const_i32(dc->ccount_delta);
297 dc->ccount_delta = 0;
f492b82d 298 gen_helper_advance_ccount(cpu_env, tmp);
b994e91b
MF
299 tcg_temp_free(tmp);
300 }
301}
302
772177c1
MF
303static void reset_used_window(DisasContext *dc)
304{
305 dc->used_window = 0;
306}
307
b994e91b 308static void gen_exception(DisasContext *dc, int excp)
dedc5eae
MF
309{
310 TCGv_i32 tmp = tcg_const_i32(excp);
b994e91b 311 gen_advance_ccount(dc);
f492b82d 312 gen_helper_exception(cpu_env, tmp);
dedc5eae
MF
313 tcg_temp_free(tmp);
314}
315
40643d7c
MF
316static void gen_exception_cause(DisasContext *dc, uint32_t cause)
317{
318 TCGv_i32 tpc = tcg_const_i32(dc->pc);
319 TCGv_i32 tcause = tcg_const_i32(cause);
b994e91b 320 gen_advance_ccount(dc);
f492b82d 321 gen_helper_exception_cause(cpu_env, tpc, tcause);
40643d7c
MF
322 tcg_temp_free(tpc);
323 tcg_temp_free(tcause);
6b814719
MF
324 if (cause == ILLEGAL_INSTRUCTION_CAUSE ||
325 cause == SYSCALL_CAUSE) {
326 dc->is_jmp = DISAS_UPDATE;
327 }
40643d7c
MF
328}
329
5b4e481b
MF
330static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause,
331 TCGv_i32 vaddr)
332{
333 TCGv_i32 tpc = tcg_const_i32(dc->pc);
334 TCGv_i32 tcause = tcg_const_i32(cause);
b994e91b 335 gen_advance_ccount(dc);
f492b82d 336 gen_helper_exception_cause_vaddr(cpu_env, tpc, tcause, vaddr);
5b4e481b
MF
337 tcg_temp_free(tpc);
338 tcg_temp_free(tcause);
339}
340
e61dc8f7
MF
341static void gen_debug_exception(DisasContext *dc, uint32_t cause)
342{
343 TCGv_i32 tpc = tcg_const_i32(dc->pc);
344 TCGv_i32 tcause = tcg_const_i32(cause);
345 gen_advance_ccount(dc);
f492b82d 346 gen_helper_debug_exception(cpu_env, tpc, tcause);
e61dc8f7
MF
347 tcg_temp_free(tpc);
348 tcg_temp_free(tcause);
349 if (cause & (DEBUGCAUSE_IB | DEBUGCAUSE_BI | DEBUGCAUSE_BN)) {
350 dc->is_jmp = DISAS_UPDATE;
351 }
352}
353
40643d7c
MF
354static void gen_check_privilege(DisasContext *dc)
355{
356 if (dc->cring) {
357 gen_exception_cause(dc, PRIVILEGED_CAUSE);
6b814719 358 dc->is_jmp = DISAS_UPDATE;
40643d7c
MF
359 }
360}
361
ef04a846
MF
362static void gen_check_cpenable(DisasContext *dc, unsigned cp)
363{
364 if (option_enabled(dc, XTENSA_OPTION_COPROCESSOR) &&
365 !(dc->cpenable & (1 << cp))) {
366 gen_exception_cause(dc, COPROCESSOR0_DISABLED + cp);
367 dc->is_jmp = DISAS_UPDATE;
368 }
369}
370
dedc5eae
MF
371static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
372{
373 tcg_gen_mov_i32(cpu_pc, dest);
35b5c044
MF
374 gen_advance_ccount(dc);
375 if (dc->icount) {
376 tcg_gen_mov_i32(cpu_SR[ICOUNT], dc->next_icount);
377 }
dedc5eae 378 if (dc->singlestep_enabled) {
b994e91b 379 gen_exception(dc, EXCP_DEBUG);
dedc5eae
MF
380 } else {
381 if (slot >= 0) {
382 tcg_gen_goto_tb(slot);
383 tcg_gen_exit_tb((tcg_target_long)dc->tb + slot);
384 } else {
385 tcg_gen_exit_tb(0);
386 }
387 }
388 dc->is_jmp = DISAS_UPDATE;
389}
390
67882fd1
MF
391static void gen_jump(DisasContext *dc, TCGv dest)
392{
393 gen_jump_slot(dc, dest, -1);
394}
395
dedc5eae
MF
396static void gen_jumpi(DisasContext *dc, uint32_t dest, int slot)
397{
398 TCGv_i32 tmp = tcg_const_i32(dest);
399 if (((dc->pc ^ dest) & TARGET_PAGE_MASK) != 0) {
400 slot = -1;
401 }
402 gen_jump_slot(dc, tmp, slot);
403 tcg_temp_free(tmp);
404}
405
553e44f9
MF
406static void gen_callw_slot(DisasContext *dc, int callinc, TCGv_i32 dest,
407 int slot)
408{
409 TCGv_i32 tcallinc = tcg_const_i32(callinc);
410
411 tcg_gen_deposit_i32(cpu_SR[PS], cpu_SR[PS],
412 tcallinc, PS_CALLINC_SHIFT, PS_CALLINC_LEN);
413 tcg_temp_free(tcallinc);
414 tcg_gen_movi_i32(cpu_R[callinc << 2],
415 (callinc << 30) | (dc->next_pc & 0x3fffffff));
416 gen_jump_slot(dc, dest, slot);
417}
418
419static void gen_callw(DisasContext *dc, int callinc, TCGv_i32 dest)
420{
421 gen_callw_slot(dc, callinc, dest, -1);
422}
423
424static void gen_callwi(DisasContext *dc, int callinc, uint32_t dest, int slot)
425{
426 TCGv_i32 tmp = tcg_const_i32(dest);
427 if (((dc->pc ^ dest) & TARGET_PAGE_MASK) != 0) {
428 slot = -1;
429 }
430 gen_callw_slot(dc, callinc, tmp, slot);
431 tcg_temp_free(tmp);
432}
433
797d780b
MF
434static bool gen_check_loop_end(DisasContext *dc, int slot)
435{
436 if (option_enabled(dc, XTENSA_OPTION_LOOP) &&
437 !(dc->tb->flags & XTENSA_TBFLAG_EXCM) &&
438 dc->next_pc == dc->lend) {
439 int label = gen_new_label();
440
d865f307 441 gen_advance_ccount(dc);
797d780b
MF
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
452static 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
MF
459static void gen_brcond(DisasContext *dc, TCGCond cond,
460 TCGv_i32 t0, TCGv_i32 t1, uint32_t offset)
461{
462 int label = gen_new_label();
463
d865f307 464 gen_advance_ccount(dc);
bd57fb91 465 tcg_gen_brcond_i32(cond, t0, t1, label);
797d780b 466 gen_jumpi_check_loop_end(dc, 0);
bd57fb91
MF
467 gen_set_label(label);
468 gen_jumpi(dc, dc->pc + offset, 1);
469}
470
471static void gen_brcondi(DisasContext *dc, TCGCond cond,
472 TCGv_i32 t0, uint32_t t1, uint32_t offset)
473{
474 TCGv_i32 tmp = tcg_const_i32(t1);
475 gen_brcond(dc, cond, t0, tmp, offset);
476 tcg_temp_free(tmp);
477}
478
fe0bd475
MF
479static void gen_check_sr(DisasContext *dc, uint32_t sr)
480{
481 if (!xtensa_option_bits_enabled(dc->config, sregnames[sr].opt_bits)) {
482 if (sregnames[sr].name) {
483 qemu_log("SR %s is not configured\n", sregnames[sr].name);
484 } else {
485 qemu_log("SR %d is not implemented\n", sr);
486 }
487 gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
488 }
489}
490
b994e91b
MF
491static void gen_rsr_ccount(DisasContext *dc, TCGv_i32 d, uint32_t sr)
492{
493 gen_advance_ccount(dc);
494 tcg_gen_mov_i32(d, cpu_SR[sr]);
495}
496
b67ea0cd
MF
497static void gen_rsr_ptevaddr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
498{
499 tcg_gen_shri_i32(d, cpu_SR[EXCVADDR], 10);
500 tcg_gen_or_i32(d, d, cpu_SR[sr]);
501 tcg_gen_andi_i32(d, d, 0xfffffffc);
502}
503
b8132eff
MF
504static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
505{
506 static void (* const rsr_handler[256])(DisasContext *dc,
507 TCGv_i32 d, uint32_t sr) = {
b994e91b 508 [CCOUNT] = gen_rsr_ccount,
b67ea0cd 509 [PTEVADDR] = gen_rsr_ptevaddr,
b8132eff
MF
510 };
511
fe0bd475
MF
512 if (rsr_handler[sr]) {
513 rsr_handler[sr](dc, d, sr);
b8132eff 514 } else {
fe0bd475 515 tcg_gen_mov_i32(d, cpu_SR[sr]);
b8132eff
MF
516 }
517}
518
797d780b
MF
519static void gen_wsr_lbeg(DisasContext *dc, uint32_t sr, TCGv_i32 s)
520{
f492b82d 521 gen_helper_wsr_lbeg(cpu_env, s);
3d0be8a5 522 gen_jumpi_check_loop_end(dc, 0);
797d780b
MF
523}
524
525static void gen_wsr_lend(DisasContext *dc, uint32_t sr, TCGv_i32 s)
526{
f492b82d 527 gen_helper_wsr_lend(cpu_env, s);
3d0be8a5 528 gen_jumpi_check_loop_end(dc, 0);
797d780b
MF
529}
530
3580ecad
MF
531static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)
532{
533 tcg_gen_andi_i32(cpu_SR[sr], s, 0x3f);
534 if (dc->sar_m32_5bit) {
535 tcg_gen_discard_i32(dc->sar_m32);
536 }
537 dc->sar_5bit = false;
538 dc->sar_m32_5bit = false;
539}
540
4dd85b6b
MF
541static void gen_wsr_br(DisasContext *dc, uint32_t sr, TCGv_i32 s)
542{
543 tcg_gen_andi_i32(cpu_SR[sr], s, 0xffff);
544}
545
6ad6dbf7
MF
546static void gen_wsr_litbase(DisasContext *dc, uint32_t sr, TCGv_i32 s)
547{
548 tcg_gen_andi_i32(cpu_SR[sr], s, 0xfffff001);
549 /* This can change tb->flags, so exit tb */
550 gen_jumpi_check_loop_end(dc, -1);
551}
552
6825b6c3
MF
553static void gen_wsr_acchi(DisasContext *dc, uint32_t sr, TCGv_i32 s)
554{
555 tcg_gen_ext8s_i32(cpu_SR[sr], s);
556}
557
553e44f9
MF
558static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
559{
f492b82d 560 gen_helper_wsr_windowbase(cpu_env, v);
772177c1
MF
561 reset_used_window(dc);
562}
563
564static void gen_wsr_windowstart(DisasContext *dc, uint32_t sr, TCGv_i32 v)
565{
53a72dfd 566 tcg_gen_andi_i32(cpu_SR[sr], v, (1 << dc->config->nareg / 4) - 1);
772177c1 567 reset_used_window(dc);
553e44f9
MF
568}
569
b67ea0cd
MF
570static void gen_wsr_ptevaddr(DisasContext *dc, uint32_t sr, TCGv_i32 v)
571{
572 tcg_gen_andi_i32(cpu_SR[sr], v, 0xffc00000);
573}
574
575static void gen_wsr_rasid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
576{
f492b82d 577 gen_helper_wsr_rasid(cpu_env, v);
b67ea0cd
MF
578 /* This can change tb->flags, so exit tb */
579 gen_jumpi_check_loop_end(dc, -1);
580}
581
582static void gen_wsr_tlbcfg(DisasContext *dc, uint32_t sr, TCGv_i32 v)
583{
584 tcg_gen_andi_i32(cpu_SR[sr], v, 0x01130000);
585}
586
e61dc8f7
MF
587static void gen_wsr_ibreakenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
588{
f492b82d 589 gen_helper_wsr_ibreakenable(cpu_env, v);
e61dc8f7
MF
590 gen_jumpi_check_loop_end(dc, 0);
591}
592
fcc803d1
MF
593static void gen_wsr_atomctl(DisasContext *dc, uint32_t sr, TCGv_i32 v)
594{
595 tcg_gen_andi_i32(cpu_SR[sr], v, 0x3f);
596}
597
e61dc8f7
MF
598static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
599{
600 unsigned id = sr - IBREAKA;
601
602 if (id < dc->config->nibreak) {
603 TCGv_i32 tmp = tcg_const_i32(id);
f492b82d 604 gen_helper_wsr_ibreaka(cpu_env, tmp, v);
e61dc8f7
MF
605 tcg_temp_free(tmp);
606 gen_jumpi_check_loop_end(dc, 0);
607 }
608}
609
f14c4b5f
MF
610static void gen_wsr_dbreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
611{
612 unsigned id = sr - DBREAKA;
613
614 if (id < dc->config->ndbreak) {
615 TCGv_i32 tmp = tcg_const_i32(id);
f492b82d 616 gen_helper_wsr_dbreaka(cpu_env, tmp, v);
f14c4b5f
MF
617 tcg_temp_free(tmp);
618 }
619}
620
621static void gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v)
622{
623 unsigned id = sr - DBREAKC;
624
625 if (id < dc->config->ndbreak) {
626 TCGv_i32 tmp = tcg_const_i32(id);
f492b82d 627 gen_helper_wsr_dbreakc(cpu_env, tmp, v);
f14c4b5f
MF
628 tcg_temp_free(tmp);
629 }
630}
631
ef04a846
MF
632static void gen_wsr_cpenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
633{
634 tcg_gen_andi_i32(cpu_SR[sr], v, 0xff);
635 /* This can change tb->flags, so exit tb */
636 gen_jumpi_check_loop_end(dc, -1);
637}
638
b994e91b
MF
639static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v)
640{
641 tcg_gen_andi_i32(cpu_SR[sr], v,
642 dc->config->inttype_mask[INTTYPE_SOFTWARE]);
643 gen_helper_check_interrupts(cpu_env);
644 gen_jumpi_check_loop_end(dc, 0);
645}
646
647static void gen_wsr_intclear(DisasContext *dc, uint32_t sr, TCGv_i32 v)
648{
649 TCGv_i32 tmp = tcg_temp_new_i32();
650
651 tcg_gen_andi_i32(tmp, v,
652 dc->config->inttype_mask[INTTYPE_EDGE] |
653 dc->config->inttype_mask[INTTYPE_NMI] |
654 dc->config->inttype_mask[INTTYPE_SOFTWARE]);
655 tcg_gen_andc_i32(cpu_SR[INTSET], cpu_SR[INTSET], tmp);
656 tcg_temp_free(tmp);
657 gen_helper_check_interrupts(cpu_env);
658}
659
660static void gen_wsr_intenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
661{
662 tcg_gen_mov_i32(cpu_SR[sr], v);
663 gen_helper_check_interrupts(cpu_env);
664 gen_jumpi_check_loop_end(dc, 0);
665}
666
f0a548b9
MF
667static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
668{
669 uint32_t mask = PS_WOE | PS_CALLINC | PS_OWB |
670 PS_UM | PS_EXCM | PS_INTLEVEL;
671
672 if (option_enabled(dc, XTENSA_OPTION_MMU)) {
673 mask |= PS_RING;
674 }
675 tcg_gen_andi_i32(cpu_SR[sr], v, mask);
772177c1 676 reset_used_window(dc);
b994e91b
MF
677 gen_helper_check_interrupts(cpu_env);
678 /* This can change mmu index and tb->flags, so exit tb */
797d780b 679 gen_jumpi_check_loop_end(dc, -1);
f0a548b9
MF
680}
681
ab58c5b4
MF
682static void gen_wsr_debugcause(DisasContext *dc, uint32_t sr, TCGv_i32 v)
683{
684}
685
f3df4c04
MF
686static void gen_wsr_prid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
687{
688}
689
35b5c044
MF
690static void gen_wsr_icount(DisasContext *dc, uint32_t sr, TCGv_i32 v)
691{
692 if (dc->icount) {
693 tcg_gen_mov_i32(dc->next_icount, v);
694 } else {
695 tcg_gen_mov_i32(cpu_SR[sr], v);
696 }
697}
698
699static void gen_wsr_icountlevel(DisasContext *dc, uint32_t sr, TCGv_i32 v)
700{
701 tcg_gen_andi_i32(cpu_SR[sr], v, 0xf);
702 /* This can change tb->flags, so exit tb */
703 gen_jumpi_check_loop_end(dc, -1);
704}
705
b994e91b
MF
706static void gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v)
707{
708 uint32_t id = sr - CCOMPARE;
709 if (id < dc->config->nccompare) {
710 uint32_t int_bit = 1 << dc->config->timerint[id];
711 gen_advance_ccount(dc);
712 tcg_gen_mov_i32(cpu_SR[sr], v);
713 tcg_gen_andi_i32(cpu_SR[INTSET], cpu_SR[INTSET], ~int_bit);
714 gen_helper_check_interrupts(cpu_env);
715 }
716}
717
b8132eff
MF
718static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
719{
720 static void (* const wsr_handler[256])(DisasContext *dc,
721 uint32_t sr, TCGv_i32 v) = {
797d780b
MF
722 [LBEG] = gen_wsr_lbeg,
723 [LEND] = gen_wsr_lend,
3580ecad 724 [SAR] = gen_wsr_sar,
4dd85b6b 725 [BR] = gen_wsr_br,
6ad6dbf7 726 [LITBASE] = gen_wsr_litbase,
6825b6c3 727 [ACCHI] = gen_wsr_acchi,
553e44f9 728 [WINDOW_BASE] = gen_wsr_windowbase,
772177c1 729 [WINDOW_START] = gen_wsr_windowstart,
b67ea0cd
MF
730 [PTEVADDR] = gen_wsr_ptevaddr,
731 [RASID] = gen_wsr_rasid,
732 [ITLBCFG] = gen_wsr_tlbcfg,
733 [DTLBCFG] = gen_wsr_tlbcfg,
e61dc8f7 734 [IBREAKENABLE] = gen_wsr_ibreakenable,
fcc803d1 735 [ATOMCTL] = gen_wsr_atomctl,
e61dc8f7
MF
736 [IBREAKA] = gen_wsr_ibreaka,
737 [IBREAKA + 1] = gen_wsr_ibreaka,
f14c4b5f
MF
738 [DBREAKA] = gen_wsr_dbreaka,
739 [DBREAKA + 1] = gen_wsr_dbreaka,
740 [DBREAKC] = gen_wsr_dbreakc,
741 [DBREAKC + 1] = gen_wsr_dbreakc,
ef04a846 742 [CPENABLE] = gen_wsr_cpenable,
b994e91b
MF
743 [INTSET] = gen_wsr_intset,
744 [INTCLEAR] = gen_wsr_intclear,
745 [INTENABLE] = gen_wsr_intenable,
f0a548b9 746 [PS] = gen_wsr_ps,
ab58c5b4 747 [DEBUGCAUSE] = gen_wsr_debugcause,
f3df4c04 748 [PRID] = gen_wsr_prid,
35b5c044
MF
749 [ICOUNT] = gen_wsr_icount,
750 [ICOUNTLEVEL] = gen_wsr_icountlevel,
b994e91b
MF
751 [CCOMPARE] = gen_wsr_ccompare,
752 [CCOMPARE + 1] = gen_wsr_ccompare,
753 [CCOMPARE + 2] = gen_wsr_ccompare,
b8132eff
MF
754 };
755
fe0bd475
MF
756 if (wsr_handler[sr]) {
757 wsr_handler[sr](dc, sr, s);
b8132eff 758 } else {
fe0bd475 759 tcg_gen_mov_i32(cpu_SR[sr], s);
b8132eff
MF
760 }
761}
762
dd519cbe
MF
763static void gen_wur(uint32_t ur, TCGv_i32 s)
764{
765 switch (ur) {
766 case FCR:
767 gen_helper_wur_fcr(cpu_env, s);
768 break;
769
770 case FSR:
771 tcg_gen_andi_i32(cpu_UR[ur], s, 0xffffff80);
772 break;
773
774 default:
775 tcg_gen_mov_i32(cpu_UR[ur], s);
776 break;
777 }
778}
779
5b4e481b
MF
780static void gen_load_store_alignment(DisasContext *dc, int shift,
781 TCGv_i32 addr, bool no_hw_alignment)
782{
783 if (!option_enabled(dc, XTENSA_OPTION_UNALIGNED_EXCEPTION)) {
784 tcg_gen_andi_i32(addr, addr, ~0 << shift);
785 } else if (option_enabled(dc, XTENSA_OPTION_HW_ALIGNMENT) &&
786 no_hw_alignment) {
787 int label = gen_new_label();
788 TCGv_i32 tmp = tcg_temp_new_i32();
789 tcg_gen_andi_i32(tmp, addr, ~(~0 << shift));
790 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
791 gen_exception_cause_vaddr(dc, LOAD_STORE_ALIGNMENT_CAUSE, addr);
792 gen_set_label(label);
793 tcg_temp_free(tmp);
794 }
795}
796
b994e91b
MF
797static void gen_waiti(DisasContext *dc, uint32_t imm4)
798{
799 TCGv_i32 pc = tcg_const_i32(dc->next_pc);
800 TCGv_i32 intlevel = tcg_const_i32(imm4);
801 gen_advance_ccount(dc);
f492b82d 802 gen_helper_waiti(cpu_env, pc, intlevel);
b994e91b
MF
803 tcg_temp_free(pc);
804 tcg_temp_free(intlevel);
805}
806
772177c1
MF
807static void gen_window_check1(DisasContext *dc, unsigned r1)
808{
809 if (dc->tb->flags & XTENSA_TBFLAG_EXCM) {
810 return;
811 }
812 if (option_enabled(dc, XTENSA_OPTION_WINDOWED_REGISTER) &&
813 r1 / 4 > dc->used_window) {
814 TCGv_i32 pc = tcg_const_i32(dc->pc);
815 TCGv_i32 w = tcg_const_i32(r1 / 4);
816
817 dc->used_window = r1 / 4;
818 gen_advance_ccount(dc);
f492b82d 819 gen_helper_window_check(cpu_env, pc, w);
772177c1
MF
820
821 tcg_temp_free(w);
822 tcg_temp_free(pc);
823 }
824}
825
826static void gen_window_check2(DisasContext *dc, unsigned r1, unsigned r2)
827{
828 gen_window_check1(dc, r1 > r2 ? r1 : r2);
829}
830
831static void gen_window_check3(DisasContext *dc, unsigned r1, unsigned r2,
832 unsigned r3)
833{
834 gen_window_check2(dc, r1, r2 > r3 ? r2 : r3);
835}
836
6825b6c3
MF
837static TCGv_i32 gen_mac16_m(TCGv_i32 v, bool hi, bool is_unsigned)
838{
839 TCGv_i32 m = tcg_temp_new_i32();
840
841 if (hi) {
842 (is_unsigned ? tcg_gen_shri_i32 : tcg_gen_sari_i32)(m, v, 16);
843 } else {
844 (is_unsigned ? tcg_gen_ext16u_i32 : tcg_gen_ext16s_i32)(m, v);
845 }
846 return m;
847}
848
0c4fabea 849static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
dedc5eae 850{
b67ea0cd
MF
851#define HAS_OPTION_BITS(opt) do { \
852 if (!option_bits_enabled(dc, opt)) { \
853 qemu_log("Option is not enabled %s:%d\n", \
854 __FILE__, __LINE__); \
dedc5eae
MF
855 goto invalid_opcode; \
856 } \
857 } while (0)
858
b67ea0cd
MF
859#define HAS_OPTION(opt) HAS_OPTION_BITS(XTENSA_OPTION_BIT(opt))
860
91a5bb76
MF
861#define TBD() qemu_log("TBD(pc = %08x): %s:%d\n", dc->pc, __FILE__, __LINE__)
862#define RESERVED() do { \
863 qemu_log("RESERVED(pc = %08x, %02x%02x%02x): %s:%d\n", \
864 dc->pc, b0, b1, b2, __FILE__, __LINE__); \
865 goto invalid_opcode; \
866 } while (0)
867
868
dedc5eae
MF
869#ifdef TARGET_WORDS_BIGENDIAN
870#define OP0 (((b0) & 0xf0) >> 4)
871#define OP1 (((b2) & 0xf0) >> 4)
872#define OP2 ((b2) & 0xf)
873#define RRR_R ((b1) & 0xf)
874#define RRR_S (((b1) & 0xf0) >> 4)
875#define RRR_T ((b0) & 0xf)
876#else
877#define OP0 (((b0) & 0xf))
878#define OP1 (((b2) & 0xf))
879#define OP2 (((b2) & 0xf0) >> 4)
880#define RRR_R (((b1) & 0xf0) >> 4)
881#define RRR_S (((b1) & 0xf))
882#define RRR_T (((b0) & 0xf0) >> 4)
883#endif
6825b6c3
MF
884#define RRR_X ((RRR_R & 0x4) >> 2)
885#define RRR_Y ((RRR_T & 0x4) >> 2)
886#define RRR_W (RRR_R & 0x3)
dedc5eae
MF
887
888#define RRRN_R RRR_R
889#define RRRN_S RRR_S
890#define RRRN_T RRR_T
891
892#define RRI8_R RRR_R
893#define RRI8_S RRR_S
894#define RRI8_T RRR_T
895#define RRI8_IMM8 (b2)
896#define RRI8_IMM8_SE ((((b2) & 0x80) ? 0xffffff00 : 0) | RRI8_IMM8)
897
898#ifdef TARGET_WORDS_BIGENDIAN
899#define RI16_IMM16 (((b1) << 8) | (b2))
900#else
901#define RI16_IMM16 (((b2) << 8) | (b1))
902#endif
903
904#ifdef TARGET_WORDS_BIGENDIAN
905#define CALL_N (((b0) & 0xc) >> 2)
906#define CALL_OFFSET ((((b0) & 0x3) << 16) | ((b1) << 8) | (b2))
907#else
908#define CALL_N (((b0) & 0x30) >> 4)
909#define CALL_OFFSET ((((b0) & 0xc0) >> 6) | ((b1) << 2) | ((b2) << 10))
910#endif
911#define CALL_OFFSET_SE \
912 (((CALL_OFFSET & 0x20000) ? 0xfffc0000 : 0) | CALL_OFFSET)
913
914#define CALLX_N CALL_N
915#ifdef TARGET_WORDS_BIGENDIAN
916#define CALLX_M ((b0) & 0x3)
917#else
918#define CALLX_M (((b0) & 0xc0) >> 6)
919#endif
920#define CALLX_S RRR_S
921
922#define BRI12_M CALLX_M
923#define BRI12_S RRR_S
924#ifdef TARGET_WORDS_BIGENDIAN
925#define BRI12_IMM12 ((((b1) & 0xf) << 8) | (b2))
926#else
927#define BRI12_IMM12 ((((b1) & 0xf0) >> 4) | ((b2) << 4))
928#endif
929#define BRI12_IMM12_SE (((BRI12_IMM12 & 0x800) ? 0xfffff000 : 0) | BRI12_IMM12)
930
931#define BRI8_M BRI12_M
932#define BRI8_R RRI8_R
933#define BRI8_S RRI8_S
934#define BRI8_IMM8 RRI8_IMM8
935#define BRI8_IMM8_SE RRI8_IMM8_SE
936
937#define RSR_SR (b1)
938
0c4fabea
BS
939 uint8_t b0 = cpu_ldub_code(env, dc->pc);
940 uint8_t b1 = cpu_ldub_code(env, dc->pc + 1);
a044ec2a 941 uint8_t b2 = 0;
dedc5eae 942
bd57fb91
MF
943 static const uint32_t B4CONST[] = {
944 0xffffffff, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
945 };
946
947 static const uint32_t B4CONSTU[] = {
948 32768, 65536, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
949 };
950
dedc5eae
MF
951 if (OP0 >= 8) {
952 dc->next_pc = dc->pc + 2;
953 HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);
954 } else {
955 dc->next_pc = dc->pc + 3;
0c4fabea 956 b2 = cpu_ldub_code(env, dc->pc + 2);
dedc5eae
MF
957 }
958
959 switch (OP0) {
960 case 0: /*QRST*/
961 switch (OP1) {
962 case 0: /*RST0*/
963 switch (OP2) {
964 case 0: /*ST0*/
965 if ((RRR_R & 0xc) == 0x8) {
966 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
967 }
968
969 switch (RRR_R) {
970 case 0: /*SNM0*/
5da4a6a8
MF
971 switch (CALLX_M) {
972 case 0: /*ILL*/
40643d7c 973 gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
5da4a6a8
MF
974 break;
975
976 case 1: /*reserved*/
91a5bb76 977 RESERVED();
5da4a6a8
MF
978 break;
979
980 case 2: /*JR*/
981 switch (CALLX_N) {
982 case 0: /*RET*/
983 case 2: /*JX*/
772177c1 984 gen_window_check1(dc, CALLX_S);
5da4a6a8
MF
985 gen_jump(dc, cpu_R[CALLX_S]);
986 break;
987
988 case 1: /*RETWw*/
989 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
553e44f9
MF
990 {
991 TCGv_i32 tmp = tcg_const_i32(dc->pc);
b994e91b 992 gen_advance_ccount(dc);
f492b82d 993 gen_helper_retw(tmp, cpu_env, tmp);
553e44f9
MF
994 gen_jump(dc, tmp);
995 tcg_temp_free(tmp);
996 }
5da4a6a8
MF
997 break;
998
999 case 3: /*reserved*/
91a5bb76 1000 RESERVED();
5da4a6a8
MF
1001 break;
1002 }
1003 break;
1004
1005 case 3: /*CALLX*/
772177c1 1006 gen_window_check2(dc, CALLX_S, CALLX_N << 2);
5da4a6a8
MF
1007 switch (CALLX_N) {
1008 case 0: /*CALLX0*/
1009 {
1010 TCGv_i32 tmp = tcg_temp_new_i32();
1011 tcg_gen_mov_i32(tmp, cpu_R[CALLX_S]);
1012 tcg_gen_movi_i32(cpu_R[0], dc->next_pc);
1013 gen_jump(dc, tmp);
1014 tcg_temp_free(tmp);
1015 }
1016 break;
1017
1018 case 1: /*CALLX4w*/
1019 case 2: /*CALLX8w*/
1020 case 3: /*CALLX12w*/
1021 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
553e44f9
MF
1022 {
1023 TCGv_i32 tmp = tcg_temp_new_i32();
1024
1025 tcg_gen_mov_i32(tmp, cpu_R[CALLX_S]);
1026 gen_callw(dc, CALLX_N, tmp);
1027 tcg_temp_free(tmp);
1028 }
5da4a6a8
MF
1029 break;
1030 }
1031 break;
1032 }
dedc5eae
MF
1033 break;
1034
1035 case 1: /*MOVSPw*/
1036 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
772177c1 1037 gen_window_check2(dc, RRR_T, RRR_S);
553e44f9
MF
1038 {
1039 TCGv_i32 pc = tcg_const_i32(dc->pc);
b994e91b 1040 gen_advance_ccount(dc);
f492b82d 1041 gen_helper_movsp(cpu_env, pc);
553e44f9
MF
1042 tcg_gen_mov_i32(cpu_R[RRR_T], cpu_R[RRR_S]);
1043 tcg_temp_free(pc);
1044 }
dedc5eae
MF
1045 break;
1046
1047 case 2: /*SYNC*/
28067b22
MF
1048 switch (RRR_T) {
1049 case 0: /*ISYNC*/
1050 break;
1051
1052 case 1: /*RSYNC*/
1053 break;
1054
1055 case 2: /*ESYNC*/
1056 break;
1057
1058 case 3: /*DSYNC*/
1059 break;
1060
1061 case 8: /*EXCW*/
1062 HAS_OPTION(XTENSA_OPTION_EXCEPTION);
1063 break;
1064
1065 case 12: /*MEMW*/
1066 break;
1067
1068 case 13: /*EXTW*/
1069 break;
1070
1071 case 15: /*NOP*/
1072 break;
1073
1074 default: /*reserved*/
1075 RESERVED();
1076 break;
1077 }
91a5bb76
MF
1078 break;
1079
1080 case 3: /*RFEIx*/
40643d7c
MF
1081 switch (RRR_T) {
1082 case 0: /*RFETx*/
1083 HAS_OPTION(XTENSA_OPTION_EXCEPTION);
1084 switch (RRR_S) {
1085 case 0: /*RFEx*/
1086 gen_check_privilege(dc);
1087 tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM);
b994e91b 1088 gen_helper_check_interrupts(cpu_env);
40643d7c
MF
1089 gen_jump(dc, cpu_SR[EPC1]);
1090 break;
1091
1092 case 1: /*RFUEx*/
1093 RESERVED();
1094 break;
1095
1096 case 2: /*RFDEx*/
1097 gen_check_privilege(dc);
1098 gen_jump(dc, cpu_SR[
1099 dc->config->ndepc ? DEPC : EPC1]);
1100 break;
1101
1102 case 4: /*RFWOw*/
1103 case 5: /*RFWUw*/
1104 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
553e44f9
MF
1105 gen_check_privilege(dc);
1106 {
1107 TCGv_i32 tmp = tcg_const_i32(1);
1108
1109 tcg_gen_andi_i32(
1110 cpu_SR[PS], cpu_SR[PS], ~PS_EXCM);
1111 tcg_gen_shl_i32(tmp, tmp, cpu_SR[WINDOW_BASE]);
1112
1113 if (RRR_S == 4) {
1114 tcg_gen_andc_i32(cpu_SR[WINDOW_START],
1115 cpu_SR[WINDOW_START], tmp);
1116 } else {
1117 tcg_gen_or_i32(cpu_SR[WINDOW_START],
1118 cpu_SR[WINDOW_START], tmp);
1119 }
1120
f492b82d 1121 gen_helper_restore_owb(cpu_env);
b994e91b 1122 gen_helper_check_interrupts(cpu_env);
553e44f9
MF
1123 gen_jump(dc, cpu_SR[EPC1]);
1124
1125 tcg_temp_free(tmp);
1126 }
40643d7c
MF
1127 break;
1128
1129 default: /*reserved*/
1130 RESERVED();
1131 break;
1132 }
1133 break;
1134
1135 case 1: /*RFIx*/
1136 HAS_OPTION(XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT);
b994e91b
MF
1137 if (RRR_S >= 2 && RRR_S <= dc->config->nlevel) {
1138 gen_check_privilege(dc);
1139 tcg_gen_mov_i32(cpu_SR[PS],
1140 cpu_SR[EPS2 + RRR_S - 2]);
1141 gen_helper_check_interrupts(cpu_env);
1142 gen_jump(dc, cpu_SR[EPC1 + RRR_S - 1]);
1143 } else {
1144 qemu_log("RFI %d is illegal\n", RRR_S);
1145 gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
1146 }
40643d7c
MF
1147 break;
1148
1149 case 2: /*RFME*/
1150 TBD();
1151 break;
1152
1153 default: /*reserved*/
1154 RESERVED();
1155 break;
1156
1157 }
91a5bb76
MF
1158 break;
1159
1160 case 4: /*BREAKx*/
e61dc8f7
MF
1161 HAS_OPTION(XTENSA_OPTION_DEBUG);
1162 if (dc->debug) {
1163 gen_debug_exception(dc, DEBUGCAUSE_BI);
1164 }
91a5bb76
MF
1165 break;
1166
1167 case 5: /*SYSCALLx*/
1168 HAS_OPTION(XTENSA_OPTION_EXCEPTION);
40643d7c
MF
1169 switch (RRR_S) {
1170 case 0: /*SYSCALLx*/
1171 gen_exception_cause(dc, SYSCALL_CAUSE);
1172 break;
1173
1174 case 1: /*SIMCALL*/
1ddeaa5d
MF
1175 if (semihosting_enabled) {
1176 gen_check_privilege(dc);
1177 gen_helper_simcall(cpu_env);
1178 } else {
1179 qemu_log("SIMCALL but semihosting is disabled\n");
1180 gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
1181 }
40643d7c
MF
1182 break;
1183
1184 default:
1185 RESERVED();
1186 break;
1187 }
91a5bb76
MF
1188 break;
1189
1190 case 6: /*RSILx*/
1191 HAS_OPTION(XTENSA_OPTION_INTERRUPT);
40643d7c 1192 gen_check_privilege(dc);
772177c1 1193 gen_window_check1(dc, RRR_T);
40643d7c 1194 tcg_gen_mov_i32(cpu_R[RRR_T], cpu_SR[PS]);
b994e91b 1195 tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL);
40643d7c 1196 tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], RRR_S);
b994e91b
MF
1197 gen_helper_check_interrupts(cpu_env);
1198 gen_jumpi_check_loop_end(dc, 0);
91a5bb76
MF
1199 break;
1200
1201 case 7: /*WAITIx*/
1202 HAS_OPTION(XTENSA_OPTION_INTERRUPT);
b994e91b
MF
1203 gen_check_privilege(dc);
1204 gen_waiti(dc, RRR_S);
91a5bb76
MF
1205 break;
1206
1207 case 8: /*ANY4p*/
91a5bb76 1208 case 9: /*ALL4p*/
91a5bb76 1209 case 10: /*ANY8p*/
91a5bb76
MF
1210 case 11: /*ALL8p*/
1211 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
4dd85b6b
MF
1212 {
1213 const unsigned shift = (RRR_R & 2) ? 8 : 4;
1214 TCGv_i32 mask = tcg_const_i32(
1215 ((1 << shift) - 1) << RRR_S);
1216 TCGv_i32 tmp = tcg_temp_new_i32();
1217
1218 tcg_gen_and_i32(tmp, cpu_SR[BR], mask);
1219 if (RRR_R & 1) { /*ALL*/
1220 tcg_gen_addi_i32(tmp, tmp, 1 << RRR_S);
1221 } else { /*ANY*/
1222 tcg_gen_add_i32(tmp, tmp, mask);
1223 }
1224 tcg_gen_shri_i32(tmp, tmp, RRR_S + shift);
1225 tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR],
1226 tmp, RRR_T, 1);
1227 tcg_temp_free(mask);
1228 tcg_temp_free(tmp);
1229 }
91a5bb76
MF
1230 break;
1231
1232 default: /*reserved*/
1233 RESERVED();
dedc5eae
MF
1234 break;
1235
1236 }
1237 break;
1238
1239 case 1: /*AND*/
772177c1 1240 gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
dedc5eae
MF
1241 tcg_gen_and_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
1242 break;
1243
1244 case 2: /*OR*/
772177c1 1245 gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
dedc5eae
MF
1246 tcg_gen_or_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
1247 break;
1248
1249 case 3: /*XOR*/
772177c1 1250 gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
dedc5eae
MF
1251 tcg_gen_xor_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
1252 break;
1253
1254 case 4: /*ST1*/
3580ecad
MF
1255 switch (RRR_R) {
1256 case 0: /*SSR*/
772177c1 1257 gen_window_check1(dc, RRR_S);
3580ecad
MF
1258 gen_right_shift_sar(dc, cpu_R[RRR_S]);
1259 break;
1260
1261 case 1: /*SSL*/
772177c1 1262 gen_window_check1(dc, RRR_S);
3580ecad
MF
1263 gen_left_shift_sar(dc, cpu_R[RRR_S]);
1264 break;
1265
1266 case 2: /*SSA8L*/
772177c1 1267 gen_window_check1(dc, RRR_S);
3580ecad
MF
1268 {
1269 TCGv_i32 tmp = tcg_temp_new_i32();
1270 tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 3);
1271 gen_right_shift_sar(dc, tmp);
1272 tcg_temp_free(tmp);
1273 }
1274 break;
1275
1276 case 3: /*SSA8B*/
772177c1 1277 gen_window_check1(dc, RRR_S);
3580ecad
MF
1278 {
1279 TCGv_i32 tmp = tcg_temp_new_i32();
1280 tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 3);
1281 gen_left_shift_sar(dc, tmp);
1282 tcg_temp_free(tmp);
1283 }
1284 break;
1285
1286 case 4: /*SSAI*/
1287 {
1288 TCGv_i32 tmp = tcg_const_i32(
1289 RRR_S | ((RRR_T & 1) << 4));
1290 gen_right_shift_sar(dc, tmp);
1291 tcg_temp_free(tmp);
1292 }
1293 break;
1294
1295 case 6: /*RER*/
91a5bb76 1296 TBD();
3580ecad
MF
1297 break;
1298
1299 case 7: /*WER*/
91a5bb76 1300 TBD();
3580ecad
MF
1301 break;
1302
1303 case 8: /*ROTWw*/
1304 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
553e44f9
MF
1305 gen_check_privilege(dc);
1306 {
1307 TCGv_i32 tmp = tcg_const_i32(
1308 RRR_T | ((RRR_T & 8) ? 0xfffffff0 : 0));
f492b82d 1309 gen_helper_rotw(cpu_env, tmp);
553e44f9 1310 tcg_temp_free(tmp);
772177c1 1311 reset_used_window(dc);
553e44f9 1312 }
3580ecad
MF
1313 break;
1314
1315 case 14: /*NSAu*/
7f65f4b0 1316 HAS_OPTION(XTENSA_OPTION_MISC_OP_NSA);
772177c1 1317 gen_window_check2(dc, RRR_S, RRR_T);
3580ecad
MF
1318 gen_helper_nsa(cpu_R[RRR_T], cpu_R[RRR_S]);
1319 break;
1320
1321 case 15: /*NSAUu*/
7f65f4b0 1322 HAS_OPTION(XTENSA_OPTION_MISC_OP_NSA);
772177c1 1323 gen_window_check2(dc, RRR_S, RRR_T);
3580ecad
MF
1324 gen_helper_nsau(cpu_R[RRR_T], cpu_R[RRR_S]);
1325 break;
1326
1327 default: /*reserved*/
91a5bb76 1328 RESERVED();
3580ecad
MF
1329 break;
1330 }
dedc5eae
MF
1331 break;
1332
1333 case 5: /*TLB*/
b67ea0cd
MF
1334 HAS_OPTION_BITS(
1335 XTENSA_OPTION_BIT(XTENSA_OPTION_MMU) |
1336 XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) |
1337 XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION));
1338 gen_check_privilege(dc);
1339 gen_window_check2(dc, RRR_S, RRR_T);
1340 {
1341 TCGv_i32 dtlb = tcg_const_i32((RRR_R & 8) != 0);
1342
1343 switch (RRR_R & 7) {
1344 case 3: /*RITLB0*/ /*RDTLB0*/
f492b82d
MF
1345 gen_helper_rtlb0(cpu_R[RRR_T],
1346 cpu_env, cpu_R[RRR_S], dtlb);
b67ea0cd
MF
1347 break;
1348
1349 case 4: /*IITLB*/ /*IDTLB*/
f492b82d 1350 gen_helper_itlb(cpu_env, cpu_R[RRR_S], dtlb);
b67ea0cd
MF
1351 /* This could change memory mapping, so exit tb */
1352 gen_jumpi_check_loop_end(dc, -1);
1353 break;
1354
1355 case 5: /*PITLB*/ /*PDTLB*/
1356 tcg_gen_movi_i32(cpu_pc, dc->pc);
f492b82d
MF
1357 gen_helper_ptlb(cpu_R[RRR_T],
1358 cpu_env, cpu_R[RRR_S], dtlb);
b67ea0cd
MF
1359 break;
1360
1361 case 6: /*WITLB*/ /*WDTLB*/
f492b82d
MF
1362 gen_helper_wtlb(
1363 cpu_env, cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
b67ea0cd
MF
1364 /* This could change memory mapping, so exit tb */
1365 gen_jumpi_check_loop_end(dc, -1);
1366 break;
1367
1368 case 7: /*RITLB1*/ /*RDTLB1*/
f492b82d
MF
1369 gen_helper_rtlb1(cpu_R[RRR_T],
1370 cpu_env, cpu_R[RRR_S], dtlb);
b67ea0cd
MF
1371 break;
1372
1373 default:
1374 tcg_temp_free(dtlb);
1375 RESERVED();
1376 break;
1377 }
1378 tcg_temp_free(dtlb);
1379 }
dedc5eae
MF
1380 break;
1381
1382 case 6: /*RT0*/
772177c1 1383 gen_window_check2(dc, RRR_R, RRR_T);
f331fe5e
MF
1384 switch (RRR_S) {
1385 case 0: /*NEG*/
1386 tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
1387 break;
1388
1389 case 1: /*ABS*/
1390 {
1391 int label = gen_new_label();
1392 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
1393 tcg_gen_brcondi_i32(
1394 TCG_COND_GE, cpu_R[RRR_R], 0, label);
1395 tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
1396 gen_set_label(label);
1397 }
1398 break;
1399
1400 default: /*reserved*/
91a5bb76 1401 RESERVED();
f331fe5e
MF
1402 break;
1403 }
dedc5eae
MF
1404 break;
1405
1406 case 7: /*reserved*/
91a5bb76 1407 RESERVED();
dedc5eae
MF
1408 break;
1409
1410 case 8: /*ADD*/
772177c1 1411 gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
dedc5eae
MF
1412 tcg_gen_add_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
1413 break;
1414
1415 case 9: /*ADD**/
1416 case 10:
1417 case 11:
772177c1 1418 gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
dedc5eae
MF
1419 {
1420 TCGv_i32 tmp = tcg_temp_new_i32();
1421 tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 8);
1422 tcg_gen_add_i32(cpu_R[RRR_R], tmp, cpu_R[RRR_T]);
1423 tcg_temp_free(tmp);
1424 }
1425 break;
1426
1427 case 12: /*SUB*/
772177c1 1428 gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
dedc5eae
MF
1429 tcg_gen_sub_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
1430 break;
1431
1432 case 13: /*SUB**/
1433 case 14:
1434 case 15:
772177c1 1435 gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
dedc5eae
MF
1436 {
1437 TCGv_i32 tmp = tcg_temp_new_i32();
1438 tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 12);
1439 tcg_gen_sub_i32(cpu_R[RRR_R], tmp, cpu_R[RRR_T]);
1440 tcg_temp_free(tmp);
1441 }
1442 break;
1443 }
1444 break;
1445
1446 case 1: /*RST1*/
3580ecad
MF
1447 switch (OP2) {
1448 case 0: /*SLLI*/
1449 case 1:
772177c1 1450 gen_window_check2(dc, RRR_R, RRR_S);
3580ecad
MF
1451 tcg_gen_shli_i32(cpu_R[RRR_R], cpu_R[RRR_S],
1452 32 - (RRR_T | ((OP2 & 1) << 4)));
1453 break;
1454
1455 case 2: /*SRAI*/
1456 case 3:
772177c1 1457 gen_window_check2(dc, RRR_R, RRR_T);
3580ecad
MF
1458 tcg_gen_sari_i32(cpu_R[RRR_R], cpu_R[RRR_T],
1459 RRR_S | ((OP2 & 1) << 4));
1460 break;
1461
1462 case 4: /*SRLI*/
772177c1 1463 gen_window_check2(dc, RRR_R, RRR_T);
3580ecad
MF
1464 tcg_gen_shri_i32(cpu_R[RRR_R], cpu_R[RRR_T], RRR_S);
1465 break;
1466
1467 case 6: /*XSR*/
1468 {
1469 TCGv_i32 tmp = tcg_temp_new_i32();
fe0bd475 1470 gen_check_sr(dc, RSR_SR);
40643d7c
MF
1471 if (RSR_SR >= 64) {
1472 gen_check_privilege(dc);
1473 }
772177c1 1474 gen_window_check1(dc, RRR_T);
3580ecad
MF
1475 tcg_gen_mov_i32(tmp, cpu_R[RRR_T]);
1476 gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
1477 gen_wsr(dc, RSR_SR, tmp);
1478 tcg_temp_free(tmp);
1479 }
1480 break;
1481
1482 /*
1483 * Note: 64 bit ops are used here solely because SAR values
1484 * have range 0..63
1485 */
1486#define gen_shift_reg(cmd, reg) do { \
1487 TCGv_i64 tmp = tcg_temp_new_i64(); \
1488 tcg_gen_extu_i32_i64(tmp, reg); \
1489 tcg_gen_##cmd##_i64(v, v, tmp); \
1490 tcg_gen_trunc_i64_i32(cpu_R[RRR_R], v); \
1491 tcg_temp_free_i64(v); \
1492 tcg_temp_free_i64(tmp); \
1493 } while (0)
1494
1495#define gen_shift(cmd) gen_shift_reg(cmd, cpu_SR[SAR])
1496
1497 case 8: /*SRC*/
772177c1 1498 gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
3580ecad
MF
1499 {
1500 TCGv_i64 v = tcg_temp_new_i64();
1501 tcg_gen_concat_i32_i64(v, cpu_R[RRR_T], cpu_R[RRR_S]);
1502 gen_shift(shr);
1503 }
1504 break;
1505
1506 case 9: /*SRL*/
772177c1 1507 gen_window_check2(dc, RRR_R, RRR_T);
3580ecad
MF
1508 if (dc->sar_5bit) {
1509 tcg_gen_shr_i32(cpu_R[RRR_R], cpu_R[RRR_T], cpu_SR[SAR]);
1510 } else {
1511 TCGv_i64 v = tcg_temp_new_i64();
1512 tcg_gen_extu_i32_i64(v, cpu_R[RRR_T]);
1513 gen_shift(shr);
1514 }
1515 break;
1516
1517 case 10: /*SLL*/
772177c1 1518 gen_window_check2(dc, RRR_R, RRR_S);
3580ecad
MF
1519 if (dc->sar_m32_5bit) {
1520 tcg_gen_shl_i32(cpu_R[RRR_R], cpu_R[RRR_S], dc->sar_m32);
1521 } else {
1522 TCGv_i64 v = tcg_temp_new_i64();
1523 TCGv_i32 s = tcg_const_i32(32);
1524 tcg_gen_sub_i32(s, s, cpu_SR[SAR]);
1525 tcg_gen_andi_i32(s, s, 0x3f);
1526 tcg_gen_extu_i32_i64(v, cpu_R[RRR_S]);
1527 gen_shift_reg(shl, s);
1528 tcg_temp_free(s);
1529 }
1530 break;
1531
1532 case 11: /*SRA*/
772177c1 1533 gen_window_check2(dc, RRR_R, RRR_T);
3580ecad
MF
1534 if (dc->sar_5bit) {
1535 tcg_gen_sar_i32(cpu_R[RRR_R], cpu_R[RRR_T], cpu_SR[SAR]);
1536 } else {
1537 TCGv_i64 v = tcg_temp_new_i64();
1538 tcg_gen_ext_i32_i64(v, cpu_R[RRR_T]);
1539 gen_shift(sar);
1540 }
1541 break;
1542#undef gen_shift
1543#undef gen_shift_reg
1544
1545 case 12: /*MUL16U*/
1546 HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL);
772177c1 1547 gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
3580ecad
MF
1548 {
1549 TCGv_i32 v1 = tcg_temp_new_i32();
1550 TCGv_i32 v2 = tcg_temp_new_i32();
1551 tcg_gen_ext16u_i32(v1, cpu_R[RRR_S]);
1552 tcg_gen_ext16u_i32(v2, cpu_R[RRR_T]);
1553 tcg_gen_mul_i32(cpu_R[RRR_R], v1, v2);
1554 tcg_temp_free(v2);
1555 tcg_temp_free(v1);
1556 }
1557 break;
1558
1559 case 13: /*MUL16S*/
1560 HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL);
772177c1 1561 gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
3580ecad
MF
1562 {
1563 TCGv_i32 v1 = tcg_temp_new_i32();
1564 TCGv_i32 v2 = tcg_temp_new_i32();
1565 tcg_gen_ext16s_i32(v1, cpu_R[RRR_S]);
1566 tcg_gen_ext16s_i32(v2, cpu_R[RRR_T]);
1567 tcg_gen_mul_i32(cpu_R[RRR_R], v1, v2);
1568 tcg_temp_free(v2);
1569 tcg_temp_free(v1);
1570 }
1571 break;
1572
1573 default: /*reserved*/
91a5bb76 1574 RESERVED();
3580ecad
MF
1575 break;
1576 }
dedc5eae
MF
1577 break;
1578
1579 case 2: /*RST2*/
4dd85b6b
MF
1580 if (OP2 >= 8) {
1581 gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
1582 }
772177c1 1583
f76ebf55
MF
1584 if (OP2 >= 12) {
1585 HAS_OPTION(XTENSA_OPTION_32_BIT_IDIV);
1586 int label = gen_new_label();
1587 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[RRR_T], 0, label);
1588 gen_exception_cause(dc, INTEGER_DIVIDE_BY_ZERO_CAUSE);
1589 gen_set_label(label);
1590 }
1591
1592 switch (OP2) {
4dd85b6b
MF
1593#define BOOLEAN_LOGIC(fn, r, s, t) \
1594 do { \
1595 HAS_OPTION(XTENSA_OPTION_BOOLEAN); \
1596 TCGv_i32 tmp1 = tcg_temp_new_i32(); \
1597 TCGv_i32 tmp2 = tcg_temp_new_i32(); \
1598 \
1599 tcg_gen_shri_i32(tmp1, cpu_SR[BR], s); \
1600 tcg_gen_shri_i32(tmp2, cpu_SR[BR], t); \
1601 tcg_gen_##fn##_i32(tmp1, tmp1, tmp2); \
1602 tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR], tmp1, r, 1); \
1603 tcg_temp_free(tmp1); \
1604 tcg_temp_free(tmp2); \
1605 } while (0)
1606
1607 case 0: /*ANDBp*/
1608 BOOLEAN_LOGIC(and, RRR_R, RRR_S, RRR_T);
1609 break;
1610
1611 case 1: /*ANDBCp*/
1612 BOOLEAN_LOGIC(andc, RRR_R, RRR_S, RRR_T);
1613 break;
1614
1615 case 2: /*ORBp*/
1616 BOOLEAN_LOGIC(or, RRR_R, RRR_S, RRR_T);
1617 break;
1618
1619 case 3: /*ORBCp*/
1620 BOOLEAN_LOGIC(orc, RRR_R, RRR_S, RRR_T);
1621 break;
1622
1623 case 4: /*XORBp*/
1624 BOOLEAN_LOGIC(xor, RRR_R, RRR_S, RRR_T);
1625 break;
1626
1627#undef BOOLEAN_LOGIC
1628
f76ebf55
MF
1629 case 8: /*MULLi*/
1630 HAS_OPTION(XTENSA_OPTION_32_BIT_IMUL);
1631 tcg_gen_mul_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
1632 break;
1633
1634 case 10: /*MULUHi*/
1635 case 11: /*MULSHi*/
7f65f4b0 1636 HAS_OPTION(XTENSA_OPTION_32_BIT_IMUL_HIGH);
f76ebf55
MF
1637 {
1638 TCGv_i64 r = tcg_temp_new_i64();
1639 TCGv_i64 s = tcg_temp_new_i64();
1640 TCGv_i64 t = tcg_temp_new_i64();
1641
1642 if (OP2 == 10) {
1643 tcg_gen_extu_i32_i64(s, cpu_R[RRR_S]);
1644 tcg_gen_extu_i32_i64(t, cpu_R[RRR_T]);
1645 } else {
1646 tcg_gen_ext_i32_i64(s, cpu_R[RRR_S]);
1647 tcg_gen_ext_i32_i64(t, cpu_R[RRR_T]);
1648 }
1649 tcg_gen_mul_i64(r, s, t);
1650 tcg_gen_shri_i64(r, r, 32);
1651 tcg_gen_trunc_i64_i32(cpu_R[RRR_R], r);
1652
1653 tcg_temp_free_i64(r);
1654 tcg_temp_free_i64(s);
1655 tcg_temp_free_i64(t);
1656 }
1657 break;
1658
1659 case 12: /*QUOUi*/
1660 tcg_gen_divu_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
1661 break;
1662
1663 case 13: /*QUOSi*/
1664 case 15: /*REMSi*/
1665 {
1666 int label1 = gen_new_label();
1667 int label2 = gen_new_label();
1668
1669 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[RRR_S], 0x80000000,
1670 label1);
1671 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[RRR_T], 0xffffffff,
1672 label1);
1673 tcg_gen_movi_i32(cpu_R[RRR_R],
1674 OP2 == 13 ? 0x80000000 : 0);
1675 tcg_gen_br(label2);
1676 gen_set_label(label1);
1677 if (OP2 == 13) {
1678 tcg_gen_div_i32(cpu_R[RRR_R],
1679 cpu_R[RRR_S], cpu_R[RRR_T]);
1680 } else {
1681 tcg_gen_rem_i32(cpu_R[RRR_R],
1682 cpu_R[RRR_S], cpu_R[RRR_T]);
1683 }
1684 gen_set_label(label2);
1685 }
1686 break;
1687
1688 case 14: /*REMUi*/
1689 tcg_gen_remu_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
1690 break;
1691
1692 default: /*reserved*/
1693 RESERVED();
1694 break;
1695 }
dedc5eae
MF
1696 break;
1697
1698 case 3: /*RST3*/
b8132eff
MF
1699 switch (OP2) {
1700 case 0: /*RSR*/
fe0bd475 1701 gen_check_sr(dc, RSR_SR);
40643d7c
MF
1702 if (RSR_SR >= 64) {
1703 gen_check_privilege(dc);
1704 }
772177c1 1705 gen_window_check1(dc, RRR_T);
b8132eff
MF
1706 gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
1707 break;
1708
1709 case 1: /*WSR*/
fe0bd475 1710 gen_check_sr(dc, RSR_SR);
40643d7c
MF
1711 if (RSR_SR >= 64) {
1712 gen_check_privilege(dc);
1713 }
772177c1 1714 gen_window_check1(dc, RRR_T);
b8132eff
MF
1715 gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);
1716 break;
1717
1718 case 2: /*SEXTu*/
7f65f4b0 1719 HAS_OPTION(XTENSA_OPTION_MISC_OP_SEXT);
772177c1 1720 gen_window_check2(dc, RRR_R, RRR_S);
b8132eff
MF
1721 {
1722 int shift = 24 - RRR_T;
1723
1724 if (shift == 24) {
1725 tcg_gen_ext8s_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
1726 } else if (shift == 16) {
1727 tcg_gen_ext16s_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
1728 } else {
1729 TCGv_i32 tmp = tcg_temp_new_i32();
1730 tcg_gen_shli_i32(tmp, cpu_R[RRR_S], shift);
1731 tcg_gen_sari_i32(cpu_R[RRR_R], tmp, shift);
1732 tcg_temp_free(tmp);
1733 }
1734 }
1735 break;
1736
1737 case 3: /*CLAMPSu*/
7f65f4b0 1738 HAS_OPTION(XTENSA_OPTION_MISC_OP_CLAMPS);
772177c1 1739 gen_window_check2(dc, RRR_R, RRR_S);
b8132eff
MF
1740 {
1741 TCGv_i32 tmp1 = tcg_temp_new_i32();
1742 TCGv_i32 tmp2 = tcg_temp_new_i32();
1743 int label = gen_new_label();
1744
1745 tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 24 - RRR_T);
1746 tcg_gen_xor_i32(tmp2, tmp1, cpu_R[RRR_S]);
1747 tcg_gen_andi_i32(tmp2, tmp2, 0xffffffff << (RRR_T + 7));
1748 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
1749 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp2, 0, label);
1750
1751 tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 31);
1752 tcg_gen_xori_i32(cpu_R[RRR_R], tmp1,
1753 0xffffffff >> (25 - RRR_T));
1754
1755 gen_set_label(label);
1756
1757 tcg_temp_free(tmp1);
1758 tcg_temp_free(tmp2);
1759 }
1760 break;
1761
1762 case 4: /*MINu*/
1763 case 5: /*MAXu*/
1764 case 6: /*MINUu*/
1765 case 7: /*MAXUu*/
7f65f4b0 1766 HAS_OPTION(XTENSA_OPTION_MISC_OP_MINMAX);
772177c1 1767 gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
b8132eff
MF
1768 {
1769 static const TCGCond cond[] = {
1770 TCG_COND_LE,
1771 TCG_COND_GE,
1772 TCG_COND_LEU,
1773 TCG_COND_GEU
1774 };
1775 int label = gen_new_label();
1776
1777 if (RRR_R != RRR_T) {
1778 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
1779 tcg_gen_brcond_i32(cond[OP2 - 4],
1780 cpu_R[RRR_S], cpu_R[RRR_T], label);
1781 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
1782 } else {
1783 tcg_gen_brcond_i32(cond[OP2 - 4],
1784 cpu_R[RRR_T], cpu_R[RRR_S], label);
1785 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
1786 }
1787 gen_set_label(label);
1788 }
1789 break;
1790
1791 case 8: /*MOVEQZ*/
1792 case 9: /*MOVNEZ*/
1793 case 10: /*MOVLTZ*/
1794 case 11: /*MOVGEZ*/
772177c1 1795 gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
b8132eff
MF
1796 {
1797 static const TCGCond cond[] = {
1798 TCG_COND_NE,
1799 TCG_COND_EQ,
1800 TCG_COND_GE,
1801 TCG_COND_LT
1802 };
1803 int label = gen_new_label();
1804 tcg_gen_brcondi_i32(cond[OP2 - 8], cpu_R[RRR_T], 0, label);
1805 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
1806 gen_set_label(label);
1807 }
1808 break;
1809
1810 case 12: /*MOVFp*/
b8132eff
MF
1811 case 13: /*MOVTp*/
1812 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
4dd85b6b
MF
1813 gen_window_check2(dc, RRR_R, RRR_S);
1814 {
1815 int label = gen_new_label();
1816 TCGv_i32 tmp = tcg_temp_new_i32();
1817
1818 tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << RRR_T);
1819 tcg_gen_brcondi_i32(
1820 OP2 & 1 ? TCG_COND_EQ : TCG_COND_NE,
1821 tmp, 0, label);
1822 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
1823 gen_set_label(label);
1824 tcg_temp_free(tmp);
1825 }
b8132eff
MF
1826 break;
1827
1828 case 14: /*RUR*/
772177c1 1829 gen_window_check1(dc, RRR_R);
b8132eff
MF
1830 {
1831 int st = (RRR_S << 4) + RRR_T;
fe0bd475 1832 if (uregnames[st].name) {
b8132eff
MF
1833 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_UR[st]);
1834 } else {
1835 qemu_log("RUR %d not implemented, ", st);
91a5bb76 1836 TBD();
b8132eff
MF
1837 }
1838 }
1839 break;
1840
1841 case 15: /*WUR*/
772177c1 1842 gen_window_check1(dc, RRR_T);
fe0bd475 1843 if (uregnames[RSR_SR].name) {
dd519cbe
MF
1844 gen_wur(RSR_SR, cpu_R[RRR_T]);
1845 } else {
1846 qemu_log("WUR %d not implemented, ", RSR_SR);
1847 TBD();
b8132eff
MF
1848 }
1849 break;
1850
1851 }
dedc5eae
MF
1852 break;
1853
1854 case 4: /*EXTUI*/
1855 case 5:
772177c1 1856 gen_window_check2(dc, RRR_R, RRR_T);
3580ecad 1857 {
f9cb5045 1858 int shiftimm = RRR_S | ((OP1 & 1) << 4);
3580ecad
MF
1859 int maskimm = (1 << (OP2 + 1)) - 1;
1860
1861 TCGv_i32 tmp = tcg_temp_new_i32();
f783cb22
AJ
1862 tcg_gen_shri_i32(tmp, cpu_R[RRR_T], shiftimm);
1863 tcg_gen_andi_i32(cpu_R[RRR_R], tmp, maskimm);
3580ecad
MF
1864 tcg_temp_free(tmp);
1865 }
dedc5eae
MF
1866 break;
1867
1868 case 6: /*CUST0*/
91a5bb76 1869 RESERVED();
dedc5eae
MF
1870 break;
1871
1872 case 7: /*CUST1*/
91a5bb76 1873 RESERVED();
dedc5eae
MF
1874 break;
1875
1876 case 8: /*LSCXp*/
9ed7ae12
MF
1877 switch (OP2) {
1878 case 0: /*LSXf*/
1879 case 1: /*LSXUf*/
1880 case 4: /*SSXf*/
1881 case 5: /*SSXUf*/
1882 HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
1883 gen_window_check2(dc, RRR_S, RRR_T);
ef04a846 1884 gen_check_cpenable(dc, 0);
9ed7ae12
MF
1885 {
1886 TCGv_i32 addr = tcg_temp_new_i32();
1887 tcg_gen_add_i32(addr, cpu_R[RRR_S], cpu_R[RRR_T]);
1888 gen_load_store_alignment(dc, 2, addr, false);
1889 if (OP2 & 0x4) {
1890 tcg_gen_qemu_st32(cpu_FR[RRR_R], addr, dc->cring);
1891 } else {
1892 tcg_gen_qemu_ld32u(cpu_FR[RRR_R], addr, dc->cring);
1893 }
1894 if (OP2 & 0x1) {
1895 tcg_gen_mov_i32(cpu_R[RRR_S], addr);
1896 }
1897 tcg_temp_free(addr);
1898 }
1899 break;
1900
1901 default: /*reserved*/
1902 RESERVED();
1903 break;
1904 }
dedc5eae
MF
1905 break;
1906
1907 case 9: /*LSC4*/
772177c1 1908 gen_window_check2(dc, RRR_S, RRR_T);
553e44f9
MF
1909 switch (OP2) {
1910 case 0: /*L32E*/
1911 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
1912 gen_check_privilege(dc);
1913 {
1914 TCGv_i32 addr = tcg_temp_new_i32();
1915 tcg_gen_addi_i32(addr, cpu_R[RRR_S],
1916 (0xffffffc0 | (RRR_R << 2)));
1917 tcg_gen_qemu_ld32u(cpu_R[RRR_T], addr, dc->ring);
1918 tcg_temp_free(addr);
1919 }
1920 break;
1921
1922 case 4: /*S32E*/
1923 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
1924 gen_check_privilege(dc);
1925 {
1926 TCGv_i32 addr = tcg_temp_new_i32();
1927 tcg_gen_addi_i32(addr, cpu_R[RRR_S],
1928 (0xffffffc0 | (RRR_R << 2)));
1929 tcg_gen_qemu_st32(cpu_R[RRR_T], addr, dc->ring);
1930 tcg_temp_free(addr);
1931 }
1932 break;
1933
1934 default:
1935 RESERVED();
1936 break;
1937 }
dedc5eae
MF
1938 break;
1939
1940 case 10: /*FP0*/
1941 HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
0b6df838
MF
1942 switch (OP2) {
1943 case 0: /*ADD.Sf*/
ef04a846 1944 gen_check_cpenable(dc, 0);
0b6df838
MF
1945 gen_helper_add_s(cpu_FR[RRR_R], cpu_env,
1946 cpu_FR[RRR_S], cpu_FR[RRR_T]);
1947 break;
1948
1949 case 1: /*SUB.Sf*/
ef04a846 1950 gen_check_cpenable(dc, 0);
0b6df838
MF
1951 gen_helper_sub_s(cpu_FR[RRR_R], cpu_env,
1952 cpu_FR[RRR_S], cpu_FR[RRR_T]);
1953 break;
1954
1955 case 2: /*MUL.Sf*/
ef04a846 1956 gen_check_cpenable(dc, 0);
0b6df838
MF
1957 gen_helper_mul_s(cpu_FR[RRR_R], cpu_env,
1958 cpu_FR[RRR_S], cpu_FR[RRR_T]);
1959 break;
1960
1961 case 4: /*MADD.Sf*/
ef04a846 1962 gen_check_cpenable(dc, 0);
0b6df838
MF
1963 gen_helper_madd_s(cpu_FR[RRR_R], cpu_env,
1964 cpu_FR[RRR_R], cpu_FR[RRR_S], cpu_FR[RRR_T]);
1965 break;
1966
1967 case 5: /*MSUB.Sf*/
ef04a846 1968 gen_check_cpenable(dc, 0);
0b6df838
MF
1969 gen_helper_msub_s(cpu_FR[RRR_R], cpu_env,
1970 cpu_FR[RRR_R], cpu_FR[RRR_S], cpu_FR[RRR_T]);
1971 break;
1972
b7ee8c6a
MF
1973 case 8: /*ROUND.Sf*/
1974 case 9: /*TRUNC.Sf*/
1975 case 10: /*FLOOR.Sf*/
1976 case 11: /*CEIL.Sf*/
1977 case 14: /*UTRUNC.Sf*/
1978 gen_window_check1(dc, RRR_R);
ef04a846 1979 gen_check_cpenable(dc, 0);
b7ee8c6a
MF
1980 {
1981 static const unsigned rounding_mode_const[] = {
1982 float_round_nearest_even,
1983 float_round_to_zero,
1984 float_round_down,
1985 float_round_up,
1986 [6] = float_round_to_zero,
1987 };
1988 TCGv_i32 rounding_mode = tcg_const_i32(
1989 rounding_mode_const[OP2 & 7]);
1990 TCGv_i32 scale = tcg_const_i32(RRR_T);
1991
1992 if (OP2 == 14) {
1993 gen_helper_ftoui(cpu_R[RRR_R], cpu_FR[RRR_S],
1994 rounding_mode, scale);
1995 } else {
1996 gen_helper_ftoi(cpu_R[RRR_R], cpu_FR[RRR_S],
1997 rounding_mode, scale);
1998 }
1999
2000 tcg_temp_free(rounding_mode);
2001 tcg_temp_free(scale);
2002 }
2003 break;
2004
2005 case 12: /*FLOAT.Sf*/
2006 case 13: /*UFLOAT.Sf*/
2007 gen_window_check1(dc, RRR_S);
ef04a846 2008 gen_check_cpenable(dc, 0);
b7ee8c6a
MF
2009 {
2010 TCGv_i32 scale = tcg_const_i32(-RRR_T);
2011
2012 if (OP2 == 13) {
2013 gen_helper_uitof(cpu_FR[RRR_R], cpu_env,
2014 cpu_R[RRR_S], scale);
2015 } else {
2016 gen_helper_itof(cpu_FR[RRR_R], cpu_env,
2017 cpu_R[RRR_S], scale);
2018 }
2019 tcg_temp_free(scale);
2020 }
2021 break;
2022
0b6df838
MF
2023 case 15: /*FP1OP*/
2024 switch (RRR_T) {
2025 case 0: /*MOV.Sf*/
ef04a846 2026 gen_check_cpenable(dc, 0);
0b6df838
MF
2027 tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_FR[RRR_S]);
2028 break;
2029
2030 case 1: /*ABS.Sf*/
ef04a846 2031 gen_check_cpenable(dc, 0);
0b6df838
MF
2032 gen_helper_abs_s(cpu_FR[RRR_R], cpu_FR[RRR_S]);
2033 break;
2034
2035 case 4: /*RFRf*/
2036 gen_window_check1(dc, RRR_R);
ef04a846 2037 gen_check_cpenable(dc, 0);
0b6df838
MF
2038 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_FR[RRR_S]);
2039 break;
2040
2041 case 5: /*WFRf*/
2042 gen_window_check1(dc, RRR_S);
ef04a846 2043 gen_check_cpenable(dc, 0);
0b6df838
MF
2044 tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_R[RRR_S]);
2045 break;
2046
2047 case 6: /*NEG.Sf*/
ef04a846 2048 gen_check_cpenable(dc, 0);
0b6df838
MF
2049 gen_helper_neg_s(cpu_FR[RRR_R], cpu_FR[RRR_S]);
2050 break;
2051
2052 default: /*reserved*/
2053 RESERVED();
2054 break;
2055 }
2056 break;
2057
2058 default: /*reserved*/
2059 RESERVED();
2060 break;
2061 }
dedc5eae
MF
2062 break;
2063
2064 case 11: /*FP1*/
2065 HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
4e273869
MF
2066
2067#define gen_compare(rel, br, a, b) \
2068 do { \
2069 TCGv_i32 bit = tcg_const_i32(1 << br); \
2070 \
ef04a846 2071 gen_check_cpenable(dc, 0); \
4e273869
MF
2072 gen_helper_##rel(cpu_env, bit, cpu_FR[a], cpu_FR[b]); \
2073 tcg_temp_free(bit); \
2074 } while (0)
2075
2076 switch (OP2) {
2077 case 1: /*UN.Sf*/
2078 gen_compare(un_s, RRR_R, RRR_S, RRR_T);
2079 break;
2080
2081 case 2: /*OEQ.Sf*/
2082 gen_compare(oeq_s, RRR_R, RRR_S, RRR_T);
2083 break;
2084
2085 case 3: /*UEQ.Sf*/
2086 gen_compare(ueq_s, RRR_R, RRR_S, RRR_T);
2087 break;
2088
2089 case 4: /*OLT.Sf*/
2090 gen_compare(olt_s, RRR_R, RRR_S, RRR_T);
2091 break;
2092
2093 case 5: /*ULT.Sf*/
2094 gen_compare(ult_s, RRR_R, RRR_S, RRR_T);
2095 break;
2096
2097 case 6: /*OLE.Sf*/
2098 gen_compare(ole_s, RRR_R, RRR_S, RRR_T);
2099 break;
2100
2101 case 7: /*ULE.Sf*/
2102 gen_compare(ule_s, RRR_R, RRR_S, RRR_T);
2103 break;
2104
2105#undef gen_compare
2106
2107 case 8: /*MOVEQZ.Sf*/
2108 case 9: /*MOVNEZ.Sf*/
2109 case 10: /*MOVLTZ.Sf*/
2110 case 11: /*MOVGEZ.Sf*/
2111 gen_window_check1(dc, RRR_T);
ef04a846 2112 gen_check_cpenable(dc, 0);
4e273869
MF
2113 {
2114 static const TCGCond cond[] = {
2115 TCG_COND_NE,
2116 TCG_COND_EQ,
2117 TCG_COND_GE,
2118 TCG_COND_LT
2119 };
2120 int label = gen_new_label();
2121 tcg_gen_brcondi_i32(cond[OP2 - 8], cpu_R[RRR_T], 0, label);
2122 tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_FR[RRR_S]);
2123 gen_set_label(label);
2124 }
2125 break;
2126
2127 case 12: /*MOVF.Sf*/
2128 case 13: /*MOVT.Sf*/
2129 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
ef04a846 2130 gen_check_cpenable(dc, 0);
4e273869
MF
2131 {
2132 int label = gen_new_label();
2133 TCGv_i32 tmp = tcg_temp_new_i32();
2134
2135 tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << RRR_T);
2136 tcg_gen_brcondi_i32(
2137 OP2 & 1 ? TCG_COND_EQ : TCG_COND_NE,
2138 tmp, 0, label);
2139 tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_FR[RRR_S]);
2140 gen_set_label(label);
2141 tcg_temp_free(tmp);
2142 }
2143 break;
2144
2145 default: /*reserved*/
2146 RESERVED();
2147 break;
2148 }
dedc5eae
MF
2149 break;
2150
2151 default: /*reserved*/
91a5bb76 2152 RESERVED();
dedc5eae
MF
2153 break;
2154 }
2155 break;
2156
2157 case 1: /*L32R*/
772177c1 2158 gen_window_check1(dc, RRR_T);
dedc5eae
MF
2159 {
2160 TCGv_i32 tmp = tcg_const_i32(
6ad6dbf7
MF
2161 ((dc->tb->flags & XTENSA_TBFLAG_LITBASE) ?
2162 0 : ((dc->pc + 3) & ~3)) +
2163 (0xfffc0000 | (RI16_IMM16 << 2)));
dedc5eae 2164
6ad6dbf7
MF
2165 if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) {
2166 tcg_gen_add_i32(tmp, tmp, dc->litbase);
2167 }
f0a548b9 2168 tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, dc->cring);
dedc5eae
MF
2169 tcg_temp_free(tmp);
2170 }
2171 break;
2172
2173 case 2: /*LSAI*/
809377aa
MF
2174#define gen_load_store(type, shift) do { \
2175 TCGv_i32 addr = tcg_temp_new_i32(); \
772177c1 2176 gen_window_check2(dc, RRI8_S, RRI8_T); \
809377aa 2177 tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << shift); \
5b4e481b
MF
2178 if (shift) { \
2179 gen_load_store_alignment(dc, shift, addr, false); \
2180 } \
f0a548b9 2181 tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
809377aa
MF
2182 tcg_temp_free(addr); \
2183 } while (0)
2184
2185 switch (RRI8_R) {
2186 case 0: /*L8UI*/
2187 gen_load_store(ld8u, 0);
2188 break;
2189
2190 case 1: /*L16UI*/
2191 gen_load_store(ld16u, 1);
2192 break;
2193
2194 case 2: /*L32I*/
2195 gen_load_store(ld32u, 2);
2196 break;
2197
2198 case 4: /*S8I*/
2199 gen_load_store(st8, 0);
2200 break;
2201
2202 case 5: /*S16I*/
2203 gen_load_store(st16, 1);
2204 break;
2205
2206 case 6: /*S32I*/
2207 gen_load_store(st32, 2);
2208 break;
2209
2210 case 7: /*CACHEc*/
8ffc2d0d
MF
2211 if (RRI8_T < 8) {
2212 HAS_OPTION(XTENSA_OPTION_DCACHE);
2213 }
2214
2215 switch (RRI8_T) {
2216 case 0: /*DPFRc*/
2217 break;
2218
2219 case 1: /*DPFWc*/
2220 break;
2221
2222 case 2: /*DPFROc*/
2223 break;
2224
2225 case 3: /*DPFWOc*/
2226 break;
2227
2228 case 4: /*DHWBc*/
2229 break;
2230
2231 case 5: /*DHWBIc*/
2232 break;
2233
2234 case 6: /*DHIc*/
2235 break;
2236
2237 case 7: /*DIIc*/
2238 break;
2239
2240 case 8: /*DCEc*/
2241 switch (OP1) {
2242 case 0: /*DPFLl*/
2243 HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);
2244 break;
2245
2246 case 2: /*DHUl*/
2247 HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);
2248 break;
2249
2250 case 3: /*DIUl*/
2251 HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);
2252 break;
2253
2254 case 4: /*DIWBc*/
2255 HAS_OPTION(XTENSA_OPTION_DCACHE);
2256 break;
2257
2258 case 5: /*DIWBIc*/
2259 HAS_OPTION(XTENSA_OPTION_DCACHE);
2260 break;
2261
2262 default: /*reserved*/
2263 RESERVED();
2264 break;
2265
2266 }
2267 break;
2268
2269 case 12: /*IPFc*/
2270 HAS_OPTION(XTENSA_OPTION_ICACHE);
2271 break;
2272
2273 case 13: /*ICEc*/
2274 switch (OP1) {
2275 case 0: /*IPFLl*/
2276 HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);
2277 break;
2278
2279 case 2: /*IHUl*/
2280 HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);
2281 break;
2282
2283 case 3: /*IIUl*/
2284 HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);
2285 break;
2286
2287 default: /*reserved*/
2288 RESERVED();
2289 break;
2290 }
2291 break;
2292
2293 case 14: /*IHIc*/
2294 HAS_OPTION(XTENSA_OPTION_ICACHE);
2295 break;
2296
2297 case 15: /*IIIc*/
2298 HAS_OPTION(XTENSA_OPTION_ICACHE);
2299 break;
2300
2301 default: /*reserved*/
2302 RESERVED();
2303 break;
2304 }
809377aa
MF
2305 break;
2306
2307 case 9: /*L16SI*/
2308 gen_load_store(ld16s, 1);
2309 break;
5b4e481b 2310#undef gen_load_store
809377aa
MF
2311
2312 case 10: /*MOVI*/
772177c1 2313 gen_window_check1(dc, RRI8_T);
809377aa
MF
2314 tcg_gen_movi_i32(cpu_R[RRI8_T],
2315 RRI8_IMM8 | (RRI8_S << 8) |
2316 ((RRI8_S & 0x8) ? 0xfffff000 : 0));
2317 break;
2318
5b4e481b
MF
2319#define gen_load_store_no_hw_align(type) do { \
2320 TCGv_i32 addr = tcg_temp_local_new_i32(); \
772177c1 2321 gen_window_check2(dc, RRI8_S, RRI8_T); \
5b4e481b
MF
2322 tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2); \
2323 gen_load_store_alignment(dc, 2, addr, true); \
2324 tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
2325 tcg_temp_free(addr); \
2326 } while (0)
2327
809377aa
MF
2328 case 11: /*L32AIy*/
2329 HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
5b4e481b 2330 gen_load_store_no_hw_align(ld32u); /*TODO acquire?*/
809377aa
MF
2331 break;
2332
2333 case 12: /*ADDI*/
772177c1 2334 gen_window_check2(dc, RRI8_S, RRI8_T);
809377aa
MF
2335 tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE);
2336 break;
2337
2338 case 13: /*ADDMI*/
772177c1 2339 gen_window_check2(dc, RRI8_S, RRI8_T);
809377aa
MF
2340 tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE << 8);
2341 break;
2342
2343 case 14: /*S32C1Iy*/
7f65f4b0 2344 HAS_OPTION(XTENSA_OPTION_CONDITIONAL_STORE);
772177c1 2345 gen_window_check2(dc, RRI8_S, RRI8_T);
809377aa
MF
2346 {
2347 int label = gen_new_label();
2348 TCGv_i32 tmp = tcg_temp_local_new_i32();
2349 TCGv_i32 addr = tcg_temp_local_new_i32();
fcc803d1 2350 TCGv_i32 tpc;
809377aa
MF
2351
2352 tcg_gen_mov_i32(tmp, cpu_R[RRI8_T]);
2353 tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2);
5b4e481b 2354 gen_load_store_alignment(dc, 2, addr, true);
fcc803d1
MF
2355
2356 gen_advance_ccount(dc);
2357 tpc = tcg_const_i32(dc->pc);
2358 gen_helper_check_atomctl(cpu_env, tpc, addr);
f0a548b9 2359 tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, dc->cring);
809377aa
MF
2360 tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[RRI8_T],
2361 cpu_SR[SCOMPARE1], label);
2362
f0a548b9 2363 tcg_gen_qemu_st32(tmp, addr, dc->cring);
809377aa
MF
2364
2365 gen_set_label(label);
fcc803d1 2366 tcg_temp_free(tpc);
809377aa
MF
2367 tcg_temp_free(addr);
2368 tcg_temp_free(tmp);
2369 }
2370 break;
2371
2372 case 15: /*S32RIy*/
2373 HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
5b4e481b 2374 gen_load_store_no_hw_align(st32); /*TODO release?*/
809377aa 2375 break;
5b4e481b 2376#undef gen_load_store_no_hw_align
809377aa
MF
2377
2378 default: /*reserved*/
91a5bb76 2379 RESERVED();
809377aa
MF
2380 break;
2381 }
dedc5eae
MF
2382 break;
2383
2384 case 3: /*LSCIp*/
9ed7ae12
MF
2385 switch (RRI8_R) {
2386 case 0: /*LSIf*/
2387 case 4: /*SSIf*/
2388 case 8: /*LSIUf*/
2389 case 12: /*SSIUf*/
2390 HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
2391 gen_window_check1(dc, RRI8_S);
ef04a846 2392 gen_check_cpenable(dc, 0);
9ed7ae12
MF
2393 {
2394 TCGv_i32 addr = tcg_temp_new_i32();
2395 tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2);
2396 gen_load_store_alignment(dc, 2, addr, false);
2397 if (RRI8_R & 0x4) {
2398 tcg_gen_qemu_st32(cpu_FR[RRI8_T], addr, dc->cring);
2399 } else {
2400 tcg_gen_qemu_ld32u(cpu_FR[RRI8_T], addr, dc->cring);
2401 }
2402 if (RRI8_R & 0x8) {
2403 tcg_gen_mov_i32(cpu_R[RRI8_S], addr);
2404 }
2405 tcg_temp_free(addr);
2406 }
2407 break;
2408
2409 default: /*reserved*/
2410 RESERVED();
2411 break;
2412 }
dedc5eae
MF
2413 break;
2414
2415 case 4: /*MAC16d*/
2416 HAS_OPTION(XTENSA_OPTION_MAC16);
6825b6c3
MF
2417 {
2418 enum {
2419 MAC16_UMUL = 0x0,
2420 MAC16_MUL = 0x4,
2421 MAC16_MULA = 0x8,
2422 MAC16_MULS = 0xc,
2423 MAC16_NONE = 0xf,
2424 } op = OP1 & 0xc;
2425 bool is_m1_sr = (OP2 & 0x3) == 2;
2426 bool is_m2_sr = (OP2 & 0xc) == 0;
2427 uint32_t ld_offset = 0;
2428
2429 if (OP2 > 9) {
2430 RESERVED();
2431 }
2432
2433 switch (OP2 & 2) {
2434 case 0: /*MACI?/MACC?*/
2435 is_m1_sr = true;
2436 ld_offset = (OP2 & 1) ? -4 : 4;
2437
2438 if (OP2 >= 8) { /*MACI/MACC*/
2439 if (OP1 == 0) { /*LDINC/LDDEC*/
2440 op = MAC16_NONE;
2441 } else {
2442 RESERVED();
2443 }
2444 } else if (op != MAC16_MULA) { /*MULA.*.*.LDINC/LDDEC*/
2445 RESERVED();
2446 }
2447 break;
2448
2449 case 2: /*MACD?/MACA?*/
2450 if (op == MAC16_UMUL && OP2 != 7) { /*UMUL only in MACAA*/
2451 RESERVED();
2452 }
2453 break;
2454 }
2455
2456 if (op != MAC16_NONE) {
2457 if (!is_m1_sr) {
2458 gen_window_check1(dc, RRR_S);
2459 }
2460 if (!is_m2_sr) {
2461 gen_window_check1(dc, RRR_T);
2462 }
2463 }
2464
2465 {
2466 TCGv_i32 vaddr = tcg_temp_new_i32();
2467 TCGv_i32 mem32 = tcg_temp_new_i32();
2468
2469 if (ld_offset) {
2470 gen_window_check1(dc, RRR_S);
2471 tcg_gen_addi_i32(vaddr, cpu_R[RRR_S], ld_offset);
2472 gen_load_store_alignment(dc, 2, vaddr, false);
2473 tcg_gen_qemu_ld32u(mem32, vaddr, dc->cring);
2474 }
2475 if (op != MAC16_NONE) {
2476 TCGv_i32 m1 = gen_mac16_m(
2477 is_m1_sr ? cpu_SR[MR + RRR_X] : cpu_R[RRR_S],
2478 OP1 & 1, op == MAC16_UMUL);
2479 TCGv_i32 m2 = gen_mac16_m(
2480 is_m2_sr ? cpu_SR[MR + 2 + RRR_Y] : cpu_R[RRR_T],
2481 OP1 & 2, op == MAC16_UMUL);
2482
2483 if (op == MAC16_MUL || op == MAC16_UMUL) {
2484 tcg_gen_mul_i32(cpu_SR[ACCLO], m1, m2);
2485 if (op == MAC16_UMUL) {
2486 tcg_gen_movi_i32(cpu_SR[ACCHI], 0);
2487 } else {
2488 tcg_gen_sari_i32(cpu_SR[ACCHI], cpu_SR[ACCLO], 31);
2489 }
2490 } else {
2491 TCGv_i32 res = tcg_temp_new_i32();
2492 TCGv_i64 res64 = tcg_temp_new_i64();
2493 TCGv_i64 tmp = tcg_temp_new_i64();
2494
2495 tcg_gen_mul_i32(res, m1, m2);
2496 tcg_gen_ext_i32_i64(res64, res);
2497 tcg_gen_concat_i32_i64(tmp,
2498 cpu_SR[ACCLO], cpu_SR[ACCHI]);
2499 if (op == MAC16_MULA) {
2500 tcg_gen_add_i64(tmp, tmp, res64);
2501 } else {
2502 tcg_gen_sub_i64(tmp, tmp, res64);
2503 }
2504 tcg_gen_trunc_i64_i32(cpu_SR[ACCLO], tmp);
2505 tcg_gen_shri_i64(tmp, tmp, 32);
2506 tcg_gen_trunc_i64_i32(cpu_SR[ACCHI], tmp);
2507 tcg_gen_ext8s_i32(cpu_SR[ACCHI], cpu_SR[ACCHI]);
2508
2509 tcg_temp_free(res);
2510 tcg_temp_free_i64(res64);
2511 tcg_temp_free_i64(tmp);
2512 }
2513 tcg_temp_free(m1);
2514 tcg_temp_free(m2);
2515 }
2516 if (ld_offset) {
2517 tcg_gen_mov_i32(cpu_R[RRR_S], vaddr);
2518 tcg_gen_mov_i32(cpu_SR[MR + RRR_W], mem32);
2519 }
2520 tcg_temp_free(vaddr);
2521 tcg_temp_free(mem32);
2522 }
2523 }
dedc5eae
MF
2524 break;
2525
2526 case 5: /*CALLN*/
2527 switch (CALL_N) {
2528 case 0: /*CALL0*/
2529 tcg_gen_movi_i32(cpu_R[0], dc->next_pc);
2530 gen_jumpi(dc, (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4, 0);
2531 break;
2532
2533 case 1: /*CALL4w*/
2534 case 2: /*CALL8w*/
2535 case 3: /*CALL12w*/
2536 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
772177c1 2537 gen_window_check1(dc, CALL_N << 2);
553e44f9
MF
2538 gen_callwi(dc, CALL_N,
2539 (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4, 0);
dedc5eae
MF
2540 break;
2541 }
2542 break;
2543
2544 case 6: /*SI*/
2545 switch (CALL_N) {
2546 case 0: /*J*/
2547 gen_jumpi(dc, dc->pc + 4 + CALL_OFFSET_SE, 0);
2548 break;
2549
bd57fb91 2550 case 1: /*BZ*/
772177c1 2551 gen_window_check1(dc, BRI12_S);
bd57fb91
MF
2552 {
2553 static const TCGCond cond[] = {
2554 TCG_COND_EQ, /*BEQZ*/
2555 TCG_COND_NE, /*BNEZ*/
2556 TCG_COND_LT, /*BLTZ*/
2557 TCG_COND_GE, /*BGEZ*/
2558 };
2559
2560 gen_brcondi(dc, cond[BRI12_M & 3], cpu_R[BRI12_S], 0,
2561 4 + BRI12_IMM12_SE);
2562 }
2563 break;
2564
2565 case 2: /*BI0*/
772177c1 2566 gen_window_check1(dc, BRI8_S);
bd57fb91
MF
2567 {
2568 static const TCGCond cond[] = {
2569 TCG_COND_EQ, /*BEQI*/
2570 TCG_COND_NE, /*BNEI*/
2571 TCG_COND_LT, /*BLTI*/
2572 TCG_COND_GE, /*BGEI*/
2573 };
2574
2575 gen_brcondi(dc, cond[BRI8_M & 3],
2576 cpu_R[BRI8_S], B4CONST[BRI8_R], 4 + BRI8_IMM8_SE);
2577 }
2578 break;
2579
2580 case 3: /*BI1*/
2581 switch (BRI8_M) {
2582 case 0: /*ENTRYw*/
2583 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
553e44f9
MF
2584 {
2585 TCGv_i32 pc = tcg_const_i32(dc->pc);
2586 TCGv_i32 s = tcg_const_i32(BRI12_S);
2587 TCGv_i32 imm = tcg_const_i32(BRI12_IMM12);
b994e91b 2588 gen_advance_ccount(dc);
f492b82d 2589 gen_helper_entry(cpu_env, pc, s, imm);
553e44f9
MF
2590 tcg_temp_free(imm);
2591 tcg_temp_free(s);
2592 tcg_temp_free(pc);
772177c1 2593 reset_used_window(dc);
553e44f9 2594 }
bd57fb91
MF
2595 break;
2596
2597 case 1: /*B1*/
2598 switch (BRI8_R) {
2599 case 0: /*BFp*/
bd57fb91
MF
2600 case 1: /*BTp*/
2601 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
4dd85b6b
MF
2602 {
2603 TCGv_i32 tmp = tcg_temp_new_i32();
2604 tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << RRI8_S);
2605 gen_brcondi(dc,
2606 BRI8_R == 1 ? TCG_COND_NE : TCG_COND_EQ,
2607 tmp, 0, 4 + RRI8_IMM8_SE);
2608 tcg_temp_free(tmp);
2609 }
bd57fb91
MF
2610 break;
2611
2612 case 8: /*LOOP*/
bd57fb91 2613 case 9: /*LOOPNEZ*/
bd57fb91 2614 case 10: /*LOOPGTZ*/
797d780b 2615 HAS_OPTION(XTENSA_OPTION_LOOP);
772177c1 2616 gen_window_check1(dc, RRI8_S);
797d780b
MF
2617 {
2618 uint32_t lend = dc->pc + RRI8_IMM8 + 4;
2619 TCGv_i32 tmp = tcg_const_i32(lend);
2620
2621 tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_R[RRI8_S], 1);
2622 tcg_gen_movi_i32(cpu_SR[LBEG], dc->next_pc);
f492b82d 2623 gen_helper_wsr_lend(cpu_env, tmp);
797d780b
MF
2624 tcg_temp_free(tmp);
2625
2626 if (BRI8_R > 8) {
2627 int label = gen_new_label();
2628 tcg_gen_brcondi_i32(
2629 BRI8_R == 9 ? TCG_COND_NE : TCG_COND_GT,
2630 cpu_R[RRI8_S], 0, label);
2631 gen_jumpi(dc, lend, 1);
2632 gen_set_label(label);
2633 }
2634
2635 gen_jumpi(dc, dc->next_pc, 0);
2636 }
bd57fb91
MF
2637 break;
2638
2639 default: /*reserved*/
91a5bb76 2640 RESERVED();
bd57fb91
MF
2641 break;
2642
2643 }
2644 break;
2645
2646 case 2: /*BLTUI*/
2647 case 3: /*BGEUI*/
772177c1 2648 gen_window_check1(dc, BRI8_S);
bd57fb91
MF
2649 gen_brcondi(dc, BRI8_M == 2 ? TCG_COND_LTU : TCG_COND_GEU,
2650 cpu_R[BRI8_S], B4CONSTU[BRI8_R], 4 + BRI8_IMM8_SE);
2651 break;
2652 }
2653 break;
2654
dedc5eae
MF
2655 }
2656 break;
2657
2658 case 7: /*B*/
bd57fb91
MF
2659 {
2660 TCGCond eq_ne = (RRI8_R & 8) ? TCG_COND_NE : TCG_COND_EQ;
2661
2662 switch (RRI8_R & 7) {
2663 case 0: /*BNONE*/ /*BANY*/
772177c1 2664 gen_window_check2(dc, RRI8_S, RRI8_T);
bd57fb91
MF
2665 {
2666 TCGv_i32 tmp = tcg_temp_new_i32();
2667 tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);
2668 gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);
2669 tcg_temp_free(tmp);
2670 }
2671 break;
2672
2673 case 1: /*BEQ*/ /*BNE*/
2674 case 2: /*BLT*/ /*BGE*/
2675 case 3: /*BLTU*/ /*BGEU*/
772177c1 2676 gen_window_check2(dc, RRI8_S, RRI8_T);
bd57fb91
MF
2677 {
2678 static const TCGCond cond[] = {
2679 [1] = TCG_COND_EQ,
2680 [2] = TCG_COND_LT,
2681 [3] = TCG_COND_LTU,
2682 [9] = TCG_COND_NE,
2683 [10] = TCG_COND_GE,
2684 [11] = TCG_COND_GEU,
2685 };
2686 gen_brcond(dc, cond[RRI8_R], cpu_R[RRI8_S], cpu_R[RRI8_T],
2687 4 + RRI8_IMM8_SE);
2688 }
2689 break;
2690
2691 case 4: /*BALL*/ /*BNALL*/
772177c1 2692 gen_window_check2(dc, RRI8_S, RRI8_T);
bd57fb91
MF
2693 {
2694 TCGv_i32 tmp = tcg_temp_new_i32();
2695 tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);
2696 gen_brcond(dc, eq_ne, tmp, cpu_R[RRI8_T],
2697 4 + RRI8_IMM8_SE);
2698 tcg_temp_free(tmp);
2699 }
2700 break;
2701
2702 case 5: /*BBC*/ /*BBS*/
772177c1 2703 gen_window_check2(dc, RRI8_S, RRI8_T);
bd57fb91 2704 {
7ff7563f
MF
2705#ifdef TARGET_WORDS_BIGENDIAN
2706 TCGv_i32 bit = tcg_const_i32(0x80000000);
2707#else
2708 TCGv_i32 bit = tcg_const_i32(0x00000001);
2709#endif
bd57fb91
MF
2710 TCGv_i32 tmp = tcg_temp_new_i32();
2711 tcg_gen_andi_i32(tmp, cpu_R[RRI8_T], 0x1f);
7ff7563f
MF
2712#ifdef TARGET_WORDS_BIGENDIAN
2713 tcg_gen_shr_i32(bit, bit, tmp);
2714#else
bd57fb91 2715 tcg_gen_shl_i32(bit, bit, tmp);
7ff7563f 2716#endif
bd57fb91
MF
2717 tcg_gen_and_i32(tmp, cpu_R[RRI8_S], bit);
2718 gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);
2719 tcg_temp_free(tmp);
2720 tcg_temp_free(bit);
2721 }
2722 break;
2723
2724 case 6: /*BBCI*/ /*BBSI*/
2725 case 7:
772177c1 2726 gen_window_check1(dc, RRI8_S);
bd57fb91
MF
2727 {
2728 TCGv_i32 tmp = tcg_temp_new_i32();
2729 tcg_gen_andi_i32(tmp, cpu_R[RRI8_S],
7ff7563f
MF
2730#ifdef TARGET_WORDS_BIGENDIAN
2731 0x80000000 >> (((RRI8_R & 1) << 4) | RRI8_T));
2732#else
2733 0x00000001 << (((RRI8_R & 1) << 4) | RRI8_T));
2734#endif
bd57fb91
MF
2735 gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);
2736 tcg_temp_free(tmp);
2737 }
2738 break;
2739
2740 }
2741 }
dedc5eae
MF
2742 break;
2743
67882fd1
MF
2744#define gen_narrow_load_store(type) do { \
2745 TCGv_i32 addr = tcg_temp_new_i32(); \
772177c1 2746 gen_window_check2(dc, RRRN_S, RRRN_T); \
67882fd1 2747 tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \
5b4e481b 2748 gen_load_store_alignment(dc, 2, addr, false); \
f0a548b9 2749 tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, dc->cring); \
67882fd1
MF
2750 tcg_temp_free(addr); \
2751 } while (0)
2752
dedc5eae 2753 case 8: /*L32I.Nn*/
67882fd1 2754 gen_narrow_load_store(ld32u);
dedc5eae
MF
2755 break;
2756
2757 case 9: /*S32I.Nn*/
67882fd1 2758 gen_narrow_load_store(st32);
dedc5eae 2759 break;
67882fd1 2760#undef gen_narrow_load_store
dedc5eae
MF
2761
2762 case 10: /*ADD.Nn*/
772177c1 2763 gen_window_check3(dc, RRRN_R, RRRN_S, RRRN_T);
67882fd1 2764 tcg_gen_add_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], cpu_R[RRRN_T]);
dedc5eae
MF
2765 break;
2766
2767 case 11: /*ADDI.Nn*/
772177c1 2768 gen_window_check2(dc, RRRN_R, RRRN_S);
67882fd1 2769 tcg_gen_addi_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], RRRN_T ? RRRN_T : -1);
dedc5eae
MF
2770 break;
2771
2772 case 12: /*ST2n*/
772177c1 2773 gen_window_check1(dc, RRRN_S);
67882fd1
MF
2774 if (RRRN_T < 8) { /*MOVI.Nn*/
2775 tcg_gen_movi_i32(cpu_R[RRRN_S],
2776 RRRN_R | (RRRN_T << 4) |
2777 ((RRRN_T & 6) == 6 ? 0xffffff80 : 0));
2778 } else { /*BEQZ.Nn*/ /*BNEZ.Nn*/
bd57fb91
MF
2779 TCGCond eq_ne = (RRRN_T & 4) ? TCG_COND_NE : TCG_COND_EQ;
2780
2781 gen_brcondi(dc, eq_ne, cpu_R[RRRN_S], 0,
2782 4 + (RRRN_R | ((RRRN_T & 3) << 4)));
67882fd1 2783 }
dedc5eae
MF
2784 break;
2785
2786 case 13: /*ST3n*/
67882fd1
MF
2787 switch (RRRN_R) {
2788 case 0: /*MOV.Nn*/
772177c1 2789 gen_window_check2(dc, RRRN_S, RRRN_T);
67882fd1
MF
2790 tcg_gen_mov_i32(cpu_R[RRRN_T], cpu_R[RRRN_S]);
2791 break;
2792
2793 case 15: /*S3*/
2794 switch (RRRN_T) {
2795 case 0: /*RET.Nn*/
2796 gen_jump(dc, cpu_R[0]);
2797 break;
2798
2799 case 1: /*RETW.Nn*/
91a5bb76 2800 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
553e44f9
MF
2801 {
2802 TCGv_i32 tmp = tcg_const_i32(dc->pc);
b994e91b 2803 gen_advance_ccount(dc);
f492b82d 2804 gen_helper_retw(tmp, cpu_env, tmp);
553e44f9
MF
2805 gen_jump(dc, tmp);
2806 tcg_temp_free(tmp);
2807 }
67882fd1
MF
2808 break;
2809
2810 case 2: /*BREAK.Nn*/
e61dc8f7
MF
2811 HAS_OPTION(XTENSA_OPTION_DEBUG);
2812 if (dc->debug) {
2813 gen_debug_exception(dc, DEBUGCAUSE_BN);
2814 }
67882fd1
MF
2815 break;
2816
2817 case 3: /*NOP.Nn*/
2818 break;
2819
2820 case 6: /*ILL.Nn*/
40643d7c 2821 gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
67882fd1
MF
2822 break;
2823
2824 default: /*reserved*/
91a5bb76 2825 RESERVED();
67882fd1
MF
2826 break;
2827 }
2828 break;
2829
2830 default: /*reserved*/
91a5bb76 2831 RESERVED();
67882fd1
MF
2832 break;
2833 }
dedc5eae
MF
2834 break;
2835
2836 default: /*reserved*/
91a5bb76 2837 RESERVED();
dedc5eae
MF
2838 break;
2839 }
2840
c26032b2
MF
2841 if (dc->is_jmp == DISAS_NEXT) {
2842 gen_check_loop_end(dc, 0);
2843 }
dedc5eae 2844 dc->pc = dc->next_pc;
797d780b 2845
dedc5eae
MF
2846 return;
2847
2848invalid_opcode:
2849 qemu_log("INVALID(pc = %08x)\n", dc->pc);
6b814719 2850 gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
dedc5eae
MF
2851#undef HAS_OPTION
2852}
2853
97129ac8 2854static void check_breakpoint(CPUXtensaState *env, DisasContext *dc)
dedc5eae
MF
2855{
2856 CPUBreakpoint *bp;
2857
2858 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
2859 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
2860 if (bp->pc == dc->pc) {
2861 tcg_gen_movi_i32(cpu_pc, dc->pc);
b994e91b 2862 gen_exception(dc, EXCP_DEBUG);
dedc5eae
MF
2863 dc->is_jmp = DISAS_UPDATE;
2864 }
2865 }
2866 }
2867}
2868
97129ac8 2869static void gen_ibreak_check(CPUXtensaState *env, DisasContext *dc)
e61dc8f7
MF
2870{
2871 unsigned i;
2872
2873 for (i = 0; i < dc->config->nibreak; ++i) {
2874 if ((env->sregs[IBREAKENABLE] & (1 << i)) &&
2875 env->sregs[IBREAKA + i] == dc->pc) {
2876 gen_debug_exception(dc, DEBUGCAUSE_IB);
2877 break;
2878 }
2879 }
2880}
2881
dedc5eae 2882static void gen_intermediate_code_internal(
97129ac8 2883 CPUXtensaState *env, TranslationBlock *tb, int search_pc)
dedc5eae
MF
2884{
2885 DisasContext dc;
2886 int insn_count = 0;
2887 int j, lj = -1;
92414b31 2888 uint16_t *gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
dedc5eae
MF
2889 int max_insns = tb->cflags & CF_COUNT_MASK;
2890 uint32_t pc_start = tb->pc;
2891 uint32_t next_page_start =
2892 (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
2893
2894 if (max_insns == 0) {
2895 max_insns = CF_COUNT_MASK;
2896 }
2897
2898 dc.config = env->config;
2899 dc.singlestep_enabled = env->singlestep_enabled;
2900 dc.tb = tb;
2901 dc.pc = pc_start;
f0a548b9
MF
2902 dc.ring = tb->flags & XTENSA_TBFLAG_RING_MASK;
2903 dc.cring = (tb->flags & XTENSA_TBFLAG_EXCM) ? 0 : dc.ring;
797d780b
MF
2904 dc.lbeg = env->sregs[LBEG];
2905 dc.lend = env->sregs[LEND];
dedc5eae 2906 dc.is_jmp = DISAS_NEXT;
b994e91b 2907 dc.ccount_delta = 0;
e61dc8f7 2908 dc.debug = tb->flags & XTENSA_TBFLAG_DEBUG;
35b5c044 2909 dc.icount = tb->flags & XTENSA_TBFLAG_ICOUNT;
ef04a846
MF
2910 dc.cpenable = (tb->flags & XTENSA_TBFLAG_CPENABLE_MASK) >>
2911 XTENSA_TBFLAG_CPENABLE_SHIFT;
dedc5eae 2912
6ad6dbf7 2913 init_litbase(&dc);
3580ecad 2914 init_sar_tracker(&dc);
772177c1 2915 reset_used_window(&dc);
35b5c044
MF
2916 if (dc.icount) {
2917 dc.next_icount = tcg_temp_local_new_i32();
2918 }
3580ecad 2919
dedc5eae
MF
2920 gen_icount_start();
2921
40643d7c
MF
2922 if (env->singlestep_enabled && env->exception_taken) {
2923 env->exception_taken = 0;
2924 tcg_gen_movi_i32(cpu_pc, dc.pc);
b994e91b 2925 gen_exception(&dc, EXCP_DEBUG);
40643d7c
MF
2926 }
2927
dedc5eae
MF
2928 do {
2929 check_breakpoint(env, &dc);
2930
2931 if (search_pc) {
92414b31 2932 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
dedc5eae
MF
2933 if (lj < j) {
2934 lj++;
2935 while (lj < j) {
ab1103de 2936 tcg_ctx.gen_opc_instr_start[lj++] = 0;
dedc5eae
MF
2937 }
2938 }
25983cad 2939 tcg_ctx.gen_opc_pc[lj] = dc.pc;
ab1103de 2940 tcg_ctx.gen_opc_instr_start[lj] = 1;
c9c99c22 2941 tcg_ctx.gen_opc_icount[lj] = insn_count;
dedc5eae
MF
2942 }
2943
fdefe51c 2944 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
dedc5eae
MF
2945 tcg_gen_debug_insn_start(dc.pc);
2946 }
2947
b994e91b
MF
2948 ++dc.ccount_delta;
2949
2950 if (insn_count + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
2951 gen_io_start();
2952 }
2953
35b5c044
MF
2954 if (dc.icount) {
2955 int label = gen_new_label();
2956
2957 tcg_gen_addi_i32(dc.next_icount, cpu_SR[ICOUNT], 1);
2958 tcg_gen_brcondi_i32(TCG_COND_NE, dc.next_icount, 0, label);
2959 tcg_gen_mov_i32(dc.next_icount, cpu_SR[ICOUNT]);
2960 if (dc.debug) {
2961 gen_debug_exception(&dc, DEBUGCAUSE_IC);
2962 }
2963 gen_set_label(label);
2964 }
2965
e61dc8f7
MF
2966 if (dc.debug) {
2967 gen_ibreak_check(env, &dc);
2968 }
2969
0c4fabea 2970 disas_xtensa_insn(env, &dc);
dedc5eae 2971 ++insn_count;
35b5c044
MF
2972 if (dc.icount) {
2973 tcg_gen_mov_i32(cpu_SR[ICOUNT], dc.next_icount);
2974 }
dedc5eae
MF
2975 if (env->singlestep_enabled) {
2976 tcg_gen_movi_i32(cpu_pc, dc.pc);
b994e91b 2977 gen_exception(&dc, EXCP_DEBUG);
dedc5eae
MF
2978 break;
2979 }
2980 } while (dc.is_jmp == DISAS_NEXT &&
2981 insn_count < max_insns &&
2982 dc.pc < next_page_start &&
efd7f486 2983 tcg_ctx.gen_opc_ptr < gen_opc_end);
dedc5eae 2984
6ad6dbf7 2985 reset_litbase(&dc);
3580ecad 2986 reset_sar_tracker(&dc);
35b5c044
MF
2987 if (dc.icount) {
2988 tcg_temp_free(dc.next_icount);
2989 }
3580ecad 2990
b994e91b
MF
2991 if (tb->cflags & CF_LAST_IO) {
2992 gen_io_end();
2993 }
2994
dedc5eae
MF
2995 if (dc.is_jmp == DISAS_NEXT) {
2996 gen_jumpi(&dc, dc.pc, 0);
2997 }
2998 gen_icount_end(tb, insn_count);
efd7f486 2999 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
dedc5eae
MF
3000
3001 if (!search_pc) {
3002 tb->size = dc.pc - pc_start;
3003 tb->icount = insn_count;
3004 }
2328826b
MF
3005}
3006
97129ac8 3007void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb)
2328826b 3008{
dedc5eae 3009 gen_intermediate_code_internal(env, tb, 0);
2328826b
MF
3010}
3011
97129ac8 3012void gen_intermediate_code_pc(CPUXtensaState *env, TranslationBlock *tb)
2328826b 3013{
dedc5eae 3014 gen_intermediate_code_internal(env, tb, 1);
2328826b
MF
3015}
3016
97129ac8 3017void cpu_dump_state(CPUXtensaState *env, FILE *f, fprintf_function cpu_fprintf,
2328826b
MF
3018 int flags)
3019{
2af3da91
MF
3020 int i, j;
3021
3022 cpu_fprintf(f, "PC=%08x\n\n", env->pc);
3023
3024 for (i = j = 0; i < 256; ++i) {
fe0bd475
MF
3025 if (xtensa_option_bits_enabled(env->config, sregnames[i].opt_bits)) {
3026 cpu_fprintf(f, "%12s=%08x%c", sregnames[i].name, env->sregs[i],
2af3da91
MF
3027 (j++ % 4) == 3 ? '\n' : ' ');
3028 }
3029 }
3030
3031 cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
3032
3033 for (i = j = 0; i < 256; ++i) {
fe0bd475
MF
3034 if (xtensa_option_bits_enabled(env->config, uregnames[i].opt_bits)) {
3035 cpu_fprintf(f, "%s=%08x%c", uregnames[i].name, env->uregs[i],
2af3da91
MF
3036 (j++ % 4) == 3 ? '\n' : ' ');
3037 }
3038 }
2328826b 3039
2af3da91 3040 cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
2328826b
MF
3041
3042 for (i = 0; i < 16; ++i) {
fe0bd475 3043 cpu_fprintf(f, " A%02d=%08x%c", i, env->regs[i],
2328826b
MF
3044 (i % 4) == 3 ? '\n' : ' ');
3045 }
553e44f9
MF
3046
3047 cpu_fprintf(f, "\n");
3048
3049 for (i = 0; i < env->config->nareg; ++i) {
3050 cpu_fprintf(f, "AR%02d=%08x%c", i, env->phys_regs[i],
3051 (i % 4) == 3 ? '\n' : ' ');
3052 }
dd519cbe
MF
3053
3054 if (xtensa_option_enabled(env->config, XTENSA_OPTION_FP_COPROCESSOR)) {
3055 cpu_fprintf(f, "\n");
3056
3057 for (i = 0; i < 16; ++i) {
3058 cpu_fprintf(f, "F%02d=%08x (%+10.8e)%c", i,
3059 float32_val(env->fregs[i]),
3060 *(float *)&env->fregs[i], (i % 2) == 1 ? '\n' : ' ');
3061 }
3062 }
2328826b
MF
3063}
3064
97129ac8 3065void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, int pc_pos)
2328826b 3066{
25983cad 3067 env->pc = tcg_ctx.gen_opc_pc[pc_pos];
2328826b 3068}