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