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