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