]> git.proxmox.com Git - qemu.git/blame - target-xtensa/translate.c
target-xtensa: implement RST3 group
[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;
48 int is_jmp;
49 int singlestep_enabled;
50} DisasContext;
51
52static TCGv_ptr cpu_env;
53static TCGv_i32 cpu_pc;
54static TCGv_i32 cpu_R[16];
2af3da91
MF
55static TCGv_i32 cpu_SR[256];
56static TCGv_i32 cpu_UR[256];
dedc5eae
MF
57
58#include "gen-icount.h"
2328826b 59
2af3da91
MF
60static const char * const sregnames[256] = {
61};
62
63static const char * const uregnames[256] = {
64 [THREADPTR] = "THREADPTR",
65 [FCR] = "FCR",
66 [FSR] = "FSR",
67};
68
2328826b
MF
69void xtensa_translate_init(void)
70{
dedc5eae
MF
71 static const char * const regnames[] = {
72 "ar0", "ar1", "ar2", "ar3",
73 "ar4", "ar5", "ar6", "ar7",
74 "ar8", "ar9", "ar10", "ar11",
75 "ar12", "ar13", "ar14", "ar15",
76 };
77 int i;
78
79 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
80 cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
81 offsetof(CPUState, pc), "pc");
82
83 for (i = 0; i < 16; i++) {
84 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
85 offsetof(CPUState, regs[i]),
86 regnames[i]);
87 }
2af3da91
MF
88
89 for (i = 0; i < 256; ++i) {
90 if (sregnames[i]) {
91 cpu_SR[i] = tcg_global_mem_new_i32(TCG_AREG0,
92 offsetof(CPUState, sregs[i]),
93 sregnames[i]);
94 }
95 }
96
97 for (i = 0; i < 256; ++i) {
98 if (uregnames[i]) {
99 cpu_UR[i] = tcg_global_mem_new_i32(TCG_AREG0,
100 offsetof(CPUState, uregs[i]),
101 uregnames[i]);
102 }
103 }
dedc5eae
MF
104#define GEN_HELPER 2
105#include "helpers.h"
106}
107
108static inline bool option_enabled(DisasContext *dc, int opt)
109{
110 return xtensa_option_enabled(dc->config, opt);
111}
112
113static void gen_exception(int excp)
114{
115 TCGv_i32 tmp = tcg_const_i32(excp);
116 gen_helper_exception(tmp);
117 tcg_temp_free(tmp);
118}
119
120static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
121{
122 tcg_gen_mov_i32(cpu_pc, dest);
123 if (dc->singlestep_enabled) {
124 gen_exception(EXCP_DEBUG);
125 } else {
126 if (slot >= 0) {
127 tcg_gen_goto_tb(slot);
128 tcg_gen_exit_tb((tcg_target_long)dc->tb + slot);
129 } else {
130 tcg_gen_exit_tb(0);
131 }
132 }
133 dc->is_jmp = DISAS_UPDATE;
134}
135
67882fd1
MF
136static void gen_jump(DisasContext *dc, TCGv dest)
137{
138 gen_jump_slot(dc, dest, -1);
139}
140
dedc5eae
MF
141static void gen_jumpi(DisasContext *dc, uint32_t dest, int slot)
142{
143 TCGv_i32 tmp = tcg_const_i32(dest);
144 if (((dc->pc ^ dest) & TARGET_PAGE_MASK) != 0) {
145 slot = -1;
146 }
147 gen_jump_slot(dc, tmp, slot);
148 tcg_temp_free(tmp);
149}
150
bd57fb91
MF
151static void gen_brcond(DisasContext *dc, TCGCond cond,
152 TCGv_i32 t0, TCGv_i32 t1, uint32_t offset)
153{
154 int label = gen_new_label();
155
156 tcg_gen_brcond_i32(cond, t0, t1, label);
157 gen_jumpi(dc, dc->next_pc, 0);
158 gen_set_label(label);
159 gen_jumpi(dc, dc->pc + offset, 1);
160}
161
162static void gen_brcondi(DisasContext *dc, TCGCond cond,
163 TCGv_i32 t0, uint32_t t1, uint32_t offset)
164{
165 TCGv_i32 tmp = tcg_const_i32(t1);
166 gen_brcond(dc, cond, t0, tmp, offset);
167 tcg_temp_free(tmp);
168}
169
b8132eff
MF
170static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
171{
172 static void (* const rsr_handler[256])(DisasContext *dc,
173 TCGv_i32 d, uint32_t sr) = {
174 };
175
176 if (sregnames[sr]) {
177 if (rsr_handler[sr]) {
178 rsr_handler[sr](dc, d, sr);
179 } else {
180 tcg_gen_mov_i32(d, cpu_SR[sr]);
181 }
182 } else {
183 qemu_log("RSR %d not implemented, ", sr);
184 }
185}
186
187static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
188{
189 static void (* const wsr_handler[256])(DisasContext *dc,
190 uint32_t sr, TCGv_i32 v) = {
191 };
192
193 if (sregnames[sr]) {
194 if (wsr_handler[sr]) {
195 wsr_handler[sr](dc, sr, s);
196 } else {
197 tcg_gen_mov_i32(cpu_SR[sr], s);
198 }
199 } else {
200 qemu_log("WSR %d not implemented, ", sr);
201 }
202}
203
dedc5eae
MF
204static void disas_xtensa_insn(DisasContext *dc)
205{
206#define HAS_OPTION(opt) do { \
207 if (!option_enabled(dc, opt)) { \
208 qemu_log("Option %d is not enabled %s:%d\n", \
209 (opt), __FILE__, __LINE__); \
210 goto invalid_opcode; \
211 } \
212 } while (0)
213
214#ifdef TARGET_WORDS_BIGENDIAN
215#define OP0 (((b0) & 0xf0) >> 4)
216#define OP1 (((b2) & 0xf0) >> 4)
217#define OP2 ((b2) & 0xf)
218#define RRR_R ((b1) & 0xf)
219#define RRR_S (((b1) & 0xf0) >> 4)
220#define RRR_T ((b0) & 0xf)
221#else
222#define OP0 (((b0) & 0xf))
223#define OP1 (((b2) & 0xf))
224#define OP2 (((b2) & 0xf0) >> 4)
225#define RRR_R (((b1) & 0xf0) >> 4)
226#define RRR_S (((b1) & 0xf))
227#define RRR_T (((b0) & 0xf0) >> 4)
228#endif
229
230#define RRRN_R RRR_R
231#define RRRN_S RRR_S
232#define RRRN_T RRR_T
233
234#define RRI8_R RRR_R
235#define RRI8_S RRR_S
236#define RRI8_T RRR_T
237#define RRI8_IMM8 (b2)
238#define RRI8_IMM8_SE ((((b2) & 0x80) ? 0xffffff00 : 0) | RRI8_IMM8)
239
240#ifdef TARGET_WORDS_BIGENDIAN
241#define RI16_IMM16 (((b1) << 8) | (b2))
242#else
243#define RI16_IMM16 (((b2) << 8) | (b1))
244#endif
245
246#ifdef TARGET_WORDS_BIGENDIAN
247#define CALL_N (((b0) & 0xc) >> 2)
248#define CALL_OFFSET ((((b0) & 0x3) << 16) | ((b1) << 8) | (b2))
249#else
250#define CALL_N (((b0) & 0x30) >> 4)
251#define CALL_OFFSET ((((b0) & 0xc0) >> 6) | ((b1) << 2) | ((b2) << 10))
252#endif
253#define CALL_OFFSET_SE \
254 (((CALL_OFFSET & 0x20000) ? 0xfffc0000 : 0) | CALL_OFFSET)
255
256#define CALLX_N CALL_N
257#ifdef TARGET_WORDS_BIGENDIAN
258#define CALLX_M ((b0) & 0x3)
259#else
260#define CALLX_M (((b0) & 0xc0) >> 6)
261#endif
262#define CALLX_S RRR_S
263
264#define BRI12_M CALLX_M
265#define BRI12_S RRR_S
266#ifdef TARGET_WORDS_BIGENDIAN
267#define BRI12_IMM12 ((((b1) & 0xf) << 8) | (b2))
268#else
269#define BRI12_IMM12 ((((b1) & 0xf0) >> 4) | ((b2) << 4))
270#endif
271#define BRI12_IMM12_SE (((BRI12_IMM12 & 0x800) ? 0xfffff000 : 0) | BRI12_IMM12)
272
273#define BRI8_M BRI12_M
274#define BRI8_R RRI8_R
275#define BRI8_S RRI8_S
276#define BRI8_IMM8 RRI8_IMM8
277#define BRI8_IMM8_SE RRI8_IMM8_SE
278
279#define RSR_SR (b1)
280
281 uint8_t b0 = ldub_code(dc->pc);
282 uint8_t b1 = ldub_code(dc->pc + 1);
283 uint8_t b2 = ldub_code(dc->pc + 2);
284
bd57fb91
MF
285 static const uint32_t B4CONST[] = {
286 0xffffffff, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
287 };
288
289 static const uint32_t B4CONSTU[] = {
290 32768, 65536, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
291 };
292
dedc5eae
MF
293 if (OP0 >= 8) {
294 dc->next_pc = dc->pc + 2;
295 HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);
296 } else {
297 dc->next_pc = dc->pc + 3;
298 }
299
300 switch (OP0) {
301 case 0: /*QRST*/
302 switch (OP1) {
303 case 0: /*RST0*/
304 switch (OP2) {
305 case 0: /*ST0*/
306 if ((RRR_R & 0xc) == 0x8) {
307 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
308 }
309
310 switch (RRR_R) {
311 case 0: /*SNM0*/
5da4a6a8
MF
312 switch (CALLX_M) {
313 case 0: /*ILL*/
314 break;
315
316 case 1: /*reserved*/
317 break;
318
319 case 2: /*JR*/
320 switch (CALLX_N) {
321 case 0: /*RET*/
322 case 2: /*JX*/
323 gen_jump(dc, cpu_R[CALLX_S]);
324 break;
325
326 case 1: /*RETWw*/
327 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
328 break;
329
330 case 3: /*reserved*/
331 break;
332 }
333 break;
334
335 case 3: /*CALLX*/
336 switch (CALLX_N) {
337 case 0: /*CALLX0*/
338 {
339 TCGv_i32 tmp = tcg_temp_new_i32();
340 tcg_gen_mov_i32(tmp, cpu_R[CALLX_S]);
341 tcg_gen_movi_i32(cpu_R[0], dc->next_pc);
342 gen_jump(dc, tmp);
343 tcg_temp_free(tmp);
344 }
345 break;
346
347 case 1: /*CALLX4w*/
348 case 2: /*CALLX8w*/
349 case 3: /*CALLX12w*/
350 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
351 break;
352 }
353 break;
354 }
dedc5eae
MF
355 break;
356
357 case 1: /*MOVSPw*/
358 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
359 break;
360
361 case 2: /*SYNC*/
362 break;
363
364 case 3:
365 break;
366
367 }
368 break;
369
370 case 1: /*AND*/
371 tcg_gen_and_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
372 break;
373
374 case 2: /*OR*/
375 tcg_gen_or_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
376 break;
377
378 case 3: /*XOR*/
379 tcg_gen_xor_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
380 break;
381
382 case 4: /*ST1*/
383 break;
384
385 case 5: /*TLB*/
386 break;
387
388 case 6: /*RT0*/
f331fe5e
MF
389 switch (RRR_S) {
390 case 0: /*NEG*/
391 tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
392 break;
393
394 case 1: /*ABS*/
395 {
396 int label = gen_new_label();
397 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
398 tcg_gen_brcondi_i32(
399 TCG_COND_GE, cpu_R[RRR_R], 0, label);
400 tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
401 gen_set_label(label);
402 }
403 break;
404
405 default: /*reserved*/
406 break;
407 }
dedc5eae
MF
408 break;
409
410 case 7: /*reserved*/
411 break;
412
413 case 8: /*ADD*/
414 tcg_gen_add_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
415 break;
416
417 case 9: /*ADD**/
418 case 10:
419 case 11:
420 {
421 TCGv_i32 tmp = tcg_temp_new_i32();
422 tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 8);
423 tcg_gen_add_i32(cpu_R[RRR_R], tmp, cpu_R[RRR_T]);
424 tcg_temp_free(tmp);
425 }
426 break;
427
428 case 12: /*SUB*/
429 tcg_gen_sub_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
430 break;
431
432 case 13: /*SUB**/
433 case 14:
434 case 15:
435 {
436 TCGv_i32 tmp = tcg_temp_new_i32();
437 tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 12);
438 tcg_gen_sub_i32(cpu_R[RRR_R], tmp, cpu_R[RRR_T]);
439 tcg_temp_free(tmp);
440 }
441 break;
442 }
443 break;
444
445 case 1: /*RST1*/
446 break;
447
448 case 2: /*RST2*/
449 break;
450
451 case 3: /*RST3*/
b8132eff
MF
452 switch (OP2) {
453 case 0: /*RSR*/
454 gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
455 break;
456
457 case 1: /*WSR*/
458 gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);
459 break;
460
461 case 2: /*SEXTu*/
462 HAS_OPTION(XTENSA_OPTION_MISC_OP);
463 {
464 int shift = 24 - RRR_T;
465
466 if (shift == 24) {
467 tcg_gen_ext8s_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
468 } else if (shift == 16) {
469 tcg_gen_ext16s_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
470 } else {
471 TCGv_i32 tmp = tcg_temp_new_i32();
472 tcg_gen_shli_i32(tmp, cpu_R[RRR_S], shift);
473 tcg_gen_sari_i32(cpu_R[RRR_R], tmp, shift);
474 tcg_temp_free(tmp);
475 }
476 }
477 break;
478
479 case 3: /*CLAMPSu*/
480 HAS_OPTION(XTENSA_OPTION_MISC_OP);
481 {
482 TCGv_i32 tmp1 = tcg_temp_new_i32();
483 TCGv_i32 tmp2 = tcg_temp_new_i32();
484 int label = gen_new_label();
485
486 tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 24 - RRR_T);
487 tcg_gen_xor_i32(tmp2, tmp1, cpu_R[RRR_S]);
488 tcg_gen_andi_i32(tmp2, tmp2, 0xffffffff << (RRR_T + 7));
489 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
490 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp2, 0, label);
491
492 tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 31);
493 tcg_gen_xori_i32(cpu_R[RRR_R], tmp1,
494 0xffffffff >> (25 - RRR_T));
495
496 gen_set_label(label);
497
498 tcg_temp_free(tmp1);
499 tcg_temp_free(tmp2);
500 }
501 break;
502
503 case 4: /*MINu*/
504 case 5: /*MAXu*/
505 case 6: /*MINUu*/
506 case 7: /*MAXUu*/
507 HAS_OPTION(XTENSA_OPTION_MISC_OP);
508 {
509 static const TCGCond cond[] = {
510 TCG_COND_LE,
511 TCG_COND_GE,
512 TCG_COND_LEU,
513 TCG_COND_GEU
514 };
515 int label = gen_new_label();
516
517 if (RRR_R != RRR_T) {
518 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
519 tcg_gen_brcond_i32(cond[OP2 - 4],
520 cpu_R[RRR_S], cpu_R[RRR_T], label);
521 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
522 } else {
523 tcg_gen_brcond_i32(cond[OP2 - 4],
524 cpu_R[RRR_T], cpu_R[RRR_S], label);
525 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
526 }
527 gen_set_label(label);
528 }
529 break;
530
531 case 8: /*MOVEQZ*/
532 case 9: /*MOVNEZ*/
533 case 10: /*MOVLTZ*/
534 case 11: /*MOVGEZ*/
535 {
536 static const TCGCond cond[] = {
537 TCG_COND_NE,
538 TCG_COND_EQ,
539 TCG_COND_GE,
540 TCG_COND_LT
541 };
542 int label = gen_new_label();
543 tcg_gen_brcondi_i32(cond[OP2 - 8], cpu_R[RRR_T], 0, label);
544 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
545 gen_set_label(label);
546 }
547 break;
548
549 case 12: /*MOVFp*/
550 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
551 break;
552
553 case 13: /*MOVTp*/
554 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
555 break;
556
557 case 14: /*RUR*/
558 {
559 int st = (RRR_S << 4) + RRR_T;
560 if (uregnames[st]) {
561 tcg_gen_mov_i32(cpu_R[RRR_R], cpu_UR[st]);
562 } else {
563 qemu_log("RUR %d not implemented, ", st);
564 }
565 }
566 break;
567
568 case 15: /*WUR*/
569 {
570 if (uregnames[RSR_SR]) {
571 tcg_gen_mov_i32(cpu_UR[RSR_SR], cpu_R[RRR_T]);
572 } else {
573 qemu_log("WUR %d not implemented, ", RSR_SR);
574 }
575 }
576 break;
577
578 }
dedc5eae
MF
579 break;
580
581 case 4: /*EXTUI*/
582 case 5:
583 break;
584
585 case 6: /*CUST0*/
586 break;
587
588 case 7: /*CUST1*/
589 break;
590
591 case 8: /*LSCXp*/
592 HAS_OPTION(XTENSA_OPTION_COPROCESSOR);
593 break;
594
595 case 9: /*LSC4*/
596 break;
597
598 case 10: /*FP0*/
599 HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
600 break;
601
602 case 11: /*FP1*/
603 HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
604 break;
605
606 default: /*reserved*/
607 break;
608 }
609 break;
610
611 case 1: /*L32R*/
612 {
613 TCGv_i32 tmp = tcg_const_i32(
614 (0xfffc0000 | (RI16_IMM16 << 2)) +
615 ((dc->pc + 3) & ~3));
616
617 /* no ext L32R */
618
619 tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, 0);
620 tcg_temp_free(tmp);
621 }
622 break;
623
624 case 2: /*LSAI*/
625 break;
626
627 case 3: /*LSCIp*/
628 HAS_OPTION(XTENSA_OPTION_COPROCESSOR);
629 break;
630
631 case 4: /*MAC16d*/
632 HAS_OPTION(XTENSA_OPTION_MAC16);
633 break;
634
635 case 5: /*CALLN*/
636 switch (CALL_N) {
637 case 0: /*CALL0*/
638 tcg_gen_movi_i32(cpu_R[0], dc->next_pc);
639 gen_jumpi(dc, (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4, 0);
640 break;
641
642 case 1: /*CALL4w*/
643 case 2: /*CALL8w*/
644 case 3: /*CALL12w*/
645 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
646 break;
647 }
648 break;
649
650 case 6: /*SI*/
651 switch (CALL_N) {
652 case 0: /*J*/
653 gen_jumpi(dc, dc->pc + 4 + CALL_OFFSET_SE, 0);
654 break;
655
bd57fb91
MF
656 case 1: /*BZ*/
657 {
658 static const TCGCond cond[] = {
659 TCG_COND_EQ, /*BEQZ*/
660 TCG_COND_NE, /*BNEZ*/
661 TCG_COND_LT, /*BLTZ*/
662 TCG_COND_GE, /*BGEZ*/
663 };
664
665 gen_brcondi(dc, cond[BRI12_M & 3], cpu_R[BRI12_S], 0,
666 4 + BRI12_IMM12_SE);
667 }
668 break;
669
670 case 2: /*BI0*/
671 {
672 static const TCGCond cond[] = {
673 TCG_COND_EQ, /*BEQI*/
674 TCG_COND_NE, /*BNEI*/
675 TCG_COND_LT, /*BLTI*/
676 TCG_COND_GE, /*BGEI*/
677 };
678
679 gen_brcondi(dc, cond[BRI8_M & 3],
680 cpu_R[BRI8_S], B4CONST[BRI8_R], 4 + BRI8_IMM8_SE);
681 }
682 break;
683
684 case 3: /*BI1*/
685 switch (BRI8_M) {
686 case 0: /*ENTRYw*/
687 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
688 break;
689
690 case 1: /*B1*/
691 switch (BRI8_R) {
692 case 0: /*BFp*/
693 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
694 break;
695
696 case 1: /*BTp*/
697 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
698 break;
699
700 case 8: /*LOOP*/
701 break;
702
703 case 9: /*LOOPNEZ*/
704 break;
705
706 case 10: /*LOOPGTZ*/
707 break;
708
709 default: /*reserved*/
710 break;
711
712 }
713 break;
714
715 case 2: /*BLTUI*/
716 case 3: /*BGEUI*/
717 gen_brcondi(dc, BRI8_M == 2 ? TCG_COND_LTU : TCG_COND_GEU,
718 cpu_R[BRI8_S], B4CONSTU[BRI8_R], 4 + BRI8_IMM8_SE);
719 break;
720 }
721 break;
722
dedc5eae
MF
723 }
724 break;
725
726 case 7: /*B*/
bd57fb91
MF
727 {
728 TCGCond eq_ne = (RRI8_R & 8) ? TCG_COND_NE : TCG_COND_EQ;
729
730 switch (RRI8_R & 7) {
731 case 0: /*BNONE*/ /*BANY*/
732 {
733 TCGv_i32 tmp = tcg_temp_new_i32();
734 tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);
735 gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);
736 tcg_temp_free(tmp);
737 }
738 break;
739
740 case 1: /*BEQ*/ /*BNE*/
741 case 2: /*BLT*/ /*BGE*/
742 case 3: /*BLTU*/ /*BGEU*/
743 {
744 static const TCGCond cond[] = {
745 [1] = TCG_COND_EQ,
746 [2] = TCG_COND_LT,
747 [3] = TCG_COND_LTU,
748 [9] = TCG_COND_NE,
749 [10] = TCG_COND_GE,
750 [11] = TCG_COND_GEU,
751 };
752 gen_brcond(dc, cond[RRI8_R], cpu_R[RRI8_S], cpu_R[RRI8_T],
753 4 + RRI8_IMM8_SE);
754 }
755 break;
756
757 case 4: /*BALL*/ /*BNALL*/
758 {
759 TCGv_i32 tmp = tcg_temp_new_i32();
760 tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);
761 gen_brcond(dc, eq_ne, tmp, cpu_R[RRI8_T],
762 4 + RRI8_IMM8_SE);
763 tcg_temp_free(tmp);
764 }
765 break;
766
767 case 5: /*BBC*/ /*BBS*/
768 {
769 TCGv_i32 bit = tcg_const_i32(1);
770 TCGv_i32 tmp = tcg_temp_new_i32();
771 tcg_gen_andi_i32(tmp, cpu_R[RRI8_T], 0x1f);
772 tcg_gen_shl_i32(bit, bit, tmp);
773 tcg_gen_and_i32(tmp, cpu_R[RRI8_S], bit);
774 gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);
775 tcg_temp_free(tmp);
776 tcg_temp_free(bit);
777 }
778 break;
779
780 case 6: /*BBCI*/ /*BBSI*/
781 case 7:
782 {
783 TCGv_i32 tmp = tcg_temp_new_i32();
784 tcg_gen_andi_i32(tmp, cpu_R[RRI8_S],
785 1 << (((RRI8_R & 1) << 4) | RRI8_T));
786 gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);
787 tcg_temp_free(tmp);
788 }
789 break;
790
791 }
792 }
dedc5eae
MF
793 break;
794
67882fd1
MF
795#define gen_narrow_load_store(type) do { \
796 TCGv_i32 addr = tcg_temp_new_i32(); \
797 tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \
798 tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, 0); \
799 tcg_temp_free(addr); \
800 } while (0)
801
dedc5eae 802 case 8: /*L32I.Nn*/
67882fd1 803 gen_narrow_load_store(ld32u);
dedc5eae
MF
804 break;
805
806 case 9: /*S32I.Nn*/
67882fd1 807 gen_narrow_load_store(st32);
dedc5eae 808 break;
67882fd1 809#undef gen_narrow_load_store
dedc5eae
MF
810
811 case 10: /*ADD.Nn*/
67882fd1 812 tcg_gen_add_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], cpu_R[RRRN_T]);
dedc5eae
MF
813 break;
814
815 case 11: /*ADDI.Nn*/
67882fd1 816 tcg_gen_addi_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], RRRN_T ? RRRN_T : -1);
dedc5eae
MF
817 break;
818
819 case 12: /*ST2n*/
67882fd1
MF
820 if (RRRN_T < 8) { /*MOVI.Nn*/
821 tcg_gen_movi_i32(cpu_R[RRRN_S],
822 RRRN_R | (RRRN_T << 4) |
823 ((RRRN_T & 6) == 6 ? 0xffffff80 : 0));
824 } else { /*BEQZ.Nn*/ /*BNEZ.Nn*/
bd57fb91
MF
825 TCGCond eq_ne = (RRRN_T & 4) ? TCG_COND_NE : TCG_COND_EQ;
826
827 gen_brcondi(dc, eq_ne, cpu_R[RRRN_S], 0,
828 4 + (RRRN_R | ((RRRN_T & 3) << 4)));
67882fd1 829 }
dedc5eae
MF
830 break;
831
832 case 13: /*ST3n*/
67882fd1
MF
833 switch (RRRN_R) {
834 case 0: /*MOV.Nn*/
835 tcg_gen_mov_i32(cpu_R[RRRN_T], cpu_R[RRRN_S]);
836 break;
837
838 case 15: /*S3*/
839 switch (RRRN_T) {
840 case 0: /*RET.Nn*/
841 gen_jump(dc, cpu_R[0]);
842 break;
843
844 case 1: /*RETW.Nn*/
845 break;
846
847 case 2: /*BREAK.Nn*/
848 break;
849
850 case 3: /*NOP.Nn*/
851 break;
852
853 case 6: /*ILL.Nn*/
854 break;
855
856 default: /*reserved*/
857 break;
858 }
859 break;
860
861 default: /*reserved*/
862 break;
863 }
dedc5eae
MF
864 break;
865
866 default: /*reserved*/
867 break;
868 }
869
870 dc->pc = dc->next_pc;
871 return;
872
873invalid_opcode:
874 qemu_log("INVALID(pc = %08x)\n", dc->pc);
875 dc->pc = dc->next_pc;
876#undef HAS_OPTION
877}
878
879static void check_breakpoint(CPUState *env, DisasContext *dc)
880{
881 CPUBreakpoint *bp;
882
883 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
884 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
885 if (bp->pc == dc->pc) {
886 tcg_gen_movi_i32(cpu_pc, dc->pc);
887 gen_exception(EXCP_DEBUG);
888 dc->is_jmp = DISAS_UPDATE;
889 }
890 }
891 }
892}
893
894static void gen_intermediate_code_internal(
895 CPUState *env, TranslationBlock *tb, int search_pc)
896{
897 DisasContext dc;
898 int insn_count = 0;
899 int j, lj = -1;
900 uint16_t *gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
901 int max_insns = tb->cflags & CF_COUNT_MASK;
902 uint32_t pc_start = tb->pc;
903 uint32_t next_page_start =
904 (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
905
906 if (max_insns == 0) {
907 max_insns = CF_COUNT_MASK;
908 }
909
910 dc.config = env->config;
911 dc.singlestep_enabled = env->singlestep_enabled;
912 dc.tb = tb;
913 dc.pc = pc_start;
914 dc.is_jmp = DISAS_NEXT;
915
916 gen_icount_start();
917
918 do {
919 check_breakpoint(env, &dc);
920
921 if (search_pc) {
922 j = gen_opc_ptr - gen_opc_buf;
923 if (lj < j) {
924 lj++;
925 while (lj < j) {
926 gen_opc_instr_start[lj++] = 0;
927 }
928 }
929 gen_opc_pc[lj] = dc.pc;
930 gen_opc_instr_start[lj] = 1;
931 gen_opc_icount[lj] = insn_count;
932 }
933
934 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
935 tcg_gen_debug_insn_start(dc.pc);
936 }
937
938 disas_xtensa_insn(&dc);
939 ++insn_count;
940 if (env->singlestep_enabled) {
941 tcg_gen_movi_i32(cpu_pc, dc.pc);
942 gen_exception(EXCP_DEBUG);
943 break;
944 }
945 } while (dc.is_jmp == DISAS_NEXT &&
946 insn_count < max_insns &&
947 dc.pc < next_page_start &&
948 gen_opc_ptr < gen_opc_end);
949
950 if (dc.is_jmp == DISAS_NEXT) {
951 gen_jumpi(&dc, dc.pc, 0);
952 }
953 gen_icount_end(tb, insn_count);
954 *gen_opc_ptr = INDEX_op_end;
955
956 if (!search_pc) {
957 tb->size = dc.pc - pc_start;
958 tb->icount = insn_count;
959 }
2328826b
MF
960}
961
962void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
963{
dedc5eae 964 gen_intermediate_code_internal(env, tb, 0);
2328826b
MF
965}
966
967void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
968{
dedc5eae 969 gen_intermediate_code_internal(env, tb, 1);
2328826b
MF
970}
971
972void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
973 int flags)
974{
2af3da91
MF
975 int i, j;
976
977 cpu_fprintf(f, "PC=%08x\n\n", env->pc);
978
979 for (i = j = 0; i < 256; ++i) {
980 if (sregnames[i]) {
981 cpu_fprintf(f, "%s=%08x%c", sregnames[i], env->sregs[i],
982 (j++ % 4) == 3 ? '\n' : ' ');
983 }
984 }
985
986 cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
987
988 for (i = j = 0; i < 256; ++i) {
989 if (uregnames[i]) {
990 cpu_fprintf(f, "%s=%08x%c", uregnames[i], env->uregs[i],
991 (j++ % 4) == 3 ? '\n' : ' ');
992 }
993 }
2328826b 994
2af3da91 995 cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
2328826b
MF
996
997 for (i = 0; i < 16; ++i) {
998 cpu_fprintf(f, "A%02d=%08x%c", i, env->regs[i],
999 (i % 4) == 3 ? '\n' : ' ');
1000 }
1001}
1002
1003void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
1004{
1005 env->pc = gen_opc_pc[pc_pos];
1006}