]> git.proxmox.com Git - qemu.git/blame - target-xtensa/translate.c
target-xtensa: add PS register and access control
[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"
38
dedc5eae
MF
39#include "helpers.h"
40#define GEN_HELPER 1
41#include "helpers.h"
42
43typedef struct DisasContext {
44 const XtensaConfig *config;
45 TranslationBlock *tb;
46 uint32_t pc;
47 uint32_t next_pc;
f0a548b9
MF
48 int cring;
49 int ring;
dedc5eae
MF
50 int is_jmp;
51 int singlestep_enabled;
3580ecad
MF
52
53 bool sar_5bit;
54 bool sar_m32_5bit;
55 bool sar_m32_allocated;
56 TCGv_i32 sar_m32;
dedc5eae
MF
57} DisasContext;
58
59static TCGv_ptr cpu_env;
60static TCGv_i32 cpu_pc;
61static TCGv_i32 cpu_R[16];
2af3da91
MF
62static TCGv_i32 cpu_SR[256];
63static TCGv_i32 cpu_UR[256];
dedc5eae
MF
64
65#include "gen-icount.h"
2328826b 66
2af3da91 67static const char * const sregnames[256] = {
3580ecad 68 [SAR] = "SAR",
809377aa 69 [SCOMPARE1] = "SCOMPARE1",
f0a548b9 70 [PS] = "PS",
2af3da91
MF
71};
72
73static const char * const uregnames[256] = {
74 [THREADPTR] = "THREADPTR",
75 [FCR] = "FCR",
76 [FSR] = "FSR",
77};
78
2328826b
MF
79void xtensa_translate_init(void)
80{
dedc5eae
MF
81 static const char * const regnames[] = {
82 "ar0", "ar1", "ar2", "ar3",
83 "ar4", "ar5", "ar6", "ar7",
84 "ar8", "ar9", "ar10", "ar11",
85 "ar12", "ar13", "ar14", "ar15",
86 };
87 int i;
88
89 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
90 cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
91 offsetof(CPUState, pc), "pc");
92
93 for (i = 0; i < 16; i++) {
94 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
95 offsetof(CPUState, regs[i]),
96 regnames[i]);
97 }
2af3da91
MF
98
99 for (i = 0; i < 256; ++i) {
100 if (sregnames[i]) {
101 cpu_SR[i] = tcg_global_mem_new_i32(TCG_AREG0,
102 offsetof(CPUState, sregs[i]),
103 sregnames[i]);
104 }
105 }
106
107 for (i = 0; i < 256; ++i) {
108 if (uregnames[i]) {
109 cpu_UR[i] = tcg_global_mem_new_i32(TCG_AREG0,
110 offsetof(CPUState, uregs[i]),
111 uregnames[i]);
112 }
113 }
dedc5eae
MF
114#define GEN_HELPER 2
115#include "helpers.h"
116}
117
118static inline bool option_enabled(DisasContext *dc, int opt)
119{
120 return xtensa_option_enabled(dc->config, opt);
121}
122
3580ecad
MF
123static void init_sar_tracker(DisasContext *dc)
124{
125 dc->sar_5bit = false;
126 dc->sar_m32_5bit = false;
127 dc->sar_m32_allocated = false;
128}
129
130static void reset_sar_tracker(DisasContext *dc)
131{
132 if (dc->sar_m32_allocated) {
133 tcg_temp_free(dc->sar_m32);
134 }
135}
136
137static void gen_right_shift_sar(DisasContext *dc, TCGv_i32 sa)
138{
139 tcg_gen_andi_i32(cpu_SR[SAR], sa, 0x1f);
140 if (dc->sar_m32_5bit) {
141 tcg_gen_discard_i32(dc->sar_m32);
142 }
143 dc->sar_5bit = true;
144 dc->sar_m32_5bit = false;
145}
146
147static void gen_left_shift_sar(DisasContext *dc, TCGv_i32 sa)
148{
149 TCGv_i32 tmp = tcg_const_i32(32);
150 if (!dc->sar_m32_allocated) {
151 dc->sar_m32 = tcg_temp_local_new_i32();
152 dc->sar_m32_allocated = true;
153 }
154 tcg_gen_andi_i32(dc->sar_m32, sa, 0x1f);
155 tcg_gen_sub_i32(cpu_SR[SAR], tmp, dc->sar_m32);
156 dc->sar_5bit = false;
157 dc->sar_m32_5bit = true;
158 tcg_temp_free(tmp);
159}
160
dedc5eae
MF
161static void gen_exception(int excp)
162{
163 TCGv_i32 tmp = tcg_const_i32(excp);
164 gen_helper_exception(tmp);
165 tcg_temp_free(tmp);
166}
167
168static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
169{
170 tcg_gen_mov_i32(cpu_pc, dest);
171 if (dc->singlestep_enabled) {
172 gen_exception(EXCP_DEBUG);
173 } else {
174 if (slot >= 0) {
175 tcg_gen_goto_tb(slot);
176 tcg_gen_exit_tb((tcg_target_long)dc->tb + slot);
177 } else {
178 tcg_gen_exit_tb(0);
179 }
180 }
181 dc->is_jmp = DISAS_UPDATE;
182}
183
67882fd1
MF
184static void gen_jump(DisasContext *dc, TCGv dest)
185{
186 gen_jump_slot(dc, dest, -1);
187}
188
dedc5eae
MF
189static void gen_jumpi(DisasContext *dc, uint32_t dest, int slot)
190{
191 TCGv_i32 tmp = tcg_const_i32(dest);
192 if (((dc->pc ^ dest) & TARGET_PAGE_MASK) != 0) {
193 slot = -1;
194 }
195 gen_jump_slot(dc, tmp, slot);
196 tcg_temp_free(tmp);
197}
198
bd57fb91
MF
199static void gen_brcond(DisasContext *dc, TCGCond cond,
200 TCGv_i32 t0, TCGv_i32 t1, uint32_t offset)
201{
202 int label = gen_new_label();
203
204 tcg_gen_brcond_i32(cond, t0, t1, label);
205 gen_jumpi(dc, dc->next_pc, 0);
206 gen_set_label(label);
207 gen_jumpi(dc, dc->pc + offset, 1);
208}
209
210static void gen_brcondi(DisasContext *dc, TCGCond cond,
211 TCGv_i32 t0, uint32_t t1, uint32_t offset)
212{
213 TCGv_i32 tmp = tcg_const_i32(t1);
214 gen_brcond(dc, cond, t0, tmp, offset);
215 tcg_temp_free(tmp);
216}
217
b8132eff
MF
218static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
219{
220 static void (* const rsr_handler[256])(DisasContext *dc,
221 TCGv_i32 d, uint32_t sr) = {
222 };
223
224 if (sregnames[sr]) {
225 if (rsr_handler[sr]) {
226 rsr_handler[sr](dc, d, sr);
227 } else {
228 tcg_gen_mov_i32(d, cpu_SR[sr]);
229 }
230 } else {
231 qemu_log("RSR %d not implemented, ", sr);
232 }
233}
234
3580ecad
MF
235static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)
236{
237 tcg_gen_andi_i32(cpu_SR[sr], s, 0x3f);
238 if (dc->sar_m32_5bit) {
239 tcg_gen_discard_i32(dc->sar_m32);
240 }
241 dc->sar_5bit = false;
242 dc->sar_m32_5bit = false;
243}
244
f0a548b9
MF
245static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
246{
247 uint32_t mask = PS_WOE | PS_CALLINC | PS_OWB |
248 PS_UM | PS_EXCM | PS_INTLEVEL;
249
250 if (option_enabled(dc, XTENSA_OPTION_MMU)) {
251 mask |= PS_RING;
252 }
253 tcg_gen_andi_i32(cpu_SR[sr], v, mask);
254 /* This can change mmu index, so exit tb */
255 gen_jumpi(dc, dc->next_pc, -1);
256}
257
b8132eff
MF
258static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
259{
260 static void (* const wsr_handler[256])(DisasContext *dc,
261 uint32_t sr, TCGv_i32 v) = {
3580ecad 262 [SAR] = gen_wsr_sar,
f0a548b9 263 [PS] = gen_wsr_ps,
b8132eff
MF
264 };
265
266 if (sregnames[sr]) {
267 if (wsr_handler[sr]) {
268 wsr_handler[sr](dc, sr, s);
269 } else {
270 tcg_gen_mov_i32(cpu_SR[sr], s);
271 }
272 } else {
273 qemu_log("WSR %d not implemented, ", sr);
274 }
275}
276
dedc5eae
MF
277static void disas_xtensa_insn(DisasContext *dc)
278{
279#define HAS_OPTION(opt) do { \
280 if (!option_enabled(dc, opt)) { \
281 qemu_log("Option %d is not enabled %s:%d\n", \
282 (opt), __FILE__, __LINE__); \
283 goto invalid_opcode; \
284 } \
285 } while (0)
286
91a5bb76
MF
287#define TBD() qemu_log("TBD(pc = %08x): %s:%d\n", dc->pc, __FILE__, __LINE__)
288#define RESERVED() do { \
289 qemu_log("RESERVED(pc = %08x, %02x%02x%02x): %s:%d\n", \
290 dc->pc, b0, b1, b2, __FILE__, __LINE__); \
291 goto invalid_opcode; \
292 } while (0)
293
294
dedc5eae
MF
295#ifdef TARGET_WORDS_BIGENDIAN
296#define OP0 (((b0) & 0xf0) >> 4)
297#define OP1 (((b2) & 0xf0) >> 4)
298#define OP2 ((b2) & 0xf)
299#define RRR_R ((b1) & 0xf)
300#define RRR_S (((b1) & 0xf0) >> 4)
301#define RRR_T ((b0) & 0xf)
302#else
303#define OP0 (((b0) & 0xf))
304#define OP1 (((b2) & 0xf))
305#define OP2 (((b2) & 0xf0) >> 4)
306#define RRR_R (((b1) & 0xf0) >> 4)
307#define RRR_S (((b1) & 0xf))
308#define RRR_T (((b0) & 0xf0) >> 4)
309#endif
310
311#define RRRN_R RRR_R
312#define RRRN_S RRR_S
313#define RRRN_T RRR_T
314
315#define RRI8_R RRR_R
316#define RRI8_S RRR_S
317#define RRI8_T RRR_T
318#define RRI8_IMM8 (b2)
319#define RRI8_IMM8_SE ((((b2) & 0x80) ? 0xffffff00 : 0) | RRI8_IMM8)
320
321#ifdef TARGET_WORDS_BIGENDIAN
322#define RI16_IMM16 (((b1) << 8) | (b2))
323#else
324#define RI16_IMM16 (((b2) << 8) | (b1))
325#endif
326
327#ifdef TARGET_WORDS_BIGENDIAN
328#define CALL_N (((b0) & 0xc) >> 2)
329#define CALL_OFFSET ((((b0) & 0x3) << 16) | ((b1) << 8) | (b2))
330#else
331#define CALL_N (((b0) & 0x30) >> 4)
332#define CALL_OFFSET ((((b0) & 0xc0) >> 6) | ((b1) << 2) | ((b2) << 10))
333#endif
334#define CALL_OFFSET_SE \
335 (((CALL_OFFSET & 0x20000) ? 0xfffc0000 : 0) | CALL_OFFSET)
336
337#define CALLX_N CALL_N
338#ifdef TARGET_WORDS_BIGENDIAN
339#define CALLX_M ((b0) & 0x3)
340#else
341#define CALLX_M (((b0) & 0xc0) >> 6)
342#endif
343#define CALLX_S RRR_S
344
345#define BRI12_M CALLX_M
346#define BRI12_S RRR_S
347#ifdef TARGET_WORDS_BIGENDIAN
348#define BRI12_IMM12 ((((b1) & 0xf) << 8) | (b2))
349#else
350#define BRI12_IMM12 ((((b1) & 0xf0) >> 4) | ((b2) << 4))
351#endif
352#define BRI12_IMM12_SE (((BRI12_IMM12 & 0x800) ? 0xfffff000 : 0) | BRI12_IMM12)
353
354#define BRI8_M BRI12_M
355#define BRI8_R RRI8_R
356#define BRI8_S RRI8_S
357#define BRI8_IMM8 RRI8_IMM8
358#define BRI8_IMM8_SE RRI8_IMM8_SE
359
360#define RSR_SR (b1)
361
362 uint8_t b0 = ldub_code(dc->pc);
363 uint8_t b1 = ldub_code(dc->pc + 1);
364 uint8_t b2 = ldub_code(dc->pc + 2);
365
bd57fb91
MF
366 static const uint32_t B4CONST[] = {
367 0xffffffff, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
368 };
369
370 static const uint32_t B4CONSTU[] = {
371 32768, 65536, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
372 };
373
dedc5eae
MF
374 if (OP0 >= 8) {
375 dc->next_pc = dc->pc + 2;
376 HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);
377 } else {
378 dc->next_pc = dc->pc + 3;
379 }
380
381 switch (OP0) {
382 case 0: /*QRST*/
383 switch (OP1) {
384 case 0: /*RST0*/
385 switch (OP2) {
386 case 0: /*ST0*/
387 if ((RRR_R & 0xc) == 0x8) {
388 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
389 }
390
391 switch (RRR_R) {
392 case 0: /*SNM0*/
5da4a6a8
MF
393 switch (CALLX_M) {
394 case 0: /*ILL*/
91a5bb76 395 TBD();
5da4a6a8
MF
396 break;
397
398 case 1: /*reserved*/
91a5bb76 399 RESERVED();
5da4a6a8
MF
400 break;
401
402 case 2: /*JR*/
403 switch (CALLX_N) {
404 case 0: /*RET*/
405 case 2: /*JX*/
406 gen_jump(dc, cpu_R[CALLX_S]);
407 break;
408
409 case 1: /*RETWw*/
410 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
91a5bb76 411 TBD();
5da4a6a8
MF
412 break;
413
414 case 3: /*reserved*/
91a5bb76 415 RESERVED();
5da4a6a8
MF
416 break;
417 }
418 break;
419
420 case 3: /*CALLX*/
421 switch (CALLX_N) {
422 case 0: /*CALLX0*/
423 {
424 TCGv_i32 tmp = tcg_temp_new_i32();
425 tcg_gen_mov_i32(tmp, cpu_R[CALLX_S]);
426 tcg_gen_movi_i32(cpu_R[0], dc->next_pc);
427 gen_jump(dc, tmp);
428 tcg_temp_free(tmp);
429 }
430 break;
431
432 case 1: /*CALLX4w*/
433 case 2: /*CALLX8w*/
434 case 3: /*CALLX12w*/
435 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
91a5bb76 436 TBD();
5da4a6a8
MF
437 break;
438 }
439 break;
440 }
dedc5eae
MF
441 break;
442
443 case 1: /*MOVSPw*/
444 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
91a5bb76 445 TBD();
dedc5eae
MF
446 break;
447
448 case 2: /*SYNC*/
28067b22
MF
449 switch (RRR_T) {
450 case 0: /*ISYNC*/
451 break;
452
453 case 1: /*RSYNC*/
454 break;
455
456 case 2: /*ESYNC*/
457 break;
458
459 case 3: /*DSYNC*/
460 break;
461
462 case 8: /*EXCW*/
463 HAS_OPTION(XTENSA_OPTION_EXCEPTION);
464 break;
465
466 case 12: /*MEMW*/
467 break;
468
469 case 13: /*EXTW*/
470 break;
471
472 case 15: /*NOP*/
473 break;
474
475 default: /*reserved*/
476 RESERVED();
477 break;
478 }
91a5bb76
MF
479 break;
480
481 case 3: /*RFEIx*/
482 TBD();
483 break;
484
485 case 4: /*BREAKx*/
486 HAS_OPTION(XTENSA_OPTION_EXCEPTION);
487 TBD();
488 break;
489
490 case 5: /*SYSCALLx*/
491 HAS_OPTION(XTENSA_OPTION_EXCEPTION);
492 TBD();
493 break;
494
495 case 6: /*RSILx*/
496 HAS_OPTION(XTENSA_OPTION_INTERRUPT);
497 TBD();
498 break;
499
500 case 7: /*WAITIx*/
501 HAS_OPTION(XTENSA_OPTION_INTERRUPT);
502 TBD();
503 break;
504
505 case 8: /*ANY4p*/
506 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
507 TBD();
508 break;
509
510 case 9: /*ALL4p*/
511 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
512 TBD();
dedc5eae
MF
513 break;
514
91a5bb76
MF
515 case 10: /*ANY8p*/
516 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
517 TBD();
518 break;
519
520 case 11: /*ALL8p*/
521 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
522 TBD();
523 break;
524
525 default: /*reserved*/
526 RESERVED();
dedc5eae
MF
527 break;
528
529 }
530 break;
531
532 case 1: /*AND*/
533 tcg_gen_and_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
534 break;
535
536 case 2: /*OR*/
537 tcg_gen_or_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
538 break;
539
540 case 3: /*XOR*/
541 tcg_gen_xor_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
542 break;
543
544 case 4: /*ST1*/
3580ecad
MF
545 switch (RRR_R) {
546 case 0: /*SSR*/
547 gen_right_shift_sar(dc, cpu_R[RRR_S]);
548 break;
549
550 case 1: /*SSL*/
551 gen_left_shift_sar(dc, cpu_R[RRR_S]);
552 break;
553
554 case 2: /*SSA8L*/
555 {
556 TCGv_i32 tmp = tcg_temp_new_i32();
557 tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 3);
558 gen_right_shift_sar(dc, tmp);
559 tcg_temp_free(tmp);
560 }
561 break;
562
563 case 3: /*SSA8B*/
564 {
565 TCGv_i32 tmp = tcg_temp_new_i32();
566 tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 3);
567 gen_left_shift_sar(dc, tmp);
568 tcg_temp_free(tmp);
569 }
570 break;
571
572 case 4: /*SSAI*/
573 {
574 TCGv_i32 tmp = tcg_const_i32(
575 RRR_S | ((RRR_T & 1) << 4));
576 gen_right_shift_sar(dc, tmp);
577 tcg_temp_free(tmp);
578 }
579 break;
580
581 case 6: /*RER*/
91a5bb76 582 TBD();
3580ecad
MF
583 break;
584
585 case 7: /*WER*/
91a5bb76 586 TBD();
3580ecad
MF
587 break;
588
589 case 8: /*ROTWw*/
590 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
91a5bb76 591 TBD();
3580ecad
MF
592 break;
593
594 case 14: /*NSAu*/
595 HAS_OPTION(XTENSA_OPTION_MISC_OP);
596 gen_helper_nsa(cpu_R[RRR_T], cpu_R[RRR_S]);
597 break;
598
599 case 15: /*NSAUu*/
600 HAS_OPTION(XTENSA_OPTION_MISC_OP);
601 gen_helper_nsau(cpu_R[RRR_T], cpu_R[RRR_S]);
602 break;
603
604 default: /*reserved*/
91a5bb76 605 RESERVED();
3580ecad
MF
606 break;
607 }
dedc5eae
MF
608 break;
609
610 case 5: /*TLB*/
91a5bb76 611 TBD();
dedc5eae
MF
612 break;
613
614 case 6: /*RT0*/
f331fe5e
MF
615 switch (RRR_S) {
616 case 0: /*NEG*/
617 tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
618 break;
619
620 case 1: /*ABS*/
621 {
622 int label = gen_new_label();
623 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
624 tcg_gen_brcondi_i32(
625 TCG_COND_GE, cpu_R[RRR_R], 0, label);
626 tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
627 gen_set_label(label);
628 }
629 break;
630
631 default: /*reserved*/
91a5bb76 632 RESERVED();
f331fe5e
MF
633 break;
634 }
dedc5eae
MF
635 break;
636
637 case 7: /*reserved*/
91a5bb76 638 RESERVED();
dedc5eae
MF
639 break;
640
641 case 8: /*ADD*/
642 tcg_gen_add_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
643 break;
644
645 case 9: /*ADD**/
646 case 10:
647 case 11:
648 {
649 TCGv_i32 tmp = tcg_temp_new_i32();
650 tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 8);
651 tcg_gen_add_i32(cpu_R[RRR_R], tmp, cpu_R[RRR_T]);
652 tcg_temp_free(tmp);
653 }
654 break;
655
656 case 12: /*SUB*/
657 tcg_gen_sub_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
658 break;
659
660 case 13: /*SUB**/
661 case 14:
662 case 15:
663 {
664 TCGv_i32 tmp = tcg_temp_new_i32();
665 tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 12);
666 tcg_gen_sub_i32(cpu_R[RRR_R], tmp, cpu_R[RRR_T]);
667 tcg_temp_free(tmp);
668 }
669 break;
670 }
671 break;
672
673 case 1: /*RST1*/
3580ecad
MF
674 switch (OP2) {
675 case 0: /*SLLI*/
676 case 1:
677 tcg_gen_shli_i32(cpu_R[RRR_R], cpu_R[RRR_S],
678 32 - (RRR_T | ((OP2 & 1) << 4)));
679 break;
680
681 case 2: /*SRAI*/
682 case 3:
683 tcg_gen_sari_i32(cpu_R[RRR_R], cpu_R[RRR_T],
684 RRR_S | ((OP2 & 1) << 4));
685 break;
686
687 case 4: /*SRLI*/
688 tcg_gen_shri_i32(cpu_R[RRR_R], cpu_R[RRR_T], RRR_S);
689 break;
690
691 case 6: /*XSR*/
692 {
693 TCGv_i32 tmp = tcg_temp_new_i32();
694 tcg_gen_mov_i32(tmp, cpu_R[RRR_T]);
695 gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
696 gen_wsr(dc, RSR_SR, tmp);
697 tcg_temp_free(tmp);
91a5bb76
MF
698 if (!sregnames[RSR_SR]) {
699 TBD();
700 }
3580ecad
MF
701 }
702 break;
703
704 /*
705 * Note: 64 bit ops are used here solely because SAR values
706 * have range 0..63
707 */
708#define gen_shift_reg(cmd, reg) do { \
709 TCGv_i64 tmp = tcg_temp_new_i64(); \
710 tcg_gen_extu_i32_i64(tmp, reg); \
711 tcg_gen_##cmd##_i64(v, v, tmp); \
712 tcg_gen_trunc_i64_i32(cpu_R[RRR_R], v); \
713 tcg_temp_free_i64(v); \
714 tcg_temp_free_i64(tmp); \
715 } while (0)
716
717#define gen_shift(cmd) gen_shift_reg(cmd, cpu_SR[SAR])
718
719 case 8: /*SRC*/
720 {
721 TCGv_i64 v = tcg_temp_new_i64();
722 tcg_gen_concat_i32_i64(v, cpu_R[RRR_T], cpu_R[RRR_S]);
723 gen_shift(shr);
724 }
725 break;
726
727 case 9: /*SRL*/
728 if (dc->sar_5bit) {
729 tcg_gen_shr_i32(cpu_R[RRR_R], cpu_R[RRR_T], cpu_SR[SAR]);
730 } else {
731 TCGv_i64 v = tcg_temp_new_i64();
732 tcg_gen_extu_i32_i64(v, cpu_R[RRR_T]);
733 gen_shift(shr);
734 }
735 break;
736
737 case 10: /*SLL*/
738 if (dc->sar_m32_5bit) {
739 tcg_gen_shl_i32(cpu_R[RRR_R], cpu_R[RRR_S], dc->sar_m32);
740 } else {
741 TCGv_i64 v = tcg_temp_new_i64();
742 TCGv_i32 s = tcg_const_i32(32);
743 tcg_gen_sub_i32(s, s, cpu_SR[SAR]);
744 tcg_gen_andi_i32(s, s, 0x3f);
745 tcg_gen_extu_i32_i64(v, cpu_R[RRR_S]);
746 gen_shift_reg(shl, s);
747 tcg_temp_free(s);
748 }
749 break;
750
751 case 11: /*SRA*/
752 if (dc->sar_5bit) {
753 tcg_gen_sar_i32(cpu_R[RRR_R], cpu_R[RRR_T], cpu_SR[SAR]);
754 } else {
755 TCGv_i64 v = tcg_temp_new_i64();
756 tcg_gen_ext_i32_i64(v, cpu_R[RRR_T]);
757 gen_shift(sar);
758 }
759 break;
760#undef gen_shift
761#undef gen_shift_reg
762
763 case 12: /*MUL16U*/
764 HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL);
765 {
766 TCGv_i32 v1 = tcg_temp_new_i32();
767 TCGv_i32 v2 = tcg_temp_new_i32();
768 tcg_gen_ext16u_i32(v1, cpu_R[RRR_S]);
769 tcg_gen_ext16u_i32(v2, cpu_R[RRR_T]);
770 tcg_gen_mul_i32(cpu_R[RRR_R], v1, v2);
771 tcg_temp_free(v2);
772 tcg_temp_free(v1);
773 }
774 break;
775
776 case 13: /*MUL16S*/
777 HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL);
778 {
779 TCGv_i32 v1 = tcg_temp_new_i32();
780 TCGv_i32 v2 = tcg_temp_new_i32();
781 tcg_gen_ext16s_i32(v1, cpu_R[RRR_S]);
782 tcg_gen_ext16s_i32(v2, cpu_R[RRR_T]);
783 tcg_gen_mul_i32(cpu_R[RRR_R], v1, v2);
784 tcg_temp_free(v2);
785 tcg_temp_free(v1);
786 }
787 break;
788
789 default: /*reserved*/
91a5bb76 790 RESERVED();
3580ecad
MF
791 break;
792 }
dedc5eae
MF
793 break;
794
795 case 2: /*RST2*/
91a5bb76 796 TBD();
dedc5eae
MF
797 break;
798
799 case 3: /*RST3*/
b8132eff
MF
800 switch (OP2) {
801 case 0: /*RSR*/
802 gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
91a5bb76
MF
803 if (!sregnames[RSR_SR]) {
804 TBD();
805 }
b8132eff
MF
806 break;
807
808 case 1: /*WSR*/
809 gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);
91a5bb76
MF
810 if (!sregnames[RSR_SR]) {
811 TBD();
812 }
b8132eff
MF
813 break;
814
815 case 2: /*SEXTu*/
816 HAS_OPTION(XTENSA_OPTION_MISC_OP);
817 {
818 int shift = 24 - RRR_T;
819
820 if (shift == 24) {
821 tcg_gen_ext8s_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
822 } else if (shift == 16) {
823 tcg_gen_ext16s_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
824 } else {
825 TCGv_i32 tmp = tcg_temp_new_i32();
826 tcg_gen_shli_i32(tmp, cpu_R[RRR_S], shift);
827 tcg_gen_sari_i32(cpu_R[RRR_R], tmp, shift);
828 tcg_temp_free(tmp);
829 }
830 }
831 break;
832
833 case 3: /*CLAMPSu*/
834 HAS_OPTION(XTENSA_OPTION_MISC_OP);
835 {
836 TCGv_i32 tmp1 = tcg_temp_new_i32();
837 TCGv_i32 tmp2 = tcg_temp_new_i32();
838 int label = gen_new_label();
839
840 tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 24 - RRR_T);
841 tcg_gen_xor_i32(tmp2, tmp1, cpu_R[RRR_S]);
842 tcg_gen_andi_i32(tmp2, tmp2, 0xffffffff << (RRR_T + 7));
843 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
844 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp2, 0, label);
845
846 tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 31);
847 tcg_gen_xori_i32(cpu_R[RRR_R], tmp1,
848 0xffffffff >> (25 - RRR_T));
849
850 gen_set_label(label);
851
852 tcg_temp_free(tmp1);
853 tcg_temp_free(tmp2);
854 }
855 break;
856
857 case 4: /*MINu*/
858 case 5: /*MAXu*/
859 case 6: /*MINUu*/
860 case 7: /*MAXUu*/
861 HAS_OPTION(XTENSA_OPTION_MISC_OP);
862 {
863 static const TCGCond cond[] = {
864 TCG_COND_LE,
865 TCG_COND_GE,
866 TCG_COND_LEU,
867 TCG_COND_GEU
868 };
869 int label = gen_new_label();
870
871 if (RRR_R != RRR_T) {
872 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
873 tcg_gen_brcond_i32(cond[OP2 - 4],
874 cpu_R[RRR_S], cpu_R[RRR_T], label);
875 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
876 } else {
877 tcg_gen_brcond_i32(cond[OP2 - 4],
878 cpu_R[RRR_T], cpu_R[RRR_S], label);
879 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
880 }
881 gen_set_label(label);
882 }
883 break;
884
885 case 8: /*MOVEQZ*/
886 case 9: /*MOVNEZ*/
887 case 10: /*MOVLTZ*/
888 case 11: /*MOVGEZ*/
889 {
890 static const TCGCond cond[] = {
891 TCG_COND_NE,
892 TCG_COND_EQ,
893 TCG_COND_GE,
894 TCG_COND_LT
895 };
896 int label = gen_new_label();
897 tcg_gen_brcondi_i32(cond[OP2 - 8], cpu_R[RRR_T], 0, label);
898 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
899 gen_set_label(label);
900 }
901 break;
902
903 case 12: /*MOVFp*/
904 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
91a5bb76 905 TBD();
b8132eff
MF
906 break;
907
908 case 13: /*MOVTp*/
909 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
91a5bb76 910 TBD();
b8132eff
MF
911 break;
912
913 case 14: /*RUR*/
914 {
915 int st = (RRR_S << 4) + RRR_T;
916 if (uregnames[st]) {
917 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_UR[st]);
918 } else {
919 qemu_log("RUR %d not implemented, ", st);
91a5bb76 920 TBD();
b8132eff
MF
921 }
922 }
923 break;
924
925 case 15: /*WUR*/
926 {
927 if (uregnames[RSR_SR]) {
928 tcg_gen_mov_i32(cpu_UR[RSR_SR], cpu_R[RRR_T]);
929 } else {
930 qemu_log("WUR %d not implemented, ", RSR_SR);
91a5bb76 931 TBD();
b8132eff
MF
932 }
933 }
934 break;
935
936 }
dedc5eae
MF
937 break;
938
939 case 4: /*EXTUI*/
940 case 5:
3580ecad
MF
941 {
942 int shiftimm = RRR_S | (OP1 << 4);
943 int maskimm = (1 << (OP2 + 1)) - 1;
944
945 TCGv_i32 tmp = tcg_temp_new_i32();
946 tcg_gen_shri_i32(tmp, cpu_R[RRR_T], shiftimm);
947 tcg_gen_andi_i32(cpu_R[RRR_R], tmp, maskimm);
948 tcg_temp_free(tmp);
949 }
dedc5eae
MF
950 break;
951
952 case 6: /*CUST0*/
91a5bb76 953 RESERVED();
dedc5eae
MF
954 break;
955
956 case 7: /*CUST1*/
91a5bb76 957 RESERVED();
dedc5eae
MF
958 break;
959
960 case 8: /*LSCXp*/
961 HAS_OPTION(XTENSA_OPTION_COPROCESSOR);
91a5bb76 962 TBD();
dedc5eae
MF
963 break;
964
965 case 9: /*LSC4*/
91a5bb76 966 TBD();
dedc5eae
MF
967 break;
968
969 case 10: /*FP0*/
970 HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
91a5bb76 971 TBD();
dedc5eae
MF
972 break;
973
974 case 11: /*FP1*/
975 HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
91a5bb76 976 TBD();
dedc5eae
MF
977 break;
978
979 default: /*reserved*/
91a5bb76 980 RESERVED();
dedc5eae
MF
981 break;
982 }
983 break;
984
985 case 1: /*L32R*/
986 {
987 TCGv_i32 tmp = tcg_const_i32(
988 (0xfffc0000 | (RI16_IMM16 << 2)) +
989 ((dc->pc + 3) & ~3));
990
991 /* no ext L32R */
992
f0a548b9 993 tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, dc->cring);
dedc5eae
MF
994 tcg_temp_free(tmp);
995 }
996 break;
997
998 case 2: /*LSAI*/
809377aa
MF
999#define gen_load_store(type, shift) do { \
1000 TCGv_i32 addr = tcg_temp_new_i32(); \
1001 tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << shift); \
f0a548b9 1002 tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
809377aa
MF
1003 tcg_temp_free(addr); \
1004 } while (0)
1005
1006 switch (RRI8_R) {
1007 case 0: /*L8UI*/
1008 gen_load_store(ld8u, 0);
1009 break;
1010
1011 case 1: /*L16UI*/
1012 gen_load_store(ld16u, 1);
1013 break;
1014
1015 case 2: /*L32I*/
1016 gen_load_store(ld32u, 2);
1017 break;
1018
1019 case 4: /*S8I*/
1020 gen_load_store(st8, 0);
1021 break;
1022
1023 case 5: /*S16I*/
1024 gen_load_store(st16, 1);
1025 break;
1026
1027 case 6: /*S32I*/
1028 gen_load_store(st32, 2);
1029 break;
1030
1031 case 7: /*CACHEc*/
8ffc2d0d
MF
1032 if (RRI8_T < 8) {
1033 HAS_OPTION(XTENSA_OPTION_DCACHE);
1034 }
1035
1036 switch (RRI8_T) {
1037 case 0: /*DPFRc*/
1038 break;
1039
1040 case 1: /*DPFWc*/
1041 break;
1042
1043 case 2: /*DPFROc*/
1044 break;
1045
1046 case 3: /*DPFWOc*/
1047 break;
1048
1049 case 4: /*DHWBc*/
1050 break;
1051
1052 case 5: /*DHWBIc*/
1053 break;
1054
1055 case 6: /*DHIc*/
1056 break;
1057
1058 case 7: /*DIIc*/
1059 break;
1060
1061 case 8: /*DCEc*/
1062 switch (OP1) {
1063 case 0: /*DPFLl*/
1064 HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);
1065 break;
1066
1067 case 2: /*DHUl*/
1068 HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);
1069 break;
1070
1071 case 3: /*DIUl*/
1072 HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);
1073 break;
1074
1075 case 4: /*DIWBc*/
1076 HAS_OPTION(XTENSA_OPTION_DCACHE);
1077 break;
1078
1079 case 5: /*DIWBIc*/
1080 HAS_OPTION(XTENSA_OPTION_DCACHE);
1081 break;
1082
1083 default: /*reserved*/
1084 RESERVED();
1085 break;
1086
1087 }
1088 break;
1089
1090 case 12: /*IPFc*/
1091 HAS_OPTION(XTENSA_OPTION_ICACHE);
1092 break;
1093
1094 case 13: /*ICEc*/
1095 switch (OP1) {
1096 case 0: /*IPFLl*/
1097 HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);
1098 break;
1099
1100 case 2: /*IHUl*/
1101 HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);
1102 break;
1103
1104 case 3: /*IIUl*/
1105 HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);
1106 break;
1107
1108 default: /*reserved*/
1109 RESERVED();
1110 break;
1111 }
1112 break;
1113
1114 case 14: /*IHIc*/
1115 HAS_OPTION(XTENSA_OPTION_ICACHE);
1116 break;
1117
1118 case 15: /*IIIc*/
1119 HAS_OPTION(XTENSA_OPTION_ICACHE);
1120 break;
1121
1122 default: /*reserved*/
1123 RESERVED();
1124 break;
1125 }
809377aa
MF
1126 break;
1127
1128 case 9: /*L16SI*/
1129 gen_load_store(ld16s, 1);
1130 break;
1131
1132 case 10: /*MOVI*/
1133 tcg_gen_movi_i32(cpu_R[RRI8_T],
1134 RRI8_IMM8 | (RRI8_S << 8) |
1135 ((RRI8_S & 0x8) ? 0xfffff000 : 0));
1136 break;
1137
1138 case 11: /*L32AIy*/
1139 HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
1140 gen_load_store(ld32u, 2); /*TODO acquire?*/
1141 break;
1142
1143 case 12: /*ADDI*/
1144 tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE);
1145 break;
1146
1147 case 13: /*ADDMI*/
1148 tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE << 8);
1149 break;
1150
1151 case 14: /*S32C1Iy*/
1152 HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
1153 {
1154 int label = gen_new_label();
1155 TCGv_i32 tmp = tcg_temp_local_new_i32();
1156 TCGv_i32 addr = tcg_temp_local_new_i32();
1157
1158 tcg_gen_mov_i32(tmp, cpu_R[RRI8_T]);
1159 tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2);
f0a548b9 1160 tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, dc->cring);
809377aa
MF
1161 tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[RRI8_T],
1162 cpu_SR[SCOMPARE1], label);
1163
f0a548b9 1164 tcg_gen_qemu_st32(tmp, addr, dc->cring);
809377aa
MF
1165
1166 gen_set_label(label);
1167 tcg_temp_free(addr);
1168 tcg_temp_free(tmp);
1169 }
1170 break;
1171
1172 case 15: /*S32RIy*/
1173 HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
1174 gen_load_store(st32, 2); /*TODO release?*/
1175 break;
1176
1177 default: /*reserved*/
91a5bb76 1178 RESERVED();
809377aa
MF
1179 break;
1180 }
dedc5eae 1181 break;
809377aa 1182#undef gen_load_store
dedc5eae
MF
1183
1184 case 3: /*LSCIp*/
1185 HAS_OPTION(XTENSA_OPTION_COPROCESSOR);
91a5bb76 1186 TBD();
dedc5eae
MF
1187 break;
1188
1189 case 4: /*MAC16d*/
1190 HAS_OPTION(XTENSA_OPTION_MAC16);
91a5bb76 1191 TBD();
dedc5eae
MF
1192 break;
1193
1194 case 5: /*CALLN*/
1195 switch (CALL_N) {
1196 case 0: /*CALL0*/
1197 tcg_gen_movi_i32(cpu_R[0], dc->next_pc);
1198 gen_jumpi(dc, (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4, 0);
1199 break;
1200
1201 case 1: /*CALL4w*/
1202 case 2: /*CALL8w*/
1203 case 3: /*CALL12w*/
1204 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
91a5bb76 1205 TBD();
dedc5eae
MF
1206 break;
1207 }
1208 break;
1209
1210 case 6: /*SI*/
1211 switch (CALL_N) {
1212 case 0: /*J*/
1213 gen_jumpi(dc, dc->pc + 4 + CALL_OFFSET_SE, 0);
1214 break;
1215
bd57fb91
MF
1216 case 1: /*BZ*/
1217 {
1218 static const TCGCond cond[] = {
1219 TCG_COND_EQ, /*BEQZ*/
1220 TCG_COND_NE, /*BNEZ*/
1221 TCG_COND_LT, /*BLTZ*/
1222 TCG_COND_GE, /*BGEZ*/
1223 };
1224
1225 gen_brcondi(dc, cond[BRI12_M & 3], cpu_R[BRI12_S], 0,
1226 4 + BRI12_IMM12_SE);
1227 }
1228 break;
1229
1230 case 2: /*BI0*/
1231 {
1232 static const TCGCond cond[] = {
1233 TCG_COND_EQ, /*BEQI*/
1234 TCG_COND_NE, /*BNEI*/
1235 TCG_COND_LT, /*BLTI*/
1236 TCG_COND_GE, /*BGEI*/
1237 };
1238
1239 gen_brcondi(dc, cond[BRI8_M & 3],
1240 cpu_R[BRI8_S], B4CONST[BRI8_R], 4 + BRI8_IMM8_SE);
1241 }
1242 break;
1243
1244 case 3: /*BI1*/
1245 switch (BRI8_M) {
1246 case 0: /*ENTRYw*/
1247 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
91a5bb76 1248 TBD();
bd57fb91
MF
1249 break;
1250
1251 case 1: /*B1*/
1252 switch (BRI8_R) {
1253 case 0: /*BFp*/
1254 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
91a5bb76 1255 TBD();
bd57fb91
MF
1256 break;
1257
1258 case 1: /*BTp*/
1259 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
91a5bb76 1260 TBD();
bd57fb91
MF
1261 break;
1262
1263 case 8: /*LOOP*/
91a5bb76 1264 TBD();
bd57fb91
MF
1265 break;
1266
1267 case 9: /*LOOPNEZ*/
91a5bb76 1268 TBD();
bd57fb91
MF
1269 break;
1270
1271 case 10: /*LOOPGTZ*/
91a5bb76 1272 TBD();
bd57fb91
MF
1273 break;
1274
1275 default: /*reserved*/
91a5bb76 1276 RESERVED();
bd57fb91
MF
1277 break;
1278
1279 }
1280 break;
1281
1282 case 2: /*BLTUI*/
1283 case 3: /*BGEUI*/
1284 gen_brcondi(dc, BRI8_M == 2 ? TCG_COND_LTU : TCG_COND_GEU,
1285 cpu_R[BRI8_S], B4CONSTU[BRI8_R], 4 + BRI8_IMM8_SE);
1286 break;
1287 }
1288 break;
1289
dedc5eae
MF
1290 }
1291 break;
1292
1293 case 7: /*B*/
bd57fb91
MF
1294 {
1295 TCGCond eq_ne = (RRI8_R & 8) ? TCG_COND_NE : TCG_COND_EQ;
1296
1297 switch (RRI8_R & 7) {
1298 case 0: /*BNONE*/ /*BANY*/
1299 {
1300 TCGv_i32 tmp = tcg_temp_new_i32();
1301 tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);
1302 gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);
1303 tcg_temp_free(tmp);
1304 }
1305 break;
1306
1307 case 1: /*BEQ*/ /*BNE*/
1308 case 2: /*BLT*/ /*BGE*/
1309 case 3: /*BLTU*/ /*BGEU*/
1310 {
1311 static const TCGCond cond[] = {
1312 [1] = TCG_COND_EQ,
1313 [2] = TCG_COND_LT,
1314 [3] = TCG_COND_LTU,
1315 [9] = TCG_COND_NE,
1316 [10] = TCG_COND_GE,
1317 [11] = TCG_COND_GEU,
1318 };
1319 gen_brcond(dc, cond[RRI8_R], cpu_R[RRI8_S], cpu_R[RRI8_T],
1320 4 + RRI8_IMM8_SE);
1321 }
1322 break;
1323
1324 case 4: /*BALL*/ /*BNALL*/
1325 {
1326 TCGv_i32 tmp = tcg_temp_new_i32();
1327 tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);
1328 gen_brcond(dc, eq_ne, tmp, cpu_R[RRI8_T],
1329 4 + RRI8_IMM8_SE);
1330 tcg_temp_free(tmp);
1331 }
1332 break;
1333
1334 case 5: /*BBC*/ /*BBS*/
1335 {
1336 TCGv_i32 bit = tcg_const_i32(1);
1337 TCGv_i32 tmp = tcg_temp_new_i32();
1338 tcg_gen_andi_i32(tmp, cpu_R[RRI8_T], 0x1f);
1339 tcg_gen_shl_i32(bit, bit, tmp);
1340 tcg_gen_and_i32(tmp, cpu_R[RRI8_S], bit);
1341 gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);
1342 tcg_temp_free(tmp);
1343 tcg_temp_free(bit);
1344 }
1345 break;
1346
1347 case 6: /*BBCI*/ /*BBSI*/
1348 case 7:
1349 {
1350 TCGv_i32 tmp = tcg_temp_new_i32();
1351 tcg_gen_andi_i32(tmp, cpu_R[RRI8_S],
1352 1 << (((RRI8_R & 1) << 4) | RRI8_T));
1353 gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);
1354 tcg_temp_free(tmp);
1355 }
1356 break;
1357
1358 }
1359 }
dedc5eae
MF
1360 break;
1361
67882fd1
MF
1362#define gen_narrow_load_store(type) do { \
1363 TCGv_i32 addr = tcg_temp_new_i32(); \
1364 tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \
f0a548b9 1365 tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, dc->cring); \
67882fd1
MF
1366 tcg_temp_free(addr); \
1367 } while (0)
1368
dedc5eae 1369 case 8: /*L32I.Nn*/
67882fd1 1370 gen_narrow_load_store(ld32u);
dedc5eae
MF
1371 break;
1372
1373 case 9: /*S32I.Nn*/
67882fd1 1374 gen_narrow_load_store(st32);
dedc5eae 1375 break;
67882fd1 1376#undef gen_narrow_load_store
dedc5eae
MF
1377
1378 case 10: /*ADD.Nn*/
67882fd1 1379 tcg_gen_add_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], cpu_R[RRRN_T]);
dedc5eae
MF
1380 break;
1381
1382 case 11: /*ADDI.Nn*/
67882fd1 1383 tcg_gen_addi_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], RRRN_T ? RRRN_T : -1);
dedc5eae
MF
1384 break;
1385
1386 case 12: /*ST2n*/
67882fd1
MF
1387 if (RRRN_T < 8) { /*MOVI.Nn*/
1388 tcg_gen_movi_i32(cpu_R[RRRN_S],
1389 RRRN_R | (RRRN_T << 4) |
1390 ((RRRN_T & 6) == 6 ? 0xffffff80 : 0));
1391 } else { /*BEQZ.Nn*/ /*BNEZ.Nn*/
bd57fb91
MF
1392 TCGCond eq_ne = (RRRN_T & 4) ? TCG_COND_NE : TCG_COND_EQ;
1393
1394 gen_brcondi(dc, eq_ne, cpu_R[RRRN_S], 0,
1395 4 + (RRRN_R | ((RRRN_T & 3) << 4)));
67882fd1 1396 }
dedc5eae
MF
1397 break;
1398
1399 case 13: /*ST3n*/
67882fd1
MF
1400 switch (RRRN_R) {
1401 case 0: /*MOV.Nn*/
1402 tcg_gen_mov_i32(cpu_R[RRRN_T], cpu_R[RRRN_S]);
1403 break;
1404
1405 case 15: /*S3*/
1406 switch (RRRN_T) {
1407 case 0: /*RET.Nn*/
1408 gen_jump(dc, cpu_R[0]);
1409 break;
1410
1411 case 1: /*RETW.Nn*/
91a5bb76
MF
1412 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
1413 TBD();
67882fd1
MF
1414 break;
1415
1416 case 2: /*BREAK.Nn*/
91a5bb76 1417 TBD();
67882fd1
MF
1418 break;
1419
1420 case 3: /*NOP.Nn*/
1421 break;
1422
1423 case 6: /*ILL.Nn*/
91a5bb76 1424 TBD();
67882fd1
MF
1425 break;
1426
1427 default: /*reserved*/
91a5bb76 1428 RESERVED();
67882fd1
MF
1429 break;
1430 }
1431 break;
1432
1433 default: /*reserved*/
91a5bb76 1434 RESERVED();
67882fd1
MF
1435 break;
1436 }
dedc5eae
MF
1437 break;
1438
1439 default: /*reserved*/
91a5bb76 1440 RESERVED();
dedc5eae
MF
1441 break;
1442 }
1443
1444 dc->pc = dc->next_pc;
1445 return;
1446
1447invalid_opcode:
1448 qemu_log("INVALID(pc = %08x)\n", dc->pc);
1449 dc->pc = dc->next_pc;
1450#undef HAS_OPTION
1451}
1452
1453static void check_breakpoint(CPUState *env, DisasContext *dc)
1454{
1455 CPUBreakpoint *bp;
1456
1457 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
1458 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1459 if (bp->pc == dc->pc) {
1460 tcg_gen_movi_i32(cpu_pc, dc->pc);
1461 gen_exception(EXCP_DEBUG);
1462 dc->is_jmp = DISAS_UPDATE;
1463 }
1464 }
1465 }
1466}
1467
1468static void gen_intermediate_code_internal(
1469 CPUState *env, TranslationBlock *tb, int search_pc)
1470{
1471 DisasContext dc;
1472 int insn_count = 0;
1473 int j, lj = -1;
1474 uint16_t *gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1475 int max_insns = tb->cflags & CF_COUNT_MASK;
1476 uint32_t pc_start = tb->pc;
1477 uint32_t next_page_start =
1478 (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
1479
1480 if (max_insns == 0) {
1481 max_insns = CF_COUNT_MASK;
1482 }
1483
1484 dc.config = env->config;
1485 dc.singlestep_enabled = env->singlestep_enabled;
1486 dc.tb = tb;
1487 dc.pc = pc_start;
f0a548b9
MF
1488 dc.ring = tb->flags & XTENSA_TBFLAG_RING_MASK;
1489 dc.cring = (tb->flags & XTENSA_TBFLAG_EXCM) ? 0 : dc.ring;
dedc5eae
MF
1490 dc.is_jmp = DISAS_NEXT;
1491
3580ecad
MF
1492 init_sar_tracker(&dc);
1493
dedc5eae
MF
1494 gen_icount_start();
1495
1496 do {
1497 check_breakpoint(env, &dc);
1498
1499 if (search_pc) {
1500 j = gen_opc_ptr - gen_opc_buf;
1501 if (lj < j) {
1502 lj++;
1503 while (lj < j) {
1504 gen_opc_instr_start[lj++] = 0;
1505 }
1506 }
1507 gen_opc_pc[lj] = dc.pc;
1508 gen_opc_instr_start[lj] = 1;
1509 gen_opc_icount[lj] = insn_count;
1510 }
1511
1512 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
1513 tcg_gen_debug_insn_start(dc.pc);
1514 }
1515
1516 disas_xtensa_insn(&dc);
1517 ++insn_count;
1518 if (env->singlestep_enabled) {
1519 tcg_gen_movi_i32(cpu_pc, dc.pc);
1520 gen_exception(EXCP_DEBUG);
1521 break;
1522 }
1523 } while (dc.is_jmp == DISAS_NEXT &&
1524 insn_count < max_insns &&
1525 dc.pc < next_page_start &&
1526 gen_opc_ptr < gen_opc_end);
1527
3580ecad
MF
1528 reset_sar_tracker(&dc);
1529
dedc5eae
MF
1530 if (dc.is_jmp == DISAS_NEXT) {
1531 gen_jumpi(&dc, dc.pc, 0);
1532 }
1533 gen_icount_end(tb, insn_count);
1534 *gen_opc_ptr = INDEX_op_end;
1535
1536 if (!search_pc) {
1537 tb->size = dc.pc - pc_start;
1538 tb->icount = insn_count;
1539 }
2328826b
MF
1540}
1541
1542void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
1543{
dedc5eae 1544 gen_intermediate_code_internal(env, tb, 0);
2328826b
MF
1545}
1546
1547void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
1548{
dedc5eae 1549 gen_intermediate_code_internal(env, tb, 1);
2328826b
MF
1550}
1551
1552void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
1553 int flags)
1554{
2af3da91
MF
1555 int i, j;
1556
1557 cpu_fprintf(f, "PC=%08x\n\n", env->pc);
1558
1559 for (i = j = 0; i < 256; ++i) {
1560 if (sregnames[i]) {
1561 cpu_fprintf(f, "%s=%08x%c", sregnames[i], env->sregs[i],
1562 (j++ % 4) == 3 ? '\n' : ' ');
1563 }
1564 }
1565
1566 cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
1567
1568 for (i = j = 0; i < 256; ++i) {
1569 if (uregnames[i]) {
1570 cpu_fprintf(f, "%s=%08x%c", uregnames[i], env->uregs[i],
1571 (j++ % 4) == 3 ? '\n' : ' ');
1572 }
1573 }
2328826b 1574
2af3da91 1575 cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
2328826b
MF
1576
1577 for (i = 0; i < 16; ++i) {
1578 cpu_fprintf(f, "A%02d=%08x%c", i, env->regs[i],
1579 (i % 4) == 3 ? '\n' : ' ');
1580 }
1581}
1582
1583void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
1584{
1585 env->pc = gen_opc_pc[pc_pos];
1586}