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