Relax qemu_ld/st constraints for !SOFTMMU case
[qemu/mini2440.git] / target-alpha / translate.c
blobd3c45007f3df3fae2c883e548eda188ffac21245
1 /*
2 * Alpha emulation cpu translation for qemu.
4 * Copyright (c) 2007 Jocelyn Mayer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <stdio.h>
25 #include "cpu.h"
26 #include "exec-all.h"
27 #include "disas.h"
28 #include "tcg-op.h"
29 #include "qemu-common.h"
31 #define DO_SINGLE_STEP
32 #define GENERATE_NOP
33 #define ALPHA_DEBUG_DISAS
34 #define DO_TB_FLUSH
36 typedef struct DisasContext DisasContext;
37 struct DisasContext {
38 uint64_t pc;
39 int mem_idx;
40 #if !defined (CONFIG_USER_ONLY)
41 int pal_mode;
42 #endif
43 uint32_t amask;
46 static TCGv cpu_env;
48 #include "gen-icount.h"
50 static void alpha_translate_init(void)
52 static int done_init = 0;
53 if (done_init)
54 return;
55 cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
56 done_init = 1;
59 static always_inline void gen_op_nop (void)
61 #if defined(GENERATE_NOP)
62 gen_op_no_op();
63 #endif
66 #define GEN32(func, NAME) \
67 static GenOpFunc *NAME ## _table [32] = { \
68 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
69 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
70 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
71 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
72 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
73 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
74 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
75 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
76 }; \
77 static always_inline void func (int n) \
78 { \
79 NAME ## _table[n](); \
82 /* IR moves */
83 /* Special hacks for ir31 */
84 #define gen_op_load_T0_ir31 gen_op_reset_T0
85 #define gen_op_load_T1_ir31 gen_op_reset_T1
86 #define gen_op_load_T2_ir31 gen_op_reset_T2
87 #define gen_op_store_T0_ir31 gen_op_nop
88 #define gen_op_store_T1_ir31 gen_op_nop
89 #define gen_op_store_T2_ir31 gen_op_nop
90 #define gen_op_cmov_ir31 gen_op_nop
91 GEN32(gen_op_load_T0_ir, gen_op_load_T0_ir);
92 GEN32(gen_op_load_T1_ir, gen_op_load_T1_ir);
93 GEN32(gen_op_load_T2_ir, gen_op_load_T2_ir);
94 GEN32(gen_op_store_T0_ir, gen_op_store_T0_ir);
95 GEN32(gen_op_store_T1_ir, gen_op_store_T1_ir);
96 GEN32(gen_op_store_T2_ir, gen_op_store_T2_ir);
97 GEN32(gen_op_cmov_ir, gen_op_cmov_ir);
99 static always_inline void gen_load_ir (DisasContext *ctx, int irn, int Tn)
101 switch (Tn) {
102 case 0:
103 gen_op_load_T0_ir(irn);
104 break;
105 case 1:
106 gen_op_load_T1_ir(irn);
107 break;
108 case 2:
109 gen_op_load_T2_ir(irn);
110 break;
114 static always_inline void gen_store_ir (DisasContext *ctx, int irn, int Tn)
116 switch (Tn) {
117 case 0:
118 gen_op_store_T0_ir(irn);
119 break;
120 case 1:
121 gen_op_store_T1_ir(irn);
122 break;
123 case 2:
124 gen_op_store_T2_ir(irn);
125 break;
129 /* FIR moves */
130 /* Special hacks for fir31 */
131 #define gen_op_load_FT0_fir31 gen_op_reset_FT0
132 #define gen_op_load_FT1_fir31 gen_op_reset_FT1
133 #define gen_op_load_FT2_fir31 gen_op_reset_FT2
134 #define gen_op_store_FT0_fir31 gen_op_nop
135 #define gen_op_store_FT1_fir31 gen_op_nop
136 #define gen_op_store_FT2_fir31 gen_op_nop
137 #define gen_op_cmov_fir31 gen_op_nop
138 GEN32(gen_op_load_FT0_fir, gen_op_load_FT0_fir);
139 GEN32(gen_op_load_FT1_fir, gen_op_load_FT1_fir);
140 GEN32(gen_op_load_FT2_fir, gen_op_load_FT2_fir);
141 GEN32(gen_op_store_FT0_fir, gen_op_store_FT0_fir);
142 GEN32(gen_op_store_FT1_fir, gen_op_store_FT1_fir);
143 GEN32(gen_op_store_FT2_fir, gen_op_store_FT2_fir);
144 GEN32(gen_op_cmov_fir, gen_op_cmov_fir);
146 static always_inline void gen_load_fir (DisasContext *ctx, int firn, int Tn)
148 switch (Tn) {
149 case 0:
150 gen_op_load_FT0_fir(firn);
151 break;
152 case 1:
153 gen_op_load_FT1_fir(firn);
154 break;
155 case 2:
156 gen_op_load_FT2_fir(firn);
157 break;
161 static always_inline void gen_store_fir (DisasContext *ctx, int firn, int Tn)
163 switch (Tn) {
164 case 0:
165 gen_op_store_FT0_fir(firn);
166 break;
167 case 1:
168 gen_op_store_FT1_fir(firn);
169 break;
170 case 2:
171 gen_op_store_FT2_fir(firn);
172 break;
176 /* Memory moves */
177 #if defined(CONFIG_USER_ONLY)
178 #define OP_LD_TABLE(width) \
179 static GenOpFunc *gen_op_ld##width[] = { \
180 &gen_op_ld##width##_raw, \
182 #define OP_ST_TABLE(width) \
183 static GenOpFunc *gen_op_st##width[] = { \
184 &gen_op_st##width##_raw, \
186 #else
187 #define OP_LD_TABLE(width) \
188 static GenOpFunc *gen_op_ld##width[] = { \
189 &gen_op_ld##width##_kernel, \
190 &gen_op_ld##width##_executive, \
191 &gen_op_ld##width##_supervisor, \
192 &gen_op_ld##width##_user, \
194 #define OP_ST_TABLE(width) \
195 static GenOpFunc *gen_op_st##width[] = { \
196 &gen_op_st##width##_kernel, \
197 &gen_op_st##width##_executive, \
198 &gen_op_st##width##_supervisor, \
199 &gen_op_st##width##_user, \
201 #endif
203 #define GEN_LD(width) \
204 OP_LD_TABLE(width); \
205 static always_inline void gen_ld##width (DisasContext *ctx) \
207 (*gen_op_ld##width[ctx->mem_idx])(); \
210 #define GEN_ST(width) \
211 OP_ST_TABLE(width); \
212 static always_inline void gen_st##width (DisasContext *ctx) \
214 (*gen_op_st##width[ctx->mem_idx])(); \
217 GEN_LD(bu);
218 GEN_ST(b);
219 GEN_LD(wu);
220 GEN_ST(w);
221 GEN_LD(l);
222 GEN_ST(l);
223 GEN_LD(q);
224 GEN_ST(q);
225 GEN_LD(q_u);
226 GEN_ST(q_u);
227 GEN_LD(l_l);
228 GEN_ST(l_c);
229 GEN_LD(q_l);
230 GEN_ST(q_c);
232 #if 0 /* currently unused */
233 GEN_LD(f);
234 GEN_ST(f);
235 GEN_LD(g);
236 GEN_ST(g);
237 #endif /* 0 */
238 GEN_LD(s);
239 GEN_ST(s);
240 GEN_LD(t);
241 GEN_ST(t);
243 #if defined(__i386__) || defined(__x86_64__)
244 static always_inline void gen_op_set_s16_T0 (int16_t imm)
246 gen_op_set_s32_T0((int32_t)imm);
249 static always_inline void gen_op_set_s16_T1 (int16_t imm)
251 gen_op_set_s32_T1((int32_t)imm);
254 static always_inline void gen_op_set_u16_T0 (uint16_t imm)
256 gen_op_set_s32_T0((uint32_t)imm);
259 static always_inline void gen_op_set_u16_T1 (uint16_t imm)
261 gen_op_set_s32_T1((uint32_t)imm);
263 #endif
265 static always_inline void gen_set_sT0 (DisasContext *ctx, int64_t imm)
267 int32_t imm32;
268 int16_t imm16;
270 imm32 = imm;
271 if (imm32 == imm) {
272 imm16 = imm;
273 if (imm16 == imm) {
274 if (imm == 0) {
275 gen_op_reset_T0();
276 } else {
277 gen_op_set_s16_T0(imm16);
279 } else {
280 gen_op_set_s32_T0(imm32);
282 } else {
283 #if 0 // Qemu does not know how to do this...
284 gen_op_set_64_T0(imm);
285 #else
286 gen_op_set_64_T0(imm >> 32, imm);
287 #endif
291 static always_inline void gen_set_sT1 (DisasContext *ctx, int64_t imm)
293 int32_t imm32;
294 int16_t imm16;
296 imm32 = imm;
297 if (imm32 == imm) {
298 imm16 = imm;
299 if (imm16 == imm) {
300 if (imm == 0) {
301 gen_op_reset_T1();
302 } else {
303 gen_op_set_s16_T1(imm16);
305 } else {
306 gen_op_set_s32_T1(imm32);
308 } else {
309 #if 0 // Qemu does not know how to do this...
310 gen_op_set_64_T1(imm);
311 #else
312 gen_op_set_64_T1(imm >> 32, imm);
313 #endif
317 static always_inline void gen_set_uT0 (DisasContext *ctx, uint64_t imm)
319 if (!(imm >> 32)) {
320 if ((!imm >> 16)) {
321 if (imm == 0)
322 gen_op_reset_T0();
323 else
324 gen_op_set_u16_T0(imm);
325 } else {
326 gen_op_set_u32_T0(imm);
328 } else {
329 #if 0 // Qemu does not know how to do this...
330 gen_op_set_64_T0(imm);
331 #else
332 gen_op_set_64_T0(imm >> 32, imm);
333 #endif
337 static always_inline void gen_set_uT1 (DisasContext *ctx, uint64_t imm)
339 if (!(imm >> 32)) {
340 if ((!imm >> 16)) {
341 if (imm == 0)
342 gen_op_reset_T1();
343 else
344 gen_op_set_u16_T1(imm);
345 } else {
346 gen_op_set_u32_T1(imm);
348 } else {
349 #if 0 // Qemu does not know how to do this...
350 gen_op_set_64_T1(imm);
351 #else
352 gen_op_set_64_T1(imm >> 32, imm);
353 #endif
357 static always_inline void gen_update_pc (DisasContext *ctx)
359 if (!(ctx->pc >> 32)) {
360 gen_op_update_pc32(ctx->pc);
361 } else {
362 #if 0 // Qemu does not know how to do this...
363 gen_op_update_pc(ctx->pc);
364 #else
365 gen_op_update_pc(ctx->pc >> 32, ctx->pc);
366 #endif
370 static always_inline void _gen_op_bcond (DisasContext *ctx)
372 #if 0 // Qemu does not know how to do this...
373 gen_op_bcond(ctx->pc);
374 #else
375 gen_op_bcond(ctx->pc >> 32, ctx->pc);
376 #endif
379 static always_inline void gen_excp (DisasContext *ctx,
380 int exception, int error_code)
382 gen_update_pc(ctx);
383 gen_op_excp(exception, error_code);
386 static always_inline void gen_invalid (DisasContext *ctx)
388 gen_excp(ctx, EXCP_OPCDEC, 0);
391 static always_inline void gen_load_mem (DisasContext *ctx,
392 void (*gen_load_op)(DisasContext *ctx),
393 int ra, int rb, int32_t disp16,
394 int clear)
396 if (ra == 31 && disp16 == 0) {
397 /* UNOP */
398 gen_op_nop();
399 } else {
400 gen_load_ir(ctx, rb, 0);
401 if (disp16 != 0) {
402 gen_set_sT1(ctx, disp16);
403 gen_op_addq();
405 if (clear)
406 gen_op_n7();
407 (*gen_load_op)(ctx);
408 gen_store_ir(ctx, ra, 1);
412 static always_inline void gen_store_mem (DisasContext *ctx,
413 void (*gen_store_op)(DisasContext *ctx),
414 int ra, int rb, int32_t disp16,
415 int clear)
417 gen_load_ir(ctx, rb, 0);
418 if (disp16 != 0) {
419 gen_set_sT1(ctx, disp16);
420 gen_op_addq();
422 if (clear)
423 gen_op_n7();
424 gen_load_ir(ctx, ra, 1);
425 (*gen_store_op)(ctx);
428 static always_inline void gen_load_fmem (DisasContext *ctx,
429 void (*gen_load_fop)(DisasContext *ctx),
430 int ra, int rb, int32_t disp16)
432 gen_load_ir(ctx, rb, 0);
433 if (disp16 != 0) {
434 gen_set_sT1(ctx, disp16);
435 gen_op_addq();
437 (*gen_load_fop)(ctx);
438 gen_store_fir(ctx, ra, 1);
441 static always_inline void gen_store_fmem (DisasContext *ctx,
442 void (*gen_store_fop)(DisasContext *ctx),
443 int ra, int rb, int32_t disp16)
445 gen_load_ir(ctx, rb, 0);
446 if (disp16 != 0) {
447 gen_set_sT1(ctx, disp16);
448 gen_op_addq();
450 gen_load_fir(ctx, ra, 1);
451 (*gen_store_fop)(ctx);
454 static always_inline void gen_bcond (DisasContext *ctx,
455 void (*gen_test_op)(void),
456 int ra, int32_t disp16)
458 if (disp16 != 0) {
459 gen_set_uT0(ctx, ctx->pc);
460 gen_set_sT1(ctx, disp16 << 2);
461 gen_op_addq1();
462 } else {
463 gen_set_uT1(ctx, ctx->pc);
465 gen_load_ir(ctx, ra, 0);
466 (*gen_test_op)();
467 _gen_op_bcond(ctx);
470 static always_inline void gen_fbcond (DisasContext *ctx,
471 void (*gen_test_op)(void),
472 int ra, int32_t disp16)
474 if (disp16 != 0) {
475 gen_set_uT0(ctx, ctx->pc);
476 gen_set_sT1(ctx, disp16 << 2);
477 gen_op_addq1();
478 } else {
479 gen_set_uT1(ctx, ctx->pc);
481 gen_load_fir(ctx, ra, 0);
482 (*gen_test_op)();
483 _gen_op_bcond(ctx);
486 static always_inline void gen_arith2 (DisasContext *ctx,
487 void (*gen_arith_op)(void),
488 int rb, int rc, int islit, int8_t lit)
490 if (islit)
491 gen_set_sT0(ctx, lit);
492 else
493 gen_load_ir(ctx, rb, 0);
494 (*gen_arith_op)();
495 gen_store_ir(ctx, rc, 0);
498 static always_inline void gen_arith3 (DisasContext *ctx,
499 void (*gen_arith_op)(void),
500 int ra, int rb, int rc,
501 int islit, int8_t lit)
503 gen_load_ir(ctx, ra, 0);
504 if (islit)
505 gen_set_sT1(ctx, lit);
506 else
507 gen_load_ir(ctx, rb, 1);
508 (*gen_arith_op)();
509 gen_store_ir(ctx, rc, 0);
512 static always_inline void gen_cmov (DisasContext *ctx,
513 void (*gen_test_op)(void),
514 int ra, int rb, int rc,
515 int islit, int8_t lit)
517 gen_load_ir(ctx, ra, 1);
518 if (islit)
519 gen_set_sT0(ctx, lit);
520 else
521 gen_load_ir(ctx, rb, 0);
522 (*gen_test_op)();
523 gen_op_cmov_ir(rc);
526 static always_inline void gen_farith2 (DisasContext *ctx,
527 void (*gen_arith_fop)(void),
528 int rb, int rc)
530 gen_load_fir(ctx, rb, 0);
531 (*gen_arith_fop)();
532 gen_store_fir(ctx, rc, 0);
535 static always_inline void gen_farith3 (DisasContext *ctx,
536 void (*gen_arith_fop)(void),
537 int ra, int rb, int rc)
539 gen_load_fir(ctx, ra, 0);
540 gen_load_fir(ctx, rb, 1);
541 (*gen_arith_fop)();
542 gen_store_fir(ctx, rc, 0);
545 static always_inline void gen_fcmov (DisasContext *ctx,
546 void (*gen_test_fop)(void),
547 int ra, int rb, int rc)
549 gen_load_fir(ctx, ra, 0);
550 gen_load_fir(ctx, rb, 1);
551 (*gen_test_fop)();
552 gen_op_cmov_fir(rc);
555 static always_inline void gen_fti (DisasContext *ctx,
556 void (*gen_move_fop)(void),
557 int ra, int rc)
559 gen_load_fir(ctx, rc, 0);
560 (*gen_move_fop)();
561 gen_store_ir(ctx, ra, 0);
564 static always_inline void gen_itf (DisasContext *ctx,
565 void (*gen_move_fop)(void),
566 int ra, int rc)
568 gen_load_ir(ctx, ra, 0);
569 (*gen_move_fop)();
570 gen_store_fir(ctx, rc, 0);
573 static always_inline void gen_s4addl (void)
575 gen_op_s4();
576 gen_op_addl();
579 static always_inline void gen_s4subl (void)
581 gen_op_s4();
582 gen_op_subl();
585 static always_inline void gen_s8addl (void)
587 gen_op_s8();
588 gen_op_addl();
591 static always_inline void gen_s8subl (void)
593 gen_op_s8();
594 gen_op_subl();
597 static always_inline void gen_s4addq (void)
599 gen_op_s4();
600 gen_op_addq();
603 static always_inline void gen_s4subq (void)
605 gen_op_s4();
606 gen_op_subq();
609 static always_inline void gen_s8addq (void)
611 gen_op_s8();
612 gen_op_addq();
615 static always_inline void gen_s8subq (void)
617 gen_op_s8();
618 gen_op_subq();
621 static always_inline void gen_amask (void)
623 gen_op_load_amask();
624 gen_op_bic();
627 static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
629 uint32_t palcode;
630 int32_t disp21, disp16, disp12;
631 uint16_t fn11, fn16;
632 uint8_t opc, ra, rb, rc, sbz, fpfn, fn7, fn2, islit;
633 int8_t lit;
634 int ret;
636 /* Decode all instruction fields */
637 opc = insn >> 26;
638 ra = (insn >> 21) & 0x1F;
639 rb = (insn >> 16) & 0x1F;
640 rc = insn & 0x1F;
641 sbz = (insn >> 13) & 0x07;
642 islit = (insn >> 12) & 1;
643 lit = (insn >> 13) & 0xFF;
644 palcode = insn & 0x03FFFFFF;
645 disp21 = ((int32_t)((insn & 0x001FFFFF) << 11)) >> 11;
646 disp16 = (int16_t)(insn & 0x0000FFFF);
647 disp12 = (int32_t)((insn & 0x00000FFF) << 20) >> 20;
648 fn16 = insn & 0x0000FFFF;
649 fn11 = (insn >> 5) & 0x000007FF;
650 fpfn = fn11 & 0x3F;
651 fn7 = (insn >> 5) & 0x0000007F;
652 fn2 = (insn >> 5) & 0x00000003;
653 ret = 0;
654 #if defined ALPHA_DEBUG_DISAS
655 if (logfile != NULL) {
656 fprintf(logfile, "opc %02x ra %d rb %d rc %d disp16 %04x\n",
657 opc, ra, rb, rc, disp16);
659 #endif
660 switch (opc) {
661 case 0x00:
662 /* CALL_PAL */
663 if (palcode >= 0x80 && palcode < 0xC0) {
664 /* Unprivileged PAL call */
665 gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x1F) << 6), 0);
666 #if !defined (CONFIG_USER_ONLY)
667 } else if (palcode < 0x40) {
668 /* Privileged PAL code */
669 if (ctx->mem_idx & 1)
670 goto invalid_opc;
671 else
672 gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x1F) << 6), 0);
673 #endif
674 } else {
675 /* Invalid PAL call */
676 goto invalid_opc;
678 ret = 3;
679 break;
680 case 0x01:
681 /* OPC01 */
682 goto invalid_opc;
683 case 0x02:
684 /* OPC02 */
685 goto invalid_opc;
686 case 0x03:
687 /* OPC03 */
688 goto invalid_opc;
689 case 0x04:
690 /* OPC04 */
691 goto invalid_opc;
692 case 0x05:
693 /* OPC05 */
694 goto invalid_opc;
695 case 0x06:
696 /* OPC06 */
697 goto invalid_opc;
698 case 0x07:
699 /* OPC07 */
700 goto invalid_opc;
701 case 0x08:
702 /* LDA */
703 gen_load_ir(ctx, rb, 0);
704 gen_set_sT1(ctx, disp16);
705 gen_op_addq();
706 gen_store_ir(ctx, ra, 0);
707 break;
708 case 0x09:
709 /* LDAH */
710 gen_load_ir(ctx, rb, 0);
711 gen_set_sT1(ctx, disp16 << 16);
712 gen_op_addq();
713 gen_store_ir(ctx, ra, 0);
714 break;
715 case 0x0A:
716 /* LDBU */
717 if (!(ctx->amask & AMASK_BWX))
718 goto invalid_opc;
719 gen_load_mem(ctx, &gen_ldbu, ra, rb, disp16, 0);
720 break;
721 case 0x0B:
722 /* LDQ_U */
723 gen_load_mem(ctx, &gen_ldq_u, ra, rb, disp16, 1);
724 break;
725 case 0x0C:
726 /* LDWU */
727 if (!(ctx->amask & AMASK_BWX))
728 goto invalid_opc;
729 gen_load_mem(ctx, &gen_ldwu, ra, rb, disp16, 0);
730 break;
731 case 0x0D:
732 /* STW */
733 if (!(ctx->amask & AMASK_BWX))
734 goto invalid_opc;
735 gen_store_mem(ctx, &gen_stw, ra, rb, disp16, 0);
736 break;
737 case 0x0E:
738 /* STB */
739 if (!(ctx->amask & AMASK_BWX))
740 goto invalid_opc;
741 gen_store_mem(ctx, &gen_stb, ra, rb, disp16, 0);
742 break;
743 case 0x0F:
744 /* STQ_U */
745 gen_store_mem(ctx, &gen_stq_u, ra, rb, disp16, 1);
746 break;
747 case 0x10:
748 switch (fn7) {
749 case 0x00:
750 /* ADDL */
751 gen_arith3(ctx, &gen_op_addl, ra, rb, rc, islit, lit);
752 break;
753 case 0x02:
754 /* S4ADDL */
755 gen_arith3(ctx, &gen_s4addl, ra, rb, rc, islit, lit);
756 break;
757 case 0x09:
758 /* SUBL */
759 gen_arith3(ctx, &gen_op_subl, ra, rb, rc, islit, lit);
760 break;
761 case 0x0B:
762 /* S4SUBL */
763 gen_arith3(ctx, &gen_s4subl, ra, rb, rc, islit, lit);
764 break;
765 case 0x0F:
766 /* CMPBGE */
767 gen_arith3(ctx, &gen_op_cmpbge, ra, rb, rc, islit, lit);
768 break;
769 case 0x12:
770 /* S8ADDL */
771 gen_arith3(ctx, &gen_s8addl, ra, rb, rc, islit, lit);
772 break;
773 case 0x1B:
774 /* S8SUBL */
775 gen_arith3(ctx, &gen_s8subl, ra, rb, rc, islit, lit);
776 break;
777 case 0x1D:
778 /* CMPULT */
779 gen_arith3(ctx, &gen_op_cmpult, ra, rb, rc, islit, lit);
780 break;
781 case 0x20:
782 /* ADDQ */
783 gen_arith3(ctx, &gen_op_addq, ra, rb, rc, islit, lit);
784 break;
785 case 0x22:
786 /* S4ADDQ */
787 gen_arith3(ctx, &gen_s4addq, ra, rb, rc, islit, lit);
788 break;
789 case 0x29:
790 /* SUBQ */
791 gen_arith3(ctx, &gen_op_subq, ra, rb, rc, islit, lit);
792 break;
793 case 0x2B:
794 /* S4SUBQ */
795 gen_arith3(ctx, &gen_s4subq, ra, rb, rc, islit, lit);
796 break;
797 case 0x2D:
798 /* CMPEQ */
799 gen_arith3(ctx, &gen_op_cmpeq, ra, rb, rc, islit, lit);
800 break;
801 case 0x32:
802 /* S8ADDQ */
803 gen_arith3(ctx, &gen_s8addq, ra, rb, rc, islit, lit);
804 break;
805 case 0x3B:
806 /* S8SUBQ */
807 gen_arith3(ctx, &gen_s8subq, ra, rb, rc, islit, lit);
808 break;
809 case 0x3D:
810 /* CMPULE */
811 gen_arith3(ctx, &gen_op_cmpule, ra, rb, rc, islit, lit);
812 break;
813 case 0x40:
814 /* ADDL/V */
815 gen_arith3(ctx, &gen_op_addlv, ra, rb, rc, islit, lit);
816 break;
817 case 0x49:
818 /* SUBL/V */
819 gen_arith3(ctx, &gen_op_sublv, ra, rb, rc, islit, lit);
820 break;
821 case 0x4D:
822 /* CMPLT */
823 gen_arith3(ctx, &gen_op_cmplt, ra, rb, rc, islit, lit);
824 break;
825 case 0x60:
826 /* ADDQ/V */
827 gen_arith3(ctx, &gen_op_addqv, ra, rb, rc, islit, lit);
828 break;
829 case 0x69:
830 /* SUBQ/V */
831 gen_arith3(ctx, &gen_op_subqv, ra, rb, rc, islit, lit);
832 break;
833 case 0x6D:
834 /* CMPLE */
835 gen_arith3(ctx, &gen_op_cmple, ra, rb, rc, islit, lit);
836 break;
837 default:
838 goto invalid_opc;
840 break;
841 case 0x11:
842 switch (fn7) {
843 case 0x00:
844 /* AND */
845 gen_arith3(ctx, &gen_op_and, ra, rb, rc, islit, lit);
846 break;
847 case 0x08:
848 /* BIC */
849 gen_arith3(ctx, &gen_op_bic, ra, rb, rc, islit, lit);
850 break;
851 case 0x14:
852 /* CMOVLBS */
853 gen_cmov(ctx, &gen_op_cmplbs, ra, rb, rc, islit, lit);
854 break;
855 case 0x16:
856 /* CMOVLBC */
857 gen_cmov(ctx, &gen_op_cmplbc, ra, rb, rc, islit, lit);
858 break;
859 case 0x20:
860 /* BIS */
861 if (ra == rb || ra == 31 || rb == 31) {
862 if (ra == 31 && rc == 31) {
863 /* NOP */
864 gen_op_nop();
865 } else {
866 /* MOV */
867 gen_load_ir(ctx, rb, 0);
868 gen_store_ir(ctx, rc, 0);
870 } else {
871 gen_arith3(ctx, &gen_op_bis, ra, rb, rc, islit, lit);
873 break;
874 case 0x24:
875 /* CMOVEQ */
876 gen_cmov(ctx, &gen_op_cmpeqz, ra, rb, rc, islit, lit);
877 break;
878 case 0x26:
879 /* CMOVNE */
880 gen_cmov(ctx, &gen_op_cmpnez, ra, rb, rc, islit, lit);
881 break;
882 case 0x28:
883 /* ORNOT */
884 gen_arith3(ctx, &gen_op_ornot, ra, rb, rc, islit, lit);
885 break;
886 case 0x40:
887 /* XOR */
888 gen_arith3(ctx, &gen_op_xor, ra, rb, rc, islit, lit);
889 break;
890 case 0x44:
891 /* CMOVLT */
892 gen_cmov(ctx, &gen_op_cmpltz, ra, rb, rc, islit, lit);
893 break;
894 case 0x46:
895 /* CMOVGE */
896 gen_cmov(ctx, &gen_op_cmpgez, ra, rb, rc, islit, lit);
897 break;
898 case 0x48:
899 /* EQV */
900 gen_arith3(ctx, &gen_op_eqv, ra, rb, rc, islit, lit);
901 break;
902 case 0x61:
903 /* AMASK */
904 gen_arith2(ctx, &gen_amask, rb, rc, islit, lit);
905 break;
906 case 0x64:
907 /* CMOVLE */
908 gen_cmov(ctx, &gen_op_cmplez, ra, rb, rc, islit, lit);
909 break;
910 case 0x66:
911 /* CMOVGT */
912 gen_cmov(ctx, &gen_op_cmpgtz, ra, rb, rc, islit, lit);
913 break;
914 case 0x6C:
915 /* IMPLVER */
916 gen_op_load_implver();
917 gen_store_ir(ctx, rc, 0);
918 break;
919 default:
920 goto invalid_opc;
922 break;
923 case 0x12:
924 switch (fn7) {
925 case 0x02:
926 /* MSKBL */
927 gen_arith3(ctx, &gen_op_mskbl, ra, rb, rc, islit, lit);
928 break;
929 case 0x06:
930 /* EXTBL */
931 gen_arith3(ctx, &gen_op_extbl, ra, rb, rc, islit, lit);
932 break;
933 case 0x0B:
934 /* INSBL */
935 gen_arith3(ctx, &gen_op_insbl, ra, rb, rc, islit, lit);
936 break;
937 case 0x12:
938 /* MSKWL */
939 gen_arith3(ctx, &gen_op_mskwl, ra, rb, rc, islit, lit);
940 break;
941 case 0x16:
942 /* EXTWL */
943 gen_arith3(ctx, &gen_op_extwl, ra, rb, rc, islit, lit);
944 break;
945 case 0x1B:
946 /* INSWL */
947 gen_arith3(ctx, &gen_op_inswl, ra, rb, rc, islit, lit);
948 break;
949 case 0x22:
950 /* MSKLL */
951 gen_arith3(ctx, &gen_op_mskll, ra, rb, rc, islit, lit);
952 break;
953 case 0x26:
954 /* EXTLL */
955 gen_arith3(ctx, &gen_op_extll, ra, rb, rc, islit, lit);
956 break;
957 case 0x2B:
958 /* INSLL */
959 gen_arith3(ctx, &gen_op_insll, ra, rb, rc, islit, lit);
960 break;
961 case 0x30:
962 /* ZAP */
963 gen_arith3(ctx, &gen_op_zap, ra, rb, rc, islit, lit);
964 break;
965 case 0x31:
966 /* ZAPNOT */
967 gen_arith3(ctx, &gen_op_zapnot, ra, rb, rc, islit, lit);
968 break;
969 case 0x32:
970 /* MSKQL */
971 gen_arith3(ctx, &gen_op_mskql, ra, rb, rc, islit, lit);
972 break;
973 case 0x34:
974 /* SRL */
975 gen_arith3(ctx, &gen_op_srl, ra, rb, rc, islit, lit);
976 break;
977 case 0x36:
978 /* EXTQL */
979 gen_arith3(ctx, &gen_op_extql, ra, rb, rc, islit, lit);
980 break;
981 case 0x39:
982 /* SLL */
983 gen_arith3(ctx, &gen_op_sll, ra, rb, rc, islit, lit);
984 break;
985 case 0x3B:
986 /* INSQL */
987 gen_arith3(ctx, &gen_op_insql, ra, rb, rc, islit, lit);
988 break;
989 case 0x3C:
990 /* SRA */
991 gen_arith3(ctx, &gen_op_sra, ra, rb, rc, islit, lit);
992 break;
993 case 0x52:
994 /* MSKWH */
995 gen_arith3(ctx, &gen_op_mskwh, ra, rb, rc, islit, lit);
996 break;
997 case 0x57:
998 /* INSWH */
999 gen_arith3(ctx, &gen_op_inswh, ra, rb, rc, islit, lit);
1000 break;
1001 case 0x5A:
1002 /* EXTWH */
1003 gen_arith3(ctx, &gen_op_extwh, ra, rb, rc, islit, lit);
1004 break;
1005 case 0x62:
1006 /* MSKLH */
1007 gen_arith3(ctx, &gen_op_msklh, ra, rb, rc, islit, lit);
1008 break;
1009 case 0x67:
1010 /* INSLH */
1011 gen_arith3(ctx, &gen_op_inslh, ra, rb, rc, islit, lit);
1012 break;
1013 case 0x6A:
1014 /* EXTLH */
1015 gen_arith3(ctx, &gen_op_extlh, ra, rb, rc, islit, lit);
1016 break;
1017 case 0x72:
1018 /* MSKQH */
1019 gen_arith3(ctx, &gen_op_mskqh, ra, rb, rc, islit, lit);
1020 break;
1021 case 0x77:
1022 /* INSQH */
1023 gen_arith3(ctx, &gen_op_insqh, ra, rb, rc, islit, lit);
1024 break;
1025 case 0x7A:
1026 /* EXTQH */
1027 gen_arith3(ctx, &gen_op_extqh, ra, rb, rc, islit, lit);
1028 break;
1029 default:
1030 goto invalid_opc;
1032 break;
1033 case 0x13:
1034 switch (fn7) {
1035 case 0x00:
1036 /* MULL */
1037 gen_arith3(ctx, &gen_op_mull, ra, rb, rc, islit, lit);
1038 break;
1039 case 0x20:
1040 /* MULQ */
1041 gen_arith3(ctx, &gen_op_mulq, ra, rb, rc, islit, lit);
1042 break;
1043 case 0x30:
1044 /* UMULH */
1045 gen_arith3(ctx, &gen_op_umulh, ra, rb, rc, islit, lit);
1046 break;
1047 case 0x40:
1048 /* MULL/V */
1049 gen_arith3(ctx, &gen_op_mullv, ra, rb, rc, islit, lit);
1050 break;
1051 case 0x60:
1052 /* MULQ/V */
1053 gen_arith3(ctx, &gen_op_mulqv, ra, rb, rc, islit, lit);
1054 break;
1055 default:
1056 goto invalid_opc;
1058 break;
1059 case 0x14:
1060 switch (fpfn) { /* f11 & 0x3F */
1061 case 0x04:
1062 /* ITOFS */
1063 if (!(ctx->amask & AMASK_FIX))
1064 goto invalid_opc;
1065 gen_itf(ctx, &gen_op_itofs, ra, rc);
1066 break;
1067 case 0x0A:
1068 /* SQRTF */
1069 if (!(ctx->amask & AMASK_FIX))
1070 goto invalid_opc;
1071 gen_farith2(ctx, &gen_op_sqrtf, rb, rc);
1072 break;
1073 case 0x0B:
1074 /* SQRTS */
1075 if (!(ctx->amask & AMASK_FIX))
1076 goto invalid_opc;
1077 gen_farith2(ctx, &gen_op_sqrts, rb, rc);
1078 break;
1079 case 0x14:
1080 /* ITOFF */
1081 if (!(ctx->amask & AMASK_FIX))
1082 goto invalid_opc;
1083 #if 0 // TODO
1084 gen_itf(ctx, &gen_op_itoff, ra, rc);
1085 #else
1086 goto invalid_opc;
1087 #endif
1088 break;
1089 case 0x24:
1090 /* ITOFT */
1091 if (!(ctx->amask & AMASK_FIX))
1092 goto invalid_opc;
1093 gen_itf(ctx, &gen_op_itoft, ra, rc);
1094 break;
1095 case 0x2A:
1096 /* SQRTG */
1097 if (!(ctx->amask & AMASK_FIX))
1098 goto invalid_opc;
1099 gen_farith2(ctx, &gen_op_sqrtg, rb, rc);
1100 break;
1101 case 0x02B:
1102 /* SQRTT */
1103 if (!(ctx->amask & AMASK_FIX))
1104 goto invalid_opc;
1105 gen_farith2(ctx, &gen_op_sqrtt, rb, rc);
1106 break;
1107 default:
1108 goto invalid_opc;
1110 break;
1111 case 0x15:
1112 /* VAX floating point */
1113 /* XXX: rounding mode and trap are ignored (!) */
1114 switch (fpfn) { /* f11 & 0x3F */
1115 case 0x00:
1116 /* ADDF */
1117 gen_farith3(ctx, &gen_op_addf, ra, rb, rc);
1118 break;
1119 case 0x01:
1120 /* SUBF */
1121 gen_farith3(ctx, &gen_op_subf, ra, rb, rc);
1122 break;
1123 case 0x02:
1124 /* MULF */
1125 gen_farith3(ctx, &gen_op_mulf, ra, rb, rc);
1126 break;
1127 case 0x03:
1128 /* DIVF */
1129 gen_farith3(ctx, &gen_op_divf, ra, rb, rc);
1130 break;
1131 case 0x1E:
1132 /* CVTDG */
1133 #if 0 // TODO
1134 gen_farith2(ctx, &gen_op_cvtdg, rb, rc);
1135 #else
1136 goto invalid_opc;
1137 #endif
1138 break;
1139 case 0x20:
1140 /* ADDG */
1141 gen_farith3(ctx, &gen_op_addg, ra, rb, rc);
1142 break;
1143 case 0x21:
1144 /* SUBG */
1145 gen_farith3(ctx, &gen_op_subg, ra, rb, rc);
1146 break;
1147 case 0x22:
1148 /* MULG */
1149 gen_farith3(ctx, &gen_op_mulg, ra, rb, rc);
1150 break;
1151 case 0x23:
1152 /* DIVG */
1153 gen_farith3(ctx, &gen_op_divg, ra, rb, rc);
1154 break;
1155 case 0x25:
1156 /* CMPGEQ */
1157 gen_farith3(ctx, &gen_op_cmpgeq, ra, rb, rc);
1158 break;
1159 case 0x26:
1160 /* CMPGLT */
1161 gen_farith3(ctx, &gen_op_cmpglt, ra, rb, rc);
1162 break;
1163 case 0x27:
1164 /* CMPGLE */
1165 gen_farith3(ctx, &gen_op_cmpgle, ra, rb, rc);
1166 break;
1167 case 0x2C:
1168 /* CVTGF */
1169 gen_farith2(ctx, &gen_op_cvtgf, rb, rc);
1170 break;
1171 case 0x2D:
1172 /* CVTGD */
1173 #if 0 // TODO
1174 gen_farith2(ctx, &gen_op_cvtgd, rb, rc);
1175 #else
1176 goto invalid_opc;
1177 #endif
1178 break;
1179 case 0x2F:
1180 /* CVTGQ */
1181 gen_farith2(ctx, &gen_op_cvtgq, rb, rc);
1182 break;
1183 case 0x3C:
1184 /* CVTQF */
1185 gen_farith2(ctx, &gen_op_cvtqf, rb, rc);
1186 break;
1187 case 0x3E:
1188 /* CVTQG */
1189 gen_farith2(ctx, &gen_op_cvtqg, rb, rc);
1190 break;
1191 default:
1192 goto invalid_opc;
1194 break;
1195 case 0x16:
1196 /* IEEE floating-point */
1197 /* XXX: rounding mode and traps are ignored (!) */
1198 switch (fpfn) { /* f11 & 0x3F */
1199 case 0x00:
1200 /* ADDS */
1201 gen_farith3(ctx, &gen_op_adds, ra, rb, rc);
1202 break;
1203 case 0x01:
1204 /* SUBS */
1205 gen_farith3(ctx, &gen_op_subs, ra, rb, rc);
1206 break;
1207 case 0x02:
1208 /* MULS */
1209 gen_farith3(ctx, &gen_op_muls, ra, rb, rc);
1210 break;
1211 case 0x03:
1212 /* DIVS */
1213 gen_farith3(ctx, &gen_op_divs, ra, rb, rc);
1214 break;
1215 case 0x20:
1216 /* ADDT */
1217 gen_farith3(ctx, &gen_op_addt, ra, rb, rc);
1218 break;
1219 case 0x21:
1220 /* SUBT */
1221 gen_farith3(ctx, &gen_op_subt, ra, rb, rc);
1222 break;
1223 case 0x22:
1224 /* MULT */
1225 gen_farith3(ctx, &gen_op_mult, ra, rb, rc);
1226 break;
1227 case 0x23:
1228 /* DIVT */
1229 gen_farith3(ctx, &gen_op_divt, ra, rb, rc);
1230 break;
1231 case 0x24:
1232 /* CMPTUN */
1233 gen_farith3(ctx, &gen_op_cmptun, ra, rb, rc);
1234 break;
1235 case 0x25:
1236 /* CMPTEQ */
1237 gen_farith3(ctx, &gen_op_cmpteq, ra, rb, rc);
1238 break;
1239 case 0x26:
1240 /* CMPTLT */
1241 gen_farith3(ctx, &gen_op_cmptlt, ra, rb, rc);
1242 break;
1243 case 0x27:
1244 /* CMPTLE */
1245 gen_farith3(ctx, &gen_op_cmptle, ra, rb, rc);
1246 break;
1247 case 0x2C:
1248 /* XXX: incorrect */
1249 if (fn11 == 0x2AC) {
1250 /* CVTST */
1251 gen_farith2(ctx, &gen_op_cvtst, rb, rc);
1252 } else {
1253 /* CVTTS */
1254 gen_farith2(ctx, &gen_op_cvtts, rb, rc);
1256 break;
1257 case 0x2F:
1258 /* CVTTQ */
1259 gen_farith2(ctx, &gen_op_cvttq, rb, rc);
1260 break;
1261 case 0x3C:
1262 /* CVTQS */
1263 gen_farith2(ctx, &gen_op_cvtqs, rb, rc);
1264 break;
1265 case 0x3E:
1266 /* CVTQT */
1267 gen_farith2(ctx, &gen_op_cvtqt, rb, rc);
1268 break;
1269 default:
1270 goto invalid_opc;
1272 break;
1273 case 0x17:
1274 switch (fn11) {
1275 case 0x010:
1276 /* CVTLQ */
1277 gen_farith2(ctx, &gen_op_cvtlq, rb, rc);
1278 break;
1279 case 0x020:
1280 /* CPYS */
1281 if (ra == rb) {
1282 if (ra == 31 && rc == 31) {
1283 /* FNOP */
1284 gen_op_nop();
1285 } else {
1286 /* FMOV */
1287 gen_load_fir(ctx, rb, 0);
1288 gen_store_fir(ctx, rc, 0);
1290 } else {
1291 gen_farith3(ctx, &gen_op_cpys, ra, rb, rc);
1293 break;
1294 case 0x021:
1295 /* CPYSN */
1296 gen_farith2(ctx, &gen_op_cpysn, rb, rc);
1297 break;
1298 case 0x022:
1299 /* CPYSE */
1300 gen_farith2(ctx, &gen_op_cpyse, rb, rc);
1301 break;
1302 case 0x024:
1303 /* MT_FPCR */
1304 gen_load_fir(ctx, ra, 0);
1305 gen_op_store_fpcr();
1306 break;
1307 case 0x025:
1308 /* MF_FPCR */
1309 gen_op_load_fpcr();
1310 gen_store_fir(ctx, ra, 0);
1311 break;
1312 case 0x02A:
1313 /* FCMOVEQ */
1314 gen_fcmov(ctx, &gen_op_cmpfeq, ra, rb, rc);
1315 break;
1316 case 0x02B:
1317 /* FCMOVNE */
1318 gen_fcmov(ctx, &gen_op_cmpfne, ra, rb, rc);
1319 break;
1320 case 0x02C:
1321 /* FCMOVLT */
1322 gen_fcmov(ctx, &gen_op_cmpflt, ra, rb, rc);
1323 break;
1324 case 0x02D:
1325 /* FCMOVGE */
1326 gen_fcmov(ctx, &gen_op_cmpfge, ra, rb, rc);
1327 break;
1328 case 0x02E:
1329 /* FCMOVLE */
1330 gen_fcmov(ctx, &gen_op_cmpfle, ra, rb, rc);
1331 break;
1332 case 0x02F:
1333 /* FCMOVGT */
1334 gen_fcmov(ctx, &gen_op_cmpfgt, ra, rb, rc);
1335 break;
1336 case 0x030:
1337 /* CVTQL */
1338 gen_farith2(ctx, &gen_op_cvtql, rb, rc);
1339 break;
1340 case 0x130:
1341 /* CVTQL/V */
1342 gen_farith2(ctx, &gen_op_cvtqlv, rb, rc);
1343 break;
1344 case 0x530:
1345 /* CVTQL/SV */
1346 gen_farith2(ctx, &gen_op_cvtqlsv, rb, rc);
1347 break;
1348 default:
1349 goto invalid_opc;
1351 break;
1352 case 0x18:
1353 switch ((uint16_t)disp16) {
1354 case 0x0000:
1355 /* TRAPB */
1356 /* No-op. Just exit from the current tb */
1357 ret = 2;
1358 break;
1359 case 0x0400:
1360 /* EXCB */
1361 /* No-op. Just exit from the current tb */
1362 ret = 2;
1363 break;
1364 case 0x4000:
1365 /* MB */
1366 /* No-op */
1367 break;
1368 case 0x4400:
1369 /* WMB */
1370 /* No-op */
1371 break;
1372 case 0x8000:
1373 /* FETCH */
1374 /* No-op */
1375 break;
1376 case 0xA000:
1377 /* FETCH_M */
1378 /* No-op */
1379 break;
1380 case 0xC000:
1381 /* RPCC */
1382 gen_op_load_pcc();
1383 gen_store_ir(ctx, ra, 0);
1384 break;
1385 case 0xE000:
1386 /* RC */
1387 gen_op_load_irf();
1388 gen_store_ir(ctx, ra, 0);
1389 gen_op_clear_irf();
1390 break;
1391 case 0xE800:
1392 /* ECB */
1393 /* XXX: TODO: evict tb cache at address rb */
1394 #if 0
1395 ret = 2;
1396 #else
1397 goto invalid_opc;
1398 #endif
1399 break;
1400 case 0xF000:
1401 /* RS */
1402 gen_op_load_irf();
1403 gen_store_ir(ctx, ra, 0);
1404 gen_op_set_irf();
1405 break;
1406 case 0xF800:
1407 /* WH64 */
1408 /* No-op */
1409 break;
1410 default:
1411 goto invalid_opc;
1413 break;
1414 case 0x19:
1415 /* HW_MFPR (PALcode) */
1416 #if defined (CONFIG_USER_ONLY)
1417 goto invalid_opc;
1418 #else
1419 if (!ctx->pal_mode)
1420 goto invalid_opc;
1421 gen_op_mfpr(insn & 0xFF);
1422 gen_store_ir(ctx, ra, 0);
1423 break;
1424 #endif
1425 case 0x1A:
1426 gen_load_ir(ctx, rb, 0);
1427 if (ra != 31) {
1428 gen_set_uT1(ctx, ctx->pc);
1429 gen_store_ir(ctx, ra, 1);
1431 gen_op_branch();
1432 /* Those four jumps only differ by the branch prediction hint */
1433 switch (fn2) {
1434 case 0x0:
1435 /* JMP */
1436 break;
1437 case 0x1:
1438 /* JSR */
1439 break;
1440 case 0x2:
1441 /* RET */
1442 break;
1443 case 0x3:
1444 /* JSR_COROUTINE */
1445 break;
1447 ret = 1;
1448 break;
1449 case 0x1B:
1450 /* HW_LD (PALcode) */
1451 #if defined (CONFIG_USER_ONLY)
1452 goto invalid_opc;
1453 #else
1454 if (!ctx->pal_mode)
1455 goto invalid_opc;
1456 gen_load_ir(ctx, rb, 0);
1457 gen_set_sT1(ctx, disp12);
1458 gen_op_addq();
1459 switch ((insn >> 12) & 0xF) {
1460 case 0x0:
1461 /* Longword physical access */
1462 gen_op_ldl_raw();
1463 break;
1464 case 0x1:
1465 /* Quadword physical access */
1466 gen_op_ldq_raw();
1467 break;
1468 case 0x2:
1469 /* Longword physical access with lock */
1470 gen_op_ldl_l_raw();
1471 break;
1472 case 0x3:
1473 /* Quadword physical access with lock */
1474 gen_op_ldq_l_raw();
1475 break;
1476 case 0x4:
1477 /* Longword virtual PTE fetch */
1478 gen_op_ldl_kernel();
1479 break;
1480 case 0x5:
1481 /* Quadword virtual PTE fetch */
1482 gen_op_ldq_kernel();
1483 break;
1484 case 0x6:
1485 /* Invalid */
1486 goto invalid_opc;
1487 case 0x7:
1488 /* Invalid */
1489 goto invalid_opc;
1490 case 0x8:
1491 /* Longword virtual access */
1492 gen_op_ld_phys_to_virt();
1493 gen_op_ldl_raw();
1494 break;
1495 case 0x9:
1496 /* Quadword virtual access */
1497 gen_op_ld_phys_to_virt();
1498 gen_op_ldq_raw();
1499 break;
1500 case 0xA:
1501 /* Longword virtual access with protection check */
1502 gen_ldl(ctx);
1503 break;
1504 case 0xB:
1505 /* Quadword virtual access with protection check */
1506 gen_ldq(ctx);
1507 break;
1508 case 0xC:
1509 /* Longword virtual access with altenate access mode */
1510 gen_op_set_alt_mode();
1511 gen_op_ld_phys_to_virt();
1512 gen_op_ldl_raw();
1513 gen_op_restore_mode();
1514 break;
1515 case 0xD:
1516 /* Quadword virtual access with altenate access mode */
1517 gen_op_set_alt_mode();
1518 gen_op_ld_phys_to_virt();
1519 gen_op_ldq_raw();
1520 gen_op_restore_mode();
1521 break;
1522 case 0xE:
1523 /* Longword virtual access with alternate access mode and
1524 * protection checks
1526 gen_op_set_alt_mode();
1527 gen_op_ldl_data();
1528 gen_op_restore_mode();
1529 break;
1530 case 0xF:
1531 /* Quadword virtual access with alternate access mode and
1532 * protection checks
1534 gen_op_set_alt_mode();
1535 gen_op_ldq_data();
1536 gen_op_restore_mode();
1537 break;
1539 gen_store_ir(ctx, ra, 1);
1540 break;
1541 #endif
1542 case 0x1C:
1543 switch (fn7) {
1544 case 0x00:
1545 /* SEXTB */
1546 if (!(ctx->amask & AMASK_BWX))
1547 goto invalid_opc;
1548 gen_arith2(ctx, &gen_op_sextb, rb, rc, islit, lit);
1549 break;
1550 case 0x01:
1551 /* SEXTW */
1552 if (!(ctx->amask & AMASK_BWX))
1553 goto invalid_opc;
1554 gen_arith2(ctx, &gen_op_sextw, rb, rc, islit, lit);
1555 break;
1556 case 0x30:
1557 /* CTPOP */
1558 if (!(ctx->amask & AMASK_CIX))
1559 goto invalid_opc;
1560 gen_arith2(ctx, &gen_op_ctpop, rb, rc, 0, 0);
1561 break;
1562 case 0x31:
1563 /* PERR */
1564 if (!(ctx->amask & AMASK_MVI))
1565 goto invalid_opc;
1566 /* XXX: TODO */
1567 goto invalid_opc;
1568 break;
1569 case 0x32:
1570 /* CTLZ */
1571 if (!(ctx->amask & AMASK_CIX))
1572 goto invalid_opc;
1573 gen_arith2(ctx, &gen_op_ctlz, rb, rc, 0, 0);
1574 break;
1575 case 0x33:
1576 /* CTTZ */
1577 if (!(ctx->amask & AMASK_CIX))
1578 goto invalid_opc;
1579 gen_arith2(ctx, &gen_op_cttz, rb, rc, 0, 0);
1580 break;
1581 case 0x34:
1582 /* UNPKBW */
1583 if (!(ctx->amask & AMASK_MVI))
1584 goto invalid_opc;
1585 /* XXX: TODO */
1586 goto invalid_opc;
1587 break;
1588 case 0x35:
1589 /* UNPKWL */
1590 if (!(ctx->amask & AMASK_MVI))
1591 goto invalid_opc;
1592 /* XXX: TODO */
1593 goto invalid_opc;
1594 break;
1595 case 0x36:
1596 /* PKWB */
1597 if (!(ctx->amask & AMASK_MVI))
1598 goto invalid_opc;
1599 /* XXX: TODO */
1600 goto invalid_opc;
1601 break;
1602 case 0x37:
1603 /* PKLB */
1604 if (!(ctx->amask & AMASK_MVI))
1605 goto invalid_opc;
1606 /* XXX: TODO */
1607 goto invalid_opc;
1608 break;
1609 case 0x38:
1610 /* MINSB8 */
1611 if (!(ctx->amask & AMASK_MVI))
1612 goto invalid_opc;
1613 /* XXX: TODO */
1614 goto invalid_opc;
1615 break;
1616 case 0x39:
1617 /* MINSW4 */
1618 if (!(ctx->amask & AMASK_MVI))
1619 goto invalid_opc;
1620 /* XXX: TODO */
1621 goto invalid_opc;
1622 break;
1623 case 0x3A:
1624 /* MINUB8 */
1625 if (!(ctx->amask & AMASK_MVI))
1626 goto invalid_opc;
1627 /* XXX: TODO */
1628 goto invalid_opc;
1629 break;
1630 case 0x3B:
1631 /* MINUW4 */
1632 if (!(ctx->amask & AMASK_MVI))
1633 goto invalid_opc;
1634 /* XXX: TODO */
1635 goto invalid_opc;
1636 break;
1637 case 0x3C:
1638 /* MAXUB8 */
1639 if (!(ctx->amask & AMASK_MVI))
1640 goto invalid_opc;
1641 /* XXX: TODO */
1642 goto invalid_opc;
1643 break;
1644 case 0x3D:
1645 /* MAXUW4 */
1646 if (!(ctx->amask & AMASK_MVI))
1647 goto invalid_opc;
1648 /* XXX: TODO */
1649 goto invalid_opc;
1650 break;
1651 case 0x3E:
1652 /* MAXSB8 */
1653 if (!(ctx->amask & AMASK_MVI))
1654 goto invalid_opc;
1655 /* XXX: TODO */
1656 goto invalid_opc;
1657 break;
1658 case 0x3F:
1659 /* MAXSW4 */
1660 if (!(ctx->amask & AMASK_MVI))
1661 goto invalid_opc;
1662 /* XXX: TODO */
1663 goto invalid_opc;
1664 break;
1665 case 0x70:
1666 /* FTOIT */
1667 if (!(ctx->amask & AMASK_FIX))
1668 goto invalid_opc;
1669 gen_fti(ctx, &gen_op_ftoit, ra, rb);
1670 break;
1671 case 0x78:
1672 /* FTOIS */
1673 if (!(ctx->amask & AMASK_FIX))
1674 goto invalid_opc;
1675 gen_fti(ctx, &gen_op_ftois, ra, rb);
1676 break;
1677 default:
1678 goto invalid_opc;
1680 break;
1681 case 0x1D:
1682 /* HW_MTPR (PALcode) */
1683 #if defined (CONFIG_USER_ONLY)
1684 goto invalid_opc;
1685 #else
1686 if (!ctx->pal_mode)
1687 goto invalid_opc;
1688 gen_load_ir(ctx, ra, 0);
1689 gen_op_mtpr(insn & 0xFF);
1690 ret = 2;
1691 break;
1692 #endif
1693 case 0x1E:
1694 /* HW_REI (PALcode) */
1695 #if defined (CONFIG_USER_ONLY)
1696 goto invalid_opc;
1697 #else
1698 if (!ctx->pal_mode)
1699 goto invalid_opc;
1700 if (rb == 31) {
1701 /* "Old" alpha */
1702 gen_op_hw_rei();
1703 } else {
1704 gen_load_ir(ctx, rb, 0);
1705 gen_set_uT1(ctx, (((int64_t)insn << 51) >> 51));
1706 gen_op_addq();
1707 gen_op_hw_ret();
1709 ret = 2;
1710 break;
1711 #endif
1712 case 0x1F:
1713 /* HW_ST (PALcode) */
1714 #if defined (CONFIG_USER_ONLY)
1715 goto invalid_opc;
1716 #else
1717 if (!ctx->pal_mode)
1718 goto invalid_opc;
1719 gen_load_ir(ctx, rb, 0);
1720 gen_set_sT1(ctx, disp12);
1721 gen_op_addq();
1722 gen_load_ir(ctx, ra, 1);
1723 switch ((insn >> 12) & 0xF) {
1724 case 0x0:
1725 /* Longword physical access */
1726 gen_op_stl_raw();
1727 break;
1728 case 0x1:
1729 /* Quadword physical access */
1730 gen_op_stq_raw();
1731 break;
1732 case 0x2:
1733 /* Longword physical access with lock */
1734 gen_op_stl_c_raw();
1735 break;
1736 case 0x3:
1737 /* Quadword physical access with lock */
1738 gen_op_stq_c_raw();
1739 break;
1740 case 0x4:
1741 /* Longword virtual access */
1742 gen_op_st_phys_to_virt();
1743 gen_op_stl_raw();
1744 break;
1745 case 0x5:
1746 /* Quadword virtual access */
1747 gen_op_st_phys_to_virt();
1748 gen_op_stq_raw();
1749 break;
1750 case 0x6:
1751 /* Invalid */
1752 goto invalid_opc;
1753 case 0x7:
1754 /* Invalid */
1755 goto invalid_opc;
1756 case 0x8:
1757 /* Invalid */
1758 goto invalid_opc;
1759 case 0x9:
1760 /* Invalid */
1761 goto invalid_opc;
1762 case 0xA:
1763 /* Invalid */
1764 goto invalid_opc;
1765 case 0xB:
1766 /* Invalid */
1767 goto invalid_opc;
1768 case 0xC:
1769 /* Longword virtual access with alternate access mode */
1770 gen_op_set_alt_mode();
1771 gen_op_st_phys_to_virt();
1772 gen_op_ldl_raw();
1773 gen_op_restore_mode();
1774 break;
1775 case 0xD:
1776 /* Quadword virtual access with alternate access mode */
1777 gen_op_set_alt_mode();
1778 gen_op_st_phys_to_virt();
1779 gen_op_ldq_raw();
1780 gen_op_restore_mode();
1781 break;
1782 case 0xE:
1783 /* Invalid */
1784 goto invalid_opc;
1785 case 0xF:
1786 /* Invalid */
1787 goto invalid_opc;
1789 ret = 2;
1790 break;
1791 #endif
1792 case 0x20:
1793 /* LDF */
1794 #if 0 // TODO
1795 gen_load_fmem(ctx, &gen_ldf, ra, rb, disp16);
1796 #else
1797 goto invalid_opc;
1798 #endif
1799 break;
1800 case 0x21:
1801 /* LDG */
1802 #if 0 // TODO
1803 gen_load_fmem(ctx, &gen_ldg, ra, rb, disp16);
1804 #else
1805 goto invalid_opc;
1806 #endif
1807 break;
1808 case 0x22:
1809 /* LDS */
1810 gen_load_fmem(ctx, &gen_lds, ra, rb, disp16);
1811 break;
1812 case 0x23:
1813 /* LDT */
1814 gen_load_fmem(ctx, &gen_ldt, ra, rb, disp16);
1815 break;
1816 case 0x24:
1817 /* STF */
1818 #if 0 // TODO
1819 gen_store_fmem(ctx, &gen_stf, ra, rb, disp16);
1820 #else
1821 goto invalid_opc;
1822 #endif
1823 break;
1824 case 0x25:
1825 /* STG */
1826 #if 0 // TODO
1827 gen_store_fmem(ctx, &gen_stg, ra, rb, disp16);
1828 #else
1829 goto invalid_opc;
1830 #endif
1831 break;
1832 case 0x26:
1833 /* STS */
1834 gen_store_fmem(ctx, &gen_sts, ra, rb, disp16);
1835 break;
1836 case 0x27:
1837 /* STT */
1838 gen_store_fmem(ctx, &gen_stt, ra, rb, disp16);
1839 break;
1840 case 0x28:
1841 /* LDL */
1842 gen_load_mem(ctx, &gen_ldl, ra, rb, disp16, 0);
1843 break;
1844 case 0x29:
1845 /* LDQ */
1846 gen_load_mem(ctx, &gen_ldq, ra, rb, disp16, 0);
1847 break;
1848 case 0x2A:
1849 /* LDL_L */
1850 gen_load_mem(ctx, &gen_ldl_l, ra, rb, disp16, 0);
1851 break;
1852 case 0x2B:
1853 /* LDQ_L */
1854 gen_load_mem(ctx, &gen_ldq_l, ra, rb, disp16, 0);
1855 break;
1856 case 0x2C:
1857 /* STL */
1858 gen_store_mem(ctx, &gen_stl, ra, rb, disp16, 0);
1859 break;
1860 case 0x2D:
1861 /* STQ */
1862 gen_store_mem(ctx, &gen_stq, ra, rb, disp16, 0);
1863 break;
1864 case 0x2E:
1865 /* STL_C */
1866 gen_store_mem(ctx, &gen_stl_c, ra, rb, disp16, 0);
1867 break;
1868 case 0x2F:
1869 /* STQ_C */
1870 gen_store_mem(ctx, &gen_stq_c, ra, rb, disp16, 0);
1871 break;
1872 case 0x30:
1873 /* BR */
1874 gen_set_uT0(ctx, ctx->pc);
1875 gen_store_ir(ctx, ra, 0);
1876 if (disp21 != 0) {
1877 gen_set_sT1(ctx, disp21 << 2);
1878 gen_op_addq();
1880 gen_op_branch();
1881 ret = 1;
1882 break;
1883 case 0x31:
1884 /* FBEQ */
1885 gen_fbcond(ctx, &gen_op_cmpfeq, ra, disp16);
1886 ret = 1;
1887 break;
1888 case 0x32:
1889 /* FBLT */
1890 gen_fbcond(ctx, &gen_op_cmpflt, ra, disp16);
1891 ret = 1;
1892 break;
1893 case 0x33:
1894 /* FBLE */
1895 gen_fbcond(ctx, &gen_op_cmpfle, ra, disp16);
1896 ret = 1;
1897 break;
1898 case 0x34:
1899 /* BSR */
1900 gen_set_uT0(ctx, ctx->pc);
1901 gen_store_ir(ctx, ra, 0);
1902 if (disp21 != 0) {
1903 gen_set_sT1(ctx, disp21 << 2);
1904 gen_op_addq();
1906 gen_op_branch();
1907 ret = 1;
1908 break;
1909 case 0x35:
1910 /* FBNE */
1911 gen_fbcond(ctx, &gen_op_cmpfne, ra, disp16);
1912 ret = 1;
1913 break;
1914 case 0x36:
1915 /* FBGE */
1916 gen_fbcond(ctx, &gen_op_cmpfge, ra, disp16);
1917 ret = 1;
1918 break;
1919 case 0x37:
1920 /* FBGT */
1921 gen_fbcond(ctx, &gen_op_cmpfgt, ra, disp16);
1922 ret = 1;
1923 break;
1924 case 0x38:
1925 /* BLBC */
1926 gen_bcond(ctx, &gen_op_cmplbc, ra, disp16);
1927 ret = 1;
1928 break;
1929 case 0x39:
1930 /* BEQ */
1931 gen_bcond(ctx, &gen_op_cmpeqz, ra, disp16);
1932 ret = 1;
1933 break;
1934 case 0x3A:
1935 /* BLT */
1936 gen_bcond(ctx, &gen_op_cmpltz, ra, disp16);
1937 ret = 1;
1938 break;
1939 case 0x3B:
1940 /* BLE */
1941 gen_bcond(ctx, &gen_op_cmplez, ra, disp16);
1942 ret = 1;
1943 break;
1944 case 0x3C:
1945 /* BLBS */
1946 gen_bcond(ctx, &gen_op_cmplbs, ra, disp16);
1947 ret = 1;
1948 break;
1949 case 0x3D:
1950 /* BNE */
1951 gen_bcond(ctx, &gen_op_cmpnez, ra, disp16);
1952 ret = 1;
1953 break;
1954 case 0x3E:
1955 /* BGE */
1956 gen_bcond(ctx, &gen_op_cmpgez, ra, disp16);
1957 ret = 1;
1958 break;
1959 case 0x3F:
1960 /* BGT */
1961 gen_bcond(ctx, &gen_op_cmpgtz, ra, disp16);
1962 ret = 1;
1963 break;
1964 invalid_opc:
1965 gen_invalid(ctx);
1966 ret = 3;
1967 break;
1970 return ret;
1973 static always_inline void gen_intermediate_code_internal (CPUState *env,
1974 TranslationBlock *tb,
1975 int search_pc)
1977 #if defined ALPHA_DEBUG_DISAS
1978 static int insn_count;
1979 #endif
1980 DisasContext ctx, *ctxp = &ctx;
1981 target_ulong pc_start;
1982 uint32_t insn;
1983 uint16_t *gen_opc_end;
1984 int j, lj = -1;
1985 int ret;
1986 int num_insns;
1987 int max_insns;
1989 pc_start = tb->pc;
1990 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1991 ctx.pc = pc_start;
1992 ctx.amask = env->amask;
1993 #if defined (CONFIG_USER_ONLY)
1994 ctx.mem_idx = 0;
1995 #else
1996 ctx.mem_idx = ((env->ps >> 3) & 3);
1997 ctx.pal_mode = env->ipr[IPR_EXC_ADDR] & 1;
1998 #endif
1999 num_insns = 0;
2000 max_insns = tb->cflags & CF_COUNT_MASK;
2001 if (max_insns == 0)
2002 max_insns = CF_COUNT_MASK;
2004 gen_icount_start();
2005 for (ret = 0; ret == 0;) {
2006 if (env->nb_breakpoints > 0) {
2007 for(j = 0; j < env->nb_breakpoints; j++) {
2008 if (env->breakpoints[j] == ctx.pc) {
2009 gen_excp(&ctx, EXCP_DEBUG, 0);
2010 break;
2014 if (search_pc) {
2015 j = gen_opc_ptr - gen_opc_buf;
2016 if (lj < j) {
2017 lj++;
2018 while (lj < j)
2019 gen_opc_instr_start[lj++] = 0;
2020 gen_opc_pc[lj] = ctx.pc;
2021 gen_opc_instr_start[lj] = 1;
2022 gen_opc_icount[lj] = num_insns;
2025 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
2026 gen_io_start();
2027 #if defined ALPHA_DEBUG_DISAS
2028 insn_count++;
2029 if (logfile != NULL) {
2030 fprintf(logfile, "pc " TARGET_FMT_lx " mem_idx %d\n",
2031 ctx.pc, ctx.mem_idx);
2033 #endif
2034 insn = ldl_code(ctx.pc);
2035 #if defined ALPHA_DEBUG_DISAS
2036 insn_count++;
2037 if (logfile != NULL) {
2038 fprintf(logfile, "opcode %08x %d\n", insn, insn_count);
2040 #endif
2041 num_insns++;
2042 ctx.pc += 4;
2043 ret = translate_one(ctxp, insn);
2044 if (ret != 0)
2045 break;
2046 /* if we reach a page boundary or are single stepping, stop
2047 * generation
2049 if (((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) ||
2050 (env->singlestep_enabled) ||
2051 num_insns >= max_insns) {
2052 break;
2054 #if defined (DO_SINGLE_STEP)
2055 break;
2056 #endif
2058 if (ret != 1 && ret != 3) {
2059 gen_update_pc(&ctx);
2061 #if defined (DO_TB_FLUSH)
2062 gen_op_tb_flush();
2063 #endif
2064 if (tb->cflags & CF_LAST_IO)
2065 gen_io_end();
2066 /* Generate the return instruction */
2067 tcg_gen_exit_tb(0);
2068 gen_icount_end(tb, num_insns);
2069 *gen_opc_ptr = INDEX_op_end;
2070 if (search_pc) {
2071 j = gen_opc_ptr - gen_opc_buf;
2072 lj++;
2073 while (lj <= j)
2074 gen_opc_instr_start[lj++] = 0;
2075 } else {
2076 tb->size = ctx.pc - pc_start;
2077 tb->icount = num_insns;
2079 #if defined ALPHA_DEBUG_DISAS
2080 if (loglevel & CPU_LOG_TB_CPU) {
2081 cpu_dump_state(env, logfile, fprintf, 0);
2083 if (loglevel & CPU_LOG_TB_IN_ASM) {
2084 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2085 target_disas(logfile, pc_start, ctx.pc - pc_start, 1);
2086 fprintf(logfile, "\n");
2088 #endif
2091 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
2093 gen_intermediate_code_internal(env, tb, 0);
2096 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
2098 gen_intermediate_code_internal(env, tb, 1);
2101 CPUAlphaState * cpu_alpha_init (const char *cpu_model)
2103 CPUAlphaState *env;
2104 uint64_t hwpcb;
2106 env = qemu_mallocz(sizeof(CPUAlphaState));
2107 if (!env)
2108 return NULL;
2109 cpu_exec_init(env);
2110 alpha_translate_init();
2111 tlb_flush(env, 1);
2112 /* XXX: should not be hardcoded */
2113 env->implver = IMPLVER_2106x;
2114 env->ps = 0x1F00;
2115 #if defined (CONFIG_USER_ONLY)
2116 env->ps |= 1 << 3;
2117 #endif
2118 pal_init(env);
2119 /* Initialize IPR */
2120 hwpcb = env->ipr[IPR_PCBB];
2121 env->ipr[IPR_ASN] = 0;
2122 env->ipr[IPR_ASTEN] = 0;
2123 env->ipr[IPR_ASTSR] = 0;
2124 env->ipr[IPR_DATFX] = 0;
2125 /* XXX: fix this */
2126 // env->ipr[IPR_ESP] = ldq_raw(hwpcb + 8);
2127 // env->ipr[IPR_KSP] = ldq_raw(hwpcb + 0);
2128 // env->ipr[IPR_SSP] = ldq_raw(hwpcb + 16);
2129 // env->ipr[IPR_USP] = ldq_raw(hwpcb + 24);
2130 env->ipr[IPR_FEN] = 0;
2131 env->ipr[IPR_IPL] = 31;
2132 env->ipr[IPR_MCES] = 0;
2133 env->ipr[IPR_PERFMON] = 0; /* Implementation specific */
2134 // env->ipr[IPR_PTBR] = ldq_raw(hwpcb + 32);
2135 env->ipr[IPR_SISR] = 0;
2136 env->ipr[IPR_VIRBND] = -1ULL;
2138 return env;
2141 void gen_pc_load(CPUState *env, TranslationBlock *tb,
2142 unsigned long searched_pc, int pc_pos, void *puc)
2144 env->pc = gen_opc_pc[pc_pos];