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