ide: fix ATAPI command permissions
[qemu/ar7.git] / target-alpha / translate.c
blob2ba5fb80ae4986a941c53f86c9385e279f4aae7b
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, see <http://www.gnu.org/licenses/>.
20 #include "cpu.h"
21 #include "disas/disas.h"
22 #include "qemu/host-utils.h"
23 #include "tcg-op.h"
24 #include "exec/cpu_ldst.h"
26 #include "exec/helper-proto.h"
27 #include "exec/helper-gen.h"
29 #include "trace-tcg.h"
32 #undef ALPHA_DEBUG_DISAS
33 #define CONFIG_SOFTFLOAT_INLINE
35 #ifdef ALPHA_DEBUG_DISAS
36 # define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
37 #else
38 # define LOG_DISAS(...) do { } while (0)
39 #endif
41 typedef struct DisasContext DisasContext;
42 struct DisasContext {
43 struct TranslationBlock *tb;
44 uint64_t pc;
45 #ifndef CONFIG_USER_ONLY
46 uint64_t palbr;
47 #endif
48 int mem_idx;
50 /* Current rounding mode for this TB. */
51 int tb_rm;
52 /* Current flush-to-zero setting for this TB. */
53 int tb_ftz;
55 /* implver value for this CPU. */
56 int implver;
58 /* The set of registers active in the current context. */
59 TCGv *ir;
61 /* Temporaries for $31 and $f31 as source and destination. */
62 TCGv zero;
63 TCGv sink;
64 /* Temporary for immediate constants. */
65 TCGv lit;
67 bool singlestep_enabled;
70 /* Return values from translate_one, indicating the state of the TB.
71 Note that zero indicates that we are not exiting the TB. */
73 typedef enum {
74 NO_EXIT,
76 /* We have emitted one or more goto_tb. No fixup required. */
77 EXIT_GOTO_TB,
79 /* We are not using a goto_tb (for whatever reason), but have updated
80 the PC (for whatever reason), so there's no need to do it again on
81 exiting the TB. */
82 EXIT_PC_UPDATED,
84 /* We are exiting the TB, but have neither emitted a goto_tb, nor
85 updated the PC for the next instruction to be executed. */
86 EXIT_PC_STALE,
88 /* We are ending the TB with a noreturn function call, e.g. longjmp.
89 No following code will be executed. */
90 EXIT_NORETURN,
91 } ExitStatus;
93 /* global register indexes */
94 static TCGv_ptr cpu_env;
95 static TCGv cpu_std_ir[31];
96 static TCGv cpu_fir[31];
97 static TCGv cpu_pc;
98 static TCGv cpu_lock_addr;
99 static TCGv cpu_lock_st_addr;
100 static TCGv cpu_lock_value;
102 #ifndef CONFIG_USER_ONLY
103 static TCGv cpu_pal_ir[31];
104 #endif
106 #include "exec/gen-icount.h"
108 void alpha_translate_init(void)
110 #define DEF_VAR(V) { &cpu_##V, #V, offsetof(CPUAlphaState, V) }
112 typedef struct { TCGv *var; const char *name; int ofs; } GlobalVar;
113 static const GlobalVar vars[] = {
114 DEF_VAR(pc),
115 DEF_VAR(lock_addr),
116 DEF_VAR(lock_st_addr),
117 DEF_VAR(lock_value),
120 #undef DEF_VAR
122 /* Use the symbolic register names that match the disassembler. */
123 static const char greg_names[31][4] = {
124 "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
125 "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp",
126 "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
127 "t10", "t11", "ra", "t12", "at", "gp", "sp"
129 static const char freg_names[31][4] = {
130 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
131 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
132 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
133 "f24", "f25", "f26", "f27", "f28", "f29", "f30"
135 #ifndef CONFIG_USER_ONLY
136 static const char shadow_names[8][8] = {
137 "pal_t7", "pal_s0", "pal_s1", "pal_s2",
138 "pal_s3", "pal_s4", "pal_s5", "pal_t11"
140 #endif
142 static bool done_init = 0;
143 int i;
145 if (done_init) {
146 return;
148 done_init = 1;
150 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
152 for (i = 0; i < 31; i++) {
153 cpu_std_ir[i] = tcg_global_mem_new_i64(TCG_AREG0,
154 offsetof(CPUAlphaState, ir[i]),
155 greg_names[i]);
158 for (i = 0; i < 31; i++) {
159 cpu_fir[i] = tcg_global_mem_new_i64(TCG_AREG0,
160 offsetof(CPUAlphaState, fir[i]),
161 freg_names[i]);
164 #ifndef CONFIG_USER_ONLY
165 memcpy(cpu_pal_ir, cpu_std_ir, sizeof(cpu_pal_ir));
166 for (i = 0; i < 8; i++) {
167 int r = (i == 7 ? 25 : i + 8);
168 cpu_pal_ir[r] = tcg_global_mem_new_i64(TCG_AREG0,
169 offsetof(CPUAlphaState,
170 shadow[i]),
171 shadow_names[i]);
173 #endif
175 for (i = 0; i < ARRAY_SIZE(vars); ++i) {
176 const GlobalVar *v = &vars[i];
177 *v->var = tcg_global_mem_new_i64(TCG_AREG0, v->ofs, v->name);
181 static TCGv load_zero(DisasContext *ctx)
183 if (TCGV_IS_UNUSED_I64(ctx->zero)) {
184 ctx->zero = tcg_const_i64(0);
186 return ctx->zero;
189 static TCGv dest_sink(DisasContext *ctx)
191 if (TCGV_IS_UNUSED_I64(ctx->sink)) {
192 ctx->sink = tcg_temp_new();
194 return ctx->sink;
197 static TCGv load_gpr(DisasContext *ctx, unsigned reg)
199 if (likely(reg < 31)) {
200 return ctx->ir[reg];
201 } else {
202 return load_zero(ctx);
206 static TCGv load_gpr_lit(DisasContext *ctx, unsigned reg,
207 uint8_t lit, bool islit)
209 if (islit) {
210 ctx->lit = tcg_const_i64(lit);
211 return ctx->lit;
212 } else if (likely(reg < 31)) {
213 return ctx->ir[reg];
214 } else {
215 return load_zero(ctx);
219 static TCGv dest_gpr(DisasContext *ctx, unsigned reg)
221 if (likely(reg < 31)) {
222 return ctx->ir[reg];
223 } else {
224 return dest_sink(ctx);
228 static TCGv load_fpr(DisasContext *ctx, unsigned reg)
230 if (likely(reg < 31)) {
231 return cpu_fir[reg];
232 } else {
233 return load_zero(ctx);
237 static TCGv dest_fpr(DisasContext *ctx, unsigned reg)
239 if (likely(reg < 31)) {
240 return cpu_fir[reg];
241 } else {
242 return dest_sink(ctx);
246 static void gen_excp_1(int exception, int error_code)
248 TCGv_i32 tmp1, tmp2;
250 tmp1 = tcg_const_i32(exception);
251 tmp2 = tcg_const_i32(error_code);
252 gen_helper_excp(cpu_env, tmp1, tmp2);
253 tcg_temp_free_i32(tmp2);
254 tcg_temp_free_i32(tmp1);
257 static ExitStatus gen_excp(DisasContext *ctx, int exception, int error_code)
259 tcg_gen_movi_i64(cpu_pc, ctx->pc);
260 gen_excp_1(exception, error_code);
261 return EXIT_NORETURN;
264 static inline ExitStatus gen_invalid(DisasContext *ctx)
266 return gen_excp(ctx, EXCP_OPCDEC, 0);
269 static inline void gen_qemu_ldf(TCGv t0, TCGv t1, int flags)
271 TCGv_i32 tmp32 = tcg_temp_new_i32();
272 tcg_gen_qemu_ld_i32(tmp32, t1, flags, MO_LEUL);
273 gen_helper_memory_to_f(t0, tmp32);
274 tcg_temp_free_i32(tmp32);
277 static inline void gen_qemu_ldg(TCGv t0, TCGv t1, int flags)
279 TCGv tmp = tcg_temp_new();
280 tcg_gen_qemu_ld_i64(tmp, t1, flags, MO_LEQ);
281 gen_helper_memory_to_g(t0, tmp);
282 tcg_temp_free(tmp);
285 static inline void gen_qemu_lds(TCGv t0, TCGv t1, int flags)
287 TCGv_i32 tmp32 = tcg_temp_new_i32();
288 tcg_gen_qemu_ld_i32(tmp32, t1, flags, MO_LEUL);
289 gen_helper_memory_to_s(t0, tmp32);
290 tcg_temp_free_i32(tmp32);
293 static inline void gen_qemu_ldl_l(TCGv t0, TCGv t1, int flags)
295 tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LESL);
296 tcg_gen_mov_i64(cpu_lock_addr, t1);
297 tcg_gen_mov_i64(cpu_lock_value, t0);
300 static inline void gen_qemu_ldq_l(TCGv t0, TCGv t1, int flags)
302 tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LEQ);
303 tcg_gen_mov_i64(cpu_lock_addr, t1);
304 tcg_gen_mov_i64(cpu_lock_value, t0);
307 static inline void gen_load_mem(DisasContext *ctx,
308 void (*tcg_gen_qemu_load)(TCGv t0, TCGv t1,
309 int flags),
310 int ra, int rb, int32_t disp16, bool fp,
311 bool clear)
313 TCGv tmp, addr, va;
315 /* LDQ_U with ra $31 is UNOP. Other various loads are forms of
316 prefetches, which we can treat as nops. No worries about
317 missed exceptions here. */
318 if (unlikely(ra == 31)) {
319 return;
322 tmp = tcg_temp_new();
323 addr = load_gpr(ctx, rb);
325 if (disp16) {
326 tcg_gen_addi_i64(tmp, addr, disp16);
327 addr = tmp;
329 if (clear) {
330 tcg_gen_andi_i64(tmp, addr, ~0x7);
331 addr = tmp;
334 va = (fp ? cpu_fir[ra] : ctx->ir[ra]);
335 tcg_gen_qemu_load(va, addr, ctx->mem_idx);
337 tcg_temp_free(tmp);
340 static inline void gen_qemu_stf(TCGv t0, TCGv t1, int flags)
342 TCGv_i32 tmp32 = tcg_temp_new_i32();
343 gen_helper_f_to_memory(tmp32, t0);
344 tcg_gen_qemu_st_i32(tmp32, t1, flags, MO_LEUL);
345 tcg_temp_free_i32(tmp32);
348 static inline void gen_qemu_stg(TCGv t0, TCGv t1, int flags)
350 TCGv tmp = tcg_temp_new();
351 gen_helper_g_to_memory(tmp, t0);
352 tcg_gen_qemu_st_i64(tmp, t1, flags, MO_LEQ);
353 tcg_temp_free(tmp);
356 static inline void gen_qemu_sts(TCGv t0, TCGv t1, int flags)
358 TCGv_i32 tmp32 = tcg_temp_new_i32();
359 gen_helper_s_to_memory(tmp32, t0);
360 tcg_gen_qemu_st_i32(tmp32, t1, flags, MO_LEUL);
361 tcg_temp_free_i32(tmp32);
364 static inline void gen_store_mem(DisasContext *ctx,
365 void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1,
366 int flags),
367 int ra, int rb, int32_t disp16, bool fp,
368 bool clear)
370 TCGv tmp, addr, va;
372 tmp = tcg_temp_new();
373 addr = load_gpr(ctx, rb);
375 if (disp16) {
376 tcg_gen_addi_i64(tmp, addr, disp16);
377 addr = tmp;
379 if (clear) {
380 tcg_gen_andi_i64(tmp, addr, ~0x7);
381 addr = tmp;
384 va = (fp ? load_fpr(ctx, ra) : load_gpr(ctx, ra));
385 tcg_gen_qemu_store(va, addr, ctx->mem_idx);
387 tcg_temp_free(tmp);
390 static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
391 int32_t disp16, int quad)
393 TCGv addr;
395 if (ra == 31) {
396 /* ??? Don't bother storing anything. The user can't tell
397 the difference, since the zero register always reads zero. */
398 return NO_EXIT;
401 #if defined(CONFIG_USER_ONLY)
402 addr = cpu_lock_st_addr;
403 #else
404 addr = tcg_temp_local_new();
405 #endif
407 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
409 #if defined(CONFIG_USER_ONLY)
410 /* ??? This is handled via a complicated version of compare-and-swap
411 in the cpu_loop. Hopefully one day we'll have a real CAS opcode
412 in TCG so that this isn't necessary. */
413 return gen_excp(ctx, quad ? EXCP_STQ_C : EXCP_STL_C, ra);
414 #else
415 /* ??? In system mode we are never multi-threaded, so CAS can be
416 implemented via a non-atomic load-compare-store sequence. */
418 TCGLabel *lab_fail, *lab_done;
419 TCGv val;
421 lab_fail = gen_new_label();
422 lab_done = gen_new_label();
423 tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
425 val = tcg_temp_new();
426 tcg_gen_qemu_ld_i64(val, addr, ctx->mem_idx, quad ? MO_LEQ : MO_LESL);
427 tcg_gen_brcond_i64(TCG_COND_NE, val, cpu_lock_value, lab_fail);
429 tcg_gen_qemu_st_i64(ctx->ir[ra], addr, ctx->mem_idx,
430 quad ? MO_LEQ : MO_LEUL);
431 tcg_gen_movi_i64(ctx->ir[ra], 1);
432 tcg_gen_br(lab_done);
434 gen_set_label(lab_fail);
435 tcg_gen_movi_i64(ctx->ir[ra], 0);
437 gen_set_label(lab_done);
438 tcg_gen_movi_i64(cpu_lock_addr, -1);
440 tcg_temp_free(addr);
441 return NO_EXIT;
443 #endif
446 static bool in_superpage(DisasContext *ctx, int64_t addr)
448 return ((ctx->tb->flags & TB_FLAGS_USER_MODE) == 0
449 && addr < 0
450 && ((addr >> 41) & 3) == 2
451 && addr >> TARGET_VIRT_ADDR_SPACE_BITS == addr >> 63);
454 static bool use_goto_tb(DisasContext *ctx, uint64_t dest)
456 /* Suppress goto_tb in the case of single-steping and IO. */
457 if ((ctx->tb->cflags & CF_LAST_IO)
458 || ctx->singlestep_enabled || singlestep) {
459 return false;
461 /* If the destination is in the superpage, the page perms can't change. */
462 if (in_superpage(ctx, dest)) {
463 return true;
465 /* Check for the dest on the same page as the start of the TB. */
466 return ((ctx->tb->pc ^ dest) & TARGET_PAGE_MASK) == 0;
469 static ExitStatus gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
471 uint64_t dest = ctx->pc + (disp << 2);
473 if (ra != 31) {
474 tcg_gen_movi_i64(ctx->ir[ra], ctx->pc);
477 /* Notice branch-to-next; used to initialize RA with the PC. */
478 if (disp == 0) {
479 return 0;
480 } else if (use_goto_tb(ctx, dest)) {
481 tcg_gen_goto_tb(0);
482 tcg_gen_movi_i64(cpu_pc, dest);
483 tcg_gen_exit_tb((uintptr_t)ctx->tb);
484 return EXIT_GOTO_TB;
485 } else {
486 tcg_gen_movi_i64(cpu_pc, dest);
487 return EXIT_PC_UPDATED;
491 static ExitStatus gen_bcond_internal(DisasContext *ctx, TCGCond cond,
492 TCGv cmp, int32_t disp)
494 uint64_t dest = ctx->pc + (disp << 2);
495 TCGLabel *lab_true = gen_new_label();
497 if (use_goto_tb(ctx, dest)) {
498 tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
500 tcg_gen_goto_tb(0);
501 tcg_gen_movi_i64(cpu_pc, ctx->pc);
502 tcg_gen_exit_tb((uintptr_t)ctx->tb);
504 gen_set_label(lab_true);
505 tcg_gen_goto_tb(1);
506 tcg_gen_movi_i64(cpu_pc, dest);
507 tcg_gen_exit_tb((uintptr_t)ctx->tb + 1);
509 return EXIT_GOTO_TB;
510 } else {
511 TCGv_i64 z = tcg_const_i64(0);
512 TCGv_i64 d = tcg_const_i64(dest);
513 TCGv_i64 p = tcg_const_i64(ctx->pc);
515 tcg_gen_movcond_i64(cond, cpu_pc, cmp, z, d, p);
517 tcg_temp_free_i64(z);
518 tcg_temp_free_i64(d);
519 tcg_temp_free_i64(p);
520 return EXIT_PC_UPDATED;
524 static ExitStatus gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
525 int32_t disp, int mask)
527 TCGv cmp_tmp;
529 if (mask) {
530 cmp_tmp = tcg_temp_new();
531 tcg_gen_andi_i64(cmp_tmp, load_gpr(ctx, ra), 1);
532 } else {
533 cmp_tmp = load_gpr(ctx, ra);
536 return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
539 /* Fold -0.0 for comparison with COND. */
541 static void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src)
543 uint64_t mzero = 1ull << 63;
545 switch (cond) {
546 case TCG_COND_LE:
547 case TCG_COND_GT:
548 /* For <= or >, the -0.0 value directly compares the way we want. */
549 tcg_gen_mov_i64(dest, src);
550 break;
552 case TCG_COND_EQ:
553 case TCG_COND_NE:
554 /* For == or !=, we can simply mask off the sign bit and compare. */
555 tcg_gen_andi_i64(dest, src, mzero - 1);
556 break;
558 case TCG_COND_GE:
559 case TCG_COND_LT:
560 /* For >= or <, map -0.0 to +0.0 via comparison and mask. */
561 tcg_gen_setcondi_i64(TCG_COND_NE, dest, src, mzero);
562 tcg_gen_neg_i64(dest, dest);
563 tcg_gen_and_i64(dest, dest, src);
564 break;
566 default:
567 abort();
571 static ExitStatus gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
572 int32_t disp)
574 TCGv cmp_tmp = tcg_temp_new();
575 gen_fold_mzero(cond, cmp_tmp, load_fpr(ctx, ra));
576 return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
579 static void gen_fcmov(DisasContext *ctx, TCGCond cond, int ra, int rb, int rc)
581 TCGv_i64 va, vb, z;
583 z = load_zero(ctx);
584 vb = load_fpr(ctx, rb);
585 va = tcg_temp_new();
586 gen_fold_mzero(cond, va, load_fpr(ctx, ra));
588 tcg_gen_movcond_i64(cond, dest_fpr(ctx, rc), va, z, vb, load_fpr(ctx, rc));
590 tcg_temp_free(va);
593 #define QUAL_RM_N 0x080 /* Round mode nearest even */
594 #define QUAL_RM_C 0x000 /* Round mode chopped */
595 #define QUAL_RM_M 0x040 /* Round mode minus infinity */
596 #define QUAL_RM_D 0x0c0 /* Round mode dynamic */
597 #define QUAL_RM_MASK 0x0c0
599 #define QUAL_U 0x100 /* Underflow enable (fp output) */
600 #define QUAL_V 0x100 /* Overflow enable (int output) */
601 #define QUAL_S 0x400 /* Software completion enable */
602 #define QUAL_I 0x200 /* Inexact detection enable */
604 static void gen_qual_roundmode(DisasContext *ctx, int fn11)
606 TCGv_i32 tmp;
608 fn11 &= QUAL_RM_MASK;
609 if (fn11 == ctx->tb_rm) {
610 return;
612 ctx->tb_rm = fn11;
614 tmp = tcg_temp_new_i32();
615 switch (fn11) {
616 case QUAL_RM_N:
617 tcg_gen_movi_i32(tmp, float_round_nearest_even);
618 break;
619 case QUAL_RM_C:
620 tcg_gen_movi_i32(tmp, float_round_to_zero);
621 break;
622 case QUAL_RM_M:
623 tcg_gen_movi_i32(tmp, float_round_down);
624 break;
625 case QUAL_RM_D:
626 tcg_gen_ld8u_i32(tmp, cpu_env,
627 offsetof(CPUAlphaState, fpcr_dyn_round));
628 break;
631 #if defined(CONFIG_SOFTFLOAT_INLINE)
632 /* ??? The "fpu/softfloat.h" interface is to call set_float_rounding_mode.
633 With CONFIG_SOFTFLOAT that expands to an out-of-line call that just
634 sets the one field. */
635 tcg_gen_st8_i32(tmp, cpu_env,
636 offsetof(CPUAlphaState, fp_status.float_rounding_mode));
637 #else
638 gen_helper_setroundmode(tmp);
639 #endif
641 tcg_temp_free_i32(tmp);
644 static void gen_qual_flushzero(DisasContext *ctx, int fn11)
646 TCGv_i32 tmp;
648 fn11 &= QUAL_U;
649 if (fn11 == ctx->tb_ftz) {
650 return;
652 ctx->tb_ftz = fn11;
654 tmp = tcg_temp_new_i32();
655 if (fn11) {
656 /* Underflow is enabled, use the FPCR setting. */
657 tcg_gen_ld8u_i32(tmp, cpu_env,
658 offsetof(CPUAlphaState, fpcr_flush_to_zero));
659 } else {
660 /* Underflow is disabled, force flush-to-zero. */
661 tcg_gen_movi_i32(tmp, 1);
664 #if defined(CONFIG_SOFTFLOAT_INLINE)
665 tcg_gen_st8_i32(tmp, cpu_env,
666 offsetof(CPUAlphaState, fp_status.flush_to_zero));
667 #else
668 gen_helper_setflushzero(tmp);
669 #endif
671 tcg_temp_free_i32(tmp);
674 static TCGv gen_ieee_input(DisasContext *ctx, int reg, int fn11, int is_cmp)
676 TCGv val;
678 if (unlikely(reg == 31)) {
679 val = load_zero(ctx);
680 } else {
681 val = cpu_fir[reg];
682 if ((fn11 & QUAL_S) == 0) {
683 if (is_cmp) {
684 gen_helper_ieee_input_cmp(cpu_env, val);
685 } else {
686 gen_helper_ieee_input(cpu_env, val);
688 } else {
689 #ifndef CONFIG_USER_ONLY
690 /* In system mode, raise exceptions for denormals like real
691 hardware. In user mode, proceed as if the OS completion
692 handler is handling the denormal as per spec. */
693 gen_helper_ieee_input_s(cpu_env, val);
694 #endif
697 return val;
700 static void gen_fp_exc_raise(int rc, int fn11)
702 /* ??? We ought to be able to do something with imprecise exceptions.
703 E.g. notice we're still in the trap shadow of something within the
704 TB and do not generate the code to signal the exception; end the TB
705 when an exception is forced to arrive, either by consumption of a
706 register value or TRAPB or EXCB. */
707 TCGv_i32 reg, ign;
708 uint32_t ignore = 0;
710 if (!(fn11 & QUAL_U)) {
711 /* Note that QUAL_U == QUAL_V, so ignore either. */
712 ignore |= FPCR_UNF | FPCR_IOV;
714 if (!(fn11 & QUAL_I)) {
715 ignore |= FPCR_INE;
717 ign = tcg_const_i32(ignore);
719 /* ??? Pass in the regno of the destination so that the helper can
720 set EXC_MASK, which contains a bitmask of destination registers
721 that have caused arithmetic traps. A simple userspace emulation
722 does not require this. We do need it for a guest kernel's entArith,
723 or if we were to do something clever with imprecise exceptions. */
724 reg = tcg_const_i32(rc + 32);
725 if (fn11 & QUAL_S) {
726 gen_helper_fp_exc_raise_s(cpu_env, ign, reg);
727 } else {
728 gen_helper_fp_exc_raise(cpu_env, ign, reg);
731 tcg_temp_free_i32(reg);
732 tcg_temp_free_i32(ign);
735 static void gen_cvtlq(TCGv vc, TCGv vb)
737 TCGv tmp = tcg_temp_new();
739 /* The arithmetic right shift here, plus the sign-extended mask below
740 yields a sign-extended result without an explicit ext32s_i64. */
741 tcg_gen_sari_i64(tmp, vb, 32);
742 tcg_gen_shri_i64(vc, vb, 29);
743 tcg_gen_andi_i64(tmp, tmp, (int32_t)0xc0000000);
744 tcg_gen_andi_i64(vc, vc, 0x3fffffff);
745 tcg_gen_or_i64(vc, vc, tmp);
747 tcg_temp_free(tmp);
750 static void gen_ieee_arith2(DisasContext *ctx,
751 void (*helper)(TCGv, TCGv_ptr, TCGv),
752 int rb, int rc, int fn11)
754 TCGv vb;
756 gen_qual_roundmode(ctx, fn11);
757 gen_qual_flushzero(ctx, fn11);
759 vb = gen_ieee_input(ctx, rb, fn11, 0);
760 helper(dest_fpr(ctx, rc), cpu_env, vb);
762 gen_fp_exc_raise(rc, fn11);
765 #define IEEE_ARITH2(name) \
766 static inline void glue(gen_, name)(DisasContext *ctx, \
767 int rb, int rc, int fn11) \
769 gen_ieee_arith2(ctx, gen_helper_##name, rb, rc, fn11); \
771 IEEE_ARITH2(sqrts)
772 IEEE_ARITH2(sqrtt)
773 IEEE_ARITH2(cvtst)
774 IEEE_ARITH2(cvtts)
776 static void gen_cvttq(DisasContext *ctx, int rb, int rc, int fn11)
778 TCGv vb, vc;
780 /* No need to set flushzero, since we have an integer output. */
781 vb = gen_ieee_input(ctx, rb, fn11, 0);
782 vc = dest_fpr(ctx, rc);
784 /* Almost all integer conversions use cropped rounding;
785 special case that. */
786 if ((fn11 & QUAL_RM_MASK) == QUAL_RM_C) {
787 gen_helper_cvttq_c(vc, cpu_env, vb);
788 } else {
789 gen_qual_roundmode(ctx, fn11);
790 gen_helper_cvttq(vc, cpu_env, vb);
792 gen_fp_exc_raise(rc, fn11);
795 static void gen_ieee_intcvt(DisasContext *ctx,
796 void (*helper)(TCGv, TCGv_ptr, TCGv),
797 int rb, int rc, int fn11)
799 TCGv vb, vc;
801 gen_qual_roundmode(ctx, fn11);
802 vb = load_fpr(ctx, rb);
803 vc = dest_fpr(ctx, rc);
805 /* The only exception that can be raised by integer conversion
806 is inexact. Thus we only need to worry about exceptions when
807 inexact handling is requested. */
808 if (fn11 & QUAL_I) {
809 helper(vc, cpu_env, vb);
810 gen_fp_exc_raise(rc, fn11);
811 } else {
812 helper(vc, cpu_env, vb);
816 #define IEEE_INTCVT(name) \
817 static inline void glue(gen_, name)(DisasContext *ctx, \
818 int rb, int rc, int fn11) \
820 gen_ieee_intcvt(ctx, gen_helper_##name, rb, rc, fn11); \
822 IEEE_INTCVT(cvtqs)
823 IEEE_INTCVT(cvtqt)
825 static void gen_cpy_mask(TCGv vc, TCGv va, TCGv vb, bool inv_a, uint64_t mask)
827 TCGv vmask = tcg_const_i64(mask);
828 TCGv tmp = tcg_temp_new_i64();
830 if (inv_a) {
831 tcg_gen_andc_i64(tmp, vmask, va);
832 } else {
833 tcg_gen_and_i64(tmp, va, vmask);
836 tcg_gen_andc_i64(vc, vb, vmask);
837 tcg_gen_or_i64(vc, vc, tmp);
839 tcg_temp_free(vmask);
840 tcg_temp_free(tmp);
843 static void gen_ieee_arith3(DisasContext *ctx,
844 void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
845 int ra, int rb, int rc, int fn11)
847 TCGv va, vb, vc;
849 gen_qual_roundmode(ctx, fn11);
850 gen_qual_flushzero(ctx, fn11);
852 va = gen_ieee_input(ctx, ra, fn11, 0);
853 vb = gen_ieee_input(ctx, rb, fn11, 0);
854 vc = dest_fpr(ctx, rc);
855 helper(vc, cpu_env, va, vb);
857 gen_fp_exc_raise(rc, fn11);
860 #define IEEE_ARITH3(name) \
861 static inline void glue(gen_, name)(DisasContext *ctx, \
862 int ra, int rb, int rc, int fn11) \
864 gen_ieee_arith3(ctx, gen_helper_##name, ra, rb, rc, fn11); \
866 IEEE_ARITH3(adds)
867 IEEE_ARITH3(subs)
868 IEEE_ARITH3(muls)
869 IEEE_ARITH3(divs)
870 IEEE_ARITH3(addt)
871 IEEE_ARITH3(subt)
872 IEEE_ARITH3(mult)
873 IEEE_ARITH3(divt)
875 static void gen_ieee_compare(DisasContext *ctx,
876 void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
877 int ra, int rb, int rc, int fn11)
879 TCGv va, vb, vc;
881 va = gen_ieee_input(ctx, ra, fn11, 1);
882 vb = gen_ieee_input(ctx, rb, fn11, 1);
883 vc = dest_fpr(ctx, rc);
884 helper(vc, cpu_env, va, vb);
886 gen_fp_exc_raise(rc, fn11);
889 #define IEEE_CMP3(name) \
890 static inline void glue(gen_, name)(DisasContext *ctx, \
891 int ra, int rb, int rc, int fn11) \
893 gen_ieee_compare(ctx, gen_helper_##name, ra, rb, rc, fn11); \
895 IEEE_CMP3(cmptun)
896 IEEE_CMP3(cmpteq)
897 IEEE_CMP3(cmptlt)
898 IEEE_CMP3(cmptle)
900 static inline uint64_t zapnot_mask(uint8_t lit)
902 uint64_t mask = 0;
903 int i;
905 for (i = 0; i < 8; ++i) {
906 if ((lit >> i) & 1) {
907 mask |= 0xffull << (i * 8);
910 return mask;
913 /* Implement zapnot with an immediate operand, which expands to some
914 form of immediate AND. This is a basic building block in the
915 definition of many of the other byte manipulation instructions. */
916 static void gen_zapnoti(TCGv dest, TCGv src, uint8_t lit)
918 switch (lit) {
919 case 0x00:
920 tcg_gen_movi_i64(dest, 0);
921 break;
922 case 0x01:
923 tcg_gen_ext8u_i64(dest, src);
924 break;
925 case 0x03:
926 tcg_gen_ext16u_i64(dest, src);
927 break;
928 case 0x0f:
929 tcg_gen_ext32u_i64(dest, src);
930 break;
931 case 0xff:
932 tcg_gen_mov_i64(dest, src);
933 break;
934 default:
935 tcg_gen_andi_i64(dest, src, zapnot_mask(lit));
936 break;
940 /* EXTWH, EXTLH, EXTQH */
941 static void gen_ext_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
942 uint8_t lit, uint8_t byte_mask)
944 if (islit) {
945 tcg_gen_shli_i64(vc, va, (64 - lit * 8) & 0x3f);
946 } else {
947 TCGv tmp = tcg_temp_new();
948 tcg_gen_shli_i64(tmp, load_gpr(ctx, rb), 3);
949 tcg_gen_neg_i64(tmp, tmp);
950 tcg_gen_andi_i64(tmp, tmp, 0x3f);
951 tcg_gen_shl_i64(vc, va, tmp);
952 tcg_temp_free(tmp);
954 gen_zapnoti(vc, vc, byte_mask);
957 /* EXTBL, EXTWL, EXTLL, EXTQL */
958 static void gen_ext_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
959 uint8_t lit, uint8_t byte_mask)
961 if (islit) {
962 tcg_gen_shri_i64(vc, va, (lit & 7) * 8);
963 } else {
964 TCGv tmp = tcg_temp_new();
965 tcg_gen_andi_i64(tmp, load_gpr(ctx, rb), 7);
966 tcg_gen_shli_i64(tmp, tmp, 3);
967 tcg_gen_shr_i64(vc, va, tmp);
968 tcg_temp_free(tmp);
970 gen_zapnoti(vc, vc, byte_mask);
973 /* INSWH, INSLH, INSQH */
974 static void gen_ins_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
975 uint8_t lit, uint8_t byte_mask)
977 TCGv tmp = tcg_temp_new();
979 /* The instruction description has us left-shift the byte mask and extract
980 bits <15:8> and apply that zap at the end. This is equivalent to simply
981 performing the zap first and shifting afterward. */
982 gen_zapnoti(tmp, va, byte_mask);
984 if (islit) {
985 lit &= 7;
986 if (unlikely(lit == 0)) {
987 tcg_gen_movi_i64(vc, 0);
988 } else {
989 tcg_gen_shri_i64(vc, tmp, 64 - lit * 8);
991 } else {
992 TCGv shift = tcg_temp_new();
994 /* If (B & 7) == 0, we need to shift by 64 and leave a zero. Do this
995 portably by splitting the shift into two parts: shift_count-1 and 1.
996 Arrange for the -1 by using ones-complement instead of
997 twos-complement in the negation: ~(B * 8) & 63. */
999 tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3);
1000 tcg_gen_not_i64(shift, shift);
1001 tcg_gen_andi_i64(shift, shift, 0x3f);
1003 tcg_gen_shr_i64(vc, tmp, shift);
1004 tcg_gen_shri_i64(vc, vc, 1);
1005 tcg_temp_free(shift);
1007 tcg_temp_free(tmp);
1010 /* INSBL, INSWL, INSLL, INSQL */
1011 static void gen_ins_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
1012 uint8_t lit, uint8_t byte_mask)
1014 TCGv tmp = tcg_temp_new();
1016 /* The instruction description has us left-shift the byte mask
1017 the same number of byte slots as the data and apply the zap
1018 at the end. This is equivalent to simply performing the zap
1019 first and shifting afterward. */
1020 gen_zapnoti(tmp, va, byte_mask);
1022 if (islit) {
1023 tcg_gen_shli_i64(vc, tmp, (lit & 7) * 8);
1024 } else {
1025 TCGv shift = tcg_temp_new();
1026 tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
1027 tcg_gen_shli_i64(shift, shift, 3);
1028 tcg_gen_shl_i64(vc, tmp, shift);
1029 tcg_temp_free(shift);
1031 tcg_temp_free(tmp);
1034 /* MSKWH, MSKLH, MSKQH */
1035 static void gen_msk_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
1036 uint8_t lit, uint8_t byte_mask)
1038 if (islit) {
1039 gen_zapnoti(vc, va, ~((byte_mask << (lit & 7)) >> 8));
1040 } else {
1041 TCGv shift = tcg_temp_new();
1042 TCGv mask = tcg_temp_new();
1044 /* The instruction description is as above, where the byte_mask
1045 is shifted left, and then we extract bits <15:8>. This can be
1046 emulated with a right-shift on the expanded byte mask. This
1047 requires extra care because for an input <2:0> == 0 we need a
1048 shift of 64 bits in order to generate a zero. This is done by
1049 splitting the shift into two parts, the variable shift - 1
1050 followed by a constant 1 shift. The code we expand below is
1051 equivalent to ~(B * 8) & 63. */
1053 tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3);
1054 tcg_gen_not_i64(shift, shift);
1055 tcg_gen_andi_i64(shift, shift, 0x3f);
1056 tcg_gen_movi_i64(mask, zapnot_mask (byte_mask));
1057 tcg_gen_shr_i64(mask, mask, shift);
1058 tcg_gen_shri_i64(mask, mask, 1);
1060 tcg_gen_andc_i64(vc, va, mask);
1062 tcg_temp_free(mask);
1063 tcg_temp_free(shift);
1067 /* MSKBL, MSKWL, MSKLL, MSKQL */
1068 static void gen_msk_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
1069 uint8_t lit, uint8_t byte_mask)
1071 if (islit) {
1072 gen_zapnoti(vc, va, ~(byte_mask << (lit & 7)));
1073 } else {
1074 TCGv shift = tcg_temp_new();
1075 TCGv mask = tcg_temp_new();
1077 tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
1078 tcg_gen_shli_i64(shift, shift, 3);
1079 tcg_gen_movi_i64(mask, zapnot_mask(byte_mask));
1080 tcg_gen_shl_i64(mask, mask, shift);
1082 tcg_gen_andc_i64(vc, va, mask);
1084 tcg_temp_free(mask);
1085 tcg_temp_free(shift);
1089 static void gen_rx(DisasContext *ctx, int ra, int set)
1091 TCGv_i32 tmp;
1093 if (ra != 31) {
1094 tcg_gen_ld8u_i64(ctx->ir[ra], cpu_env,
1095 offsetof(CPUAlphaState, intr_flag));
1098 tmp = tcg_const_i32(set);
1099 tcg_gen_st8_i32(tmp, cpu_env, offsetof(CPUAlphaState, intr_flag));
1100 tcg_temp_free_i32(tmp);
1103 static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
1105 /* We're emulating OSF/1 PALcode. Many of these are trivial access
1106 to internal cpu registers. */
1108 /* Unprivileged PAL call */
1109 if (palcode >= 0x80 && palcode < 0xC0) {
1110 switch (palcode) {
1111 case 0x86:
1112 /* IMB */
1113 /* No-op inside QEMU. */
1114 break;
1115 case 0x9E:
1116 /* RDUNIQUE */
1117 tcg_gen_ld_i64(ctx->ir[IR_V0], cpu_env,
1118 offsetof(CPUAlphaState, unique));
1119 break;
1120 case 0x9F:
1121 /* WRUNIQUE */
1122 tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env,
1123 offsetof(CPUAlphaState, unique));
1124 break;
1125 default:
1126 palcode &= 0xbf;
1127 goto do_call_pal;
1129 return NO_EXIT;
1132 #ifndef CONFIG_USER_ONLY
1133 /* Privileged PAL code */
1134 if (palcode < 0x40 && (ctx->tb->flags & TB_FLAGS_USER_MODE) == 0) {
1135 switch (palcode) {
1136 case 0x01:
1137 /* CFLUSH */
1138 /* No-op inside QEMU. */
1139 break;
1140 case 0x02:
1141 /* DRAINA */
1142 /* No-op inside QEMU. */
1143 break;
1144 case 0x2D:
1145 /* WRVPTPTR */
1146 tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env,
1147 offsetof(CPUAlphaState, vptptr));
1148 break;
1149 case 0x31:
1150 /* WRVAL */
1151 tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env,
1152 offsetof(CPUAlphaState, sysval));
1153 break;
1154 case 0x32:
1155 /* RDVAL */
1156 tcg_gen_ld_i64(ctx->ir[IR_V0], cpu_env,
1157 offsetof(CPUAlphaState, sysval));
1158 break;
1160 case 0x35: {
1161 /* SWPIPL */
1162 TCGv tmp;
1164 /* Note that we already know we're in kernel mode, so we know
1165 that PS only contains the 3 IPL bits. */
1166 tcg_gen_ld8u_i64(ctx->ir[IR_V0], cpu_env,
1167 offsetof(CPUAlphaState, ps));
1169 /* But make sure and store only the 3 IPL bits from the user. */
1170 tmp = tcg_temp_new();
1171 tcg_gen_andi_i64(tmp, ctx->ir[IR_A0], PS_INT_MASK);
1172 tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, ps));
1173 tcg_temp_free(tmp);
1174 break;
1177 case 0x36:
1178 /* RDPS */
1179 tcg_gen_ld8u_i64(ctx->ir[IR_V0], cpu_env,
1180 offsetof(CPUAlphaState, ps));
1181 break;
1182 case 0x38:
1183 /* WRUSP */
1184 tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env,
1185 offsetof(CPUAlphaState, usp));
1186 break;
1187 case 0x3A:
1188 /* RDUSP */
1189 tcg_gen_ld_i64(ctx->ir[IR_V0], cpu_env,
1190 offsetof(CPUAlphaState, usp));
1191 break;
1192 case 0x3C:
1193 /* WHAMI */
1194 tcg_gen_ld32s_i64(ctx->ir[IR_V0], cpu_env,
1195 -offsetof(AlphaCPU, env) + offsetof(CPUState, cpu_index));
1196 break;
1198 default:
1199 palcode &= 0x3f;
1200 goto do_call_pal;
1202 return NO_EXIT;
1204 #endif
1205 return gen_invalid(ctx);
1207 do_call_pal:
1208 #ifdef CONFIG_USER_ONLY
1209 return gen_excp(ctx, EXCP_CALL_PAL, palcode);
1210 #else
1212 TCGv tmp = tcg_temp_new();
1213 uint64_t exc_addr = ctx->pc;
1214 uint64_t entry = ctx->palbr;
1216 if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
1217 exc_addr |= 1;
1218 } else {
1219 tcg_gen_movi_i64(tmp, 1);
1220 tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, pal_mode));
1223 tcg_gen_movi_i64(tmp, exc_addr);
1224 tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUAlphaState, exc_addr));
1225 tcg_temp_free(tmp);
1227 entry += (palcode & 0x80
1228 ? 0x2000 + (palcode - 0x80) * 64
1229 : 0x1000 + palcode * 64);
1231 /* Since the destination is running in PALmode, we don't really
1232 need the page permissions check. We'll see the existence of
1233 the page when we create the TB, and we'll flush all TBs if
1234 we change the PAL base register. */
1235 if (!ctx->singlestep_enabled && !(ctx->tb->cflags & CF_LAST_IO)) {
1236 tcg_gen_goto_tb(0);
1237 tcg_gen_movi_i64(cpu_pc, entry);
1238 tcg_gen_exit_tb((uintptr_t)ctx->tb);
1239 return EXIT_GOTO_TB;
1240 } else {
1241 tcg_gen_movi_i64(cpu_pc, entry);
1242 return EXIT_PC_UPDATED;
1245 #endif
1248 #ifndef CONFIG_USER_ONLY
1250 #define PR_BYTE 0x100000
1251 #define PR_LONG 0x200000
1253 static int cpu_pr_data(int pr)
1255 switch (pr) {
1256 case 0: return offsetof(CPUAlphaState, ps) | PR_BYTE;
1257 case 1: return offsetof(CPUAlphaState, fen) | PR_BYTE;
1258 case 2: return offsetof(CPUAlphaState, pcc_ofs) | PR_LONG;
1259 case 3: return offsetof(CPUAlphaState, trap_arg0);
1260 case 4: return offsetof(CPUAlphaState, trap_arg1);
1261 case 5: return offsetof(CPUAlphaState, trap_arg2);
1262 case 6: return offsetof(CPUAlphaState, exc_addr);
1263 case 7: return offsetof(CPUAlphaState, palbr);
1264 case 8: return offsetof(CPUAlphaState, ptbr);
1265 case 9: return offsetof(CPUAlphaState, vptptr);
1266 case 10: return offsetof(CPUAlphaState, unique);
1267 case 11: return offsetof(CPUAlphaState, sysval);
1268 case 12: return offsetof(CPUAlphaState, usp);
1270 case 40 ... 63:
1271 return offsetof(CPUAlphaState, scratch[pr - 40]);
1273 case 251:
1274 return offsetof(CPUAlphaState, alarm_expire);
1276 return 0;
1279 static ExitStatus gen_mfpr(DisasContext *ctx, TCGv va, int regno)
1281 void (*helper)(TCGv);
1282 int data;
1284 switch (regno) {
1285 case 32 ... 39:
1286 /* Accessing the "non-shadow" general registers. */
1287 regno = regno == 39 ? 25 : regno - 32 + 8;
1288 tcg_gen_mov_i64(va, cpu_std_ir[regno]);
1289 break;
1291 case 250: /* WALLTIME */
1292 helper = gen_helper_get_walltime;
1293 goto do_helper;
1294 case 249: /* VMTIME */
1295 helper = gen_helper_get_vmtime;
1296 do_helper:
1297 if (use_icount) {
1298 gen_io_start();
1299 helper(va);
1300 gen_io_end();
1301 return EXIT_PC_STALE;
1302 } else {
1303 helper(va);
1305 break;
1307 default:
1308 /* The basic registers are data only, and unknown registers
1309 are read-zero, write-ignore. */
1310 data = cpu_pr_data(regno);
1311 if (data == 0) {
1312 tcg_gen_movi_i64(va, 0);
1313 } else if (data & PR_BYTE) {
1314 tcg_gen_ld8u_i64(va, cpu_env, data & ~PR_BYTE);
1315 } else if (data & PR_LONG) {
1316 tcg_gen_ld32s_i64(va, cpu_env, data & ~PR_LONG);
1317 } else {
1318 tcg_gen_ld_i64(va, cpu_env, data);
1320 break;
1323 return NO_EXIT;
1326 static ExitStatus gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
1328 TCGv tmp;
1329 int data;
1331 switch (regno) {
1332 case 255:
1333 /* TBIA */
1334 gen_helper_tbia(cpu_env);
1335 break;
1337 case 254:
1338 /* TBIS */
1339 gen_helper_tbis(cpu_env, vb);
1340 break;
1342 case 253:
1343 /* WAIT */
1344 tmp = tcg_const_i64(1);
1345 tcg_gen_st32_i64(tmp, cpu_env, -offsetof(AlphaCPU, env) +
1346 offsetof(CPUState, halted));
1347 return gen_excp(ctx, EXCP_HLT, 0);
1349 case 252:
1350 /* HALT */
1351 gen_helper_halt(vb);
1352 return EXIT_PC_STALE;
1354 case 251:
1355 /* ALARM */
1356 gen_helper_set_alarm(cpu_env, vb);
1357 break;
1359 case 7:
1360 /* PALBR */
1361 tcg_gen_st_i64(vb, cpu_env, offsetof(CPUAlphaState, palbr));
1362 /* Changing the PAL base register implies un-chaining all of the TBs
1363 that ended with a CALL_PAL. Since the base register usually only
1364 changes during boot, flushing everything works well. */
1365 gen_helper_tb_flush(cpu_env);
1366 return EXIT_PC_STALE;
1368 case 32 ... 39:
1369 /* Accessing the "non-shadow" general registers. */
1370 regno = regno == 39 ? 25 : regno - 32 + 8;
1371 tcg_gen_mov_i64(cpu_std_ir[regno], vb);
1372 break;
1374 default:
1375 /* The basic registers are data only, and unknown registers
1376 are read-zero, write-ignore. */
1377 data = cpu_pr_data(regno);
1378 if (data != 0) {
1379 if (data & PR_BYTE) {
1380 tcg_gen_st8_i64(vb, cpu_env, data & ~PR_BYTE);
1381 } else if (data & PR_LONG) {
1382 tcg_gen_st32_i64(vb, cpu_env, data & ~PR_LONG);
1383 } else {
1384 tcg_gen_st_i64(vb, cpu_env, data);
1387 break;
1390 return NO_EXIT;
1392 #endif /* !USER_ONLY*/
1394 #define REQUIRE_NO_LIT \
1395 do { \
1396 if (real_islit) { \
1397 goto invalid_opc; \
1399 } while (0)
1401 #define REQUIRE_TB_FLAG(FLAG) \
1402 do { \
1403 if ((ctx->tb->flags & (FLAG)) == 0) { \
1404 goto invalid_opc; \
1406 } while (0)
1408 #define REQUIRE_REG_31(WHICH) \
1409 do { \
1410 if (WHICH != 31) { \
1411 goto invalid_opc; \
1413 } while (0)
1415 static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
1417 int32_t disp21, disp16, disp12 __attribute__((unused));
1418 uint16_t fn11;
1419 uint8_t opc, ra, rb, rc, fpfn, fn7, lit;
1420 bool islit, real_islit;
1421 TCGv va, vb, vc, tmp, tmp2;
1422 TCGv_i32 t32;
1423 ExitStatus ret;
1425 /* Decode all instruction fields */
1426 opc = extract32(insn, 26, 6);
1427 ra = extract32(insn, 21, 5);
1428 rb = extract32(insn, 16, 5);
1429 rc = extract32(insn, 0, 5);
1430 real_islit = islit = extract32(insn, 12, 1);
1431 lit = extract32(insn, 13, 8);
1433 disp21 = sextract32(insn, 0, 21);
1434 disp16 = sextract32(insn, 0, 16);
1435 disp12 = sextract32(insn, 0, 12);
1437 fn11 = extract32(insn, 5, 11);
1438 fpfn = extract32(insn, 5, 6);
1439 fn7 = extract32(insn, 5, 7);
1441 if (rb == 31 && !islit) {
1442 islit = true;
1443 lit = 0;
1446 ret = NO_EXIT;
1447 switch (opc) {
1448 case 0x00:
1449 /* CALL_PAL */
1450 ret = gen_call_pal(ctx, insn & 0x03ffffff);
1451 break;
1452 case 0x01:
1453 /* OPC01 */
1454 goto invalid_opc;
1455 case 0x02:
1456 /* OPC02 */
1457 goto invalid_opc;
1458 case 0x03:
1459 /* OPC03 */
1460 goto invalid_opc;
1461 case 0x04:
1462 /* OPC04 */
1463 goto invalid_opc;
1464 case 0x05:
1465 /* OPC05 */
1466 goto invalid_opc;
1467 case 0x06:
1468 /* OPC06 */
1469 goto invalid_opc;
1470 case 0x07:
1471 /* OPC07 */
1472 goto invalid_opc;
1474 case 0x09:
1475 /* LDAH */
1476 disp16 = (uint32_t)disp16 << 16;
1477 /* fall through */
1478 case 0x08:
1479 /* LDA */
1480 va = dest_gpr(ctx, ra);
1481 /* It's worth special-casing immediate loads. */
1482 if (rb == 31) {
1483 tcg_gen_movi_i64(va, disp16);
1484 } else {
1485 tcg_gen_addi_i64(va, load_gpr(ctx, rb), disp16);
1487 break;
1489 case 0x0A:
1490 /* LDBU */
1491 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
1492 gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
1493 break;
1494 case 0x0B:
1495 /* LDQ_U */
1496 gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 1);
1497 break;
1498 case 0x0C:
1499 /* LDWU */
1500 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
1501 gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 0);
1502 break;
1503 case 0x0D:
1504 /* STW */
1505 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
1506 gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0);
1507 break;
1508 case 0x0E:
1509 /* STB */
1510 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
1511 gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0);
1512 break;
1513 case 0x0F:
1514 /* STQ_U */
1515 gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1);
1516 break;
1518 case 0x10:
1519 vc = dest_gpr(ctx, rc);
1520 vb = load_gpr_lit(ctx, rb, lit, islit);
1522 if (ra == 31) {
1523 if (fn7 == 0x00) {
1524 /* Special case ADDL as SEXTL. */
1525 tcg_gen_ext32s_i64(vc, vb);
1526 break;
1528 if (fn7 == 0x29) {
1529 /* Special case SUBQ as NEGQ. */
1530 tcg_gen_neg_i64(vc, vb);
1531 break;
1535 va = load_gpr(ctx, ra);
1536 switch (fn7) {
1537 case 0x00:
1538 /* ADDL */
1539 tcg_gen_add_i64(vc, va, vb);
1540 tcg_gen_ext32s_i64(vc, vc);
1541 break;
1542 case 0x02:
1543 /* S4ADDL */
1544 tmp = tcg_temp_new();
1545 tcg_gen_shli_i64(tmp, va, 2);
1546 tcg_gen_add_i64(tmp, tmp, vb);
1547 tcg_gen_ext32s_i64(vc, tmp);
1548 tcg_temp_free(tmp);
1549 break;
1550 case 0x09:
1551 /* SUBL */
1552 tcg_gen_sub_i64(vc, va, vb);
1553 tcg_gen_ext32s_i64(vc, vc);
1554 break;
1555 case 0x0B:
1556 /* S4SUBL */
1557 tmp = tcg_temp_new();
1558 tcg_gen_shli_i64(tmp, va, 2);
1559 tcg_gen_sub_i64(tmp, tmp, vb);
1560 tcg_gen_ext32s_i64(vc, tmp);
1561 tcg_temp_free(tmp);
1562 break;
1563 case 0x0F:
1564 /* CMPBGE */
1565 if (ra == 31) {
1566 /* Special case 0 >= X as X == 0. */
1567 gen_helper_cmpbe0(vc, vb);
1568 } else {
1569 gen_helper_cmpbge(vc, va, vb);
1571 break;
1572 case 0x12:
1573 /* S8ADDL */
1574 tmp = tcg_temp_new();
1575 tcg_gen_shli_i64(tmp, va, 3);
1576 tcg_gen_add_i64(tmp, tmp, vb);
1577 tcg_gen_ext32s_i64(vc, tmp);
1578 tcg_temp_free(tmp);
1579 break;
1580 case 0x1B:
1581 /* S8SUBL */
1582 tmp = tcg_temp_new();
1583 tcg_gen_shli_i64(tmp, va, 3);
1584 tcg_gen_sub_i64(tmp, tmp, vb);
1585 tcg_gen_ext32s_i64(vc, tmp);
1586 tcg_temp_free(tmp);
1587 break;
1588 case 0x1D:
1589 /* CMPULT */
1590 tcg_gen_setcond_i64(TCG_COND_LTU, vc, va, vb);
1591 break;
1592 case 0x20:
1593 /* ADDQ */
1594 tcg_gen_add_i64(vc, va, vb);
1595 break;
1596 case 0x22:
1597 /* S4ADDQ */
1598 tmp = tcg_temp_new();
1599 tcg_gen_shli_i64(tmp, va, 2);
1600 tcg_gen_add_i64(vc, tmp, vb);
1601 tcg_temp_free(tmp);
1602 break;
1603 case 0x29:
1604 /* SUBQ */
1605 tcg_gen_sub_i64(vc, va, vb);
1606 break;
1607 case 0x2B:
1608 /* S4SUBQ */
1609 tmp = tcg_temp_new();
1610 tcg_gen_shli_i64(tmp, va, 2);
1611 tcg_gen_sub_i64(vc, tmp, vb);
1612 tcg_temp_free(tmp);
1613 break;
1614 case 0x2D:
1615 /* CMPEQ */
1616 tcg_gen_setcond_i64(TCG_COND_EQ, vc, va, vb);
1617 break;
1618 case 0x32:
1619 /* S8ADDQ */
1620 tmp = tcg_temp_new();
1621 tcg_gen_shli_i64(tmp, va, 3);
1622 tcg_gen_add_i64(vc, tmp, vb);
1623 tcg_temp_free(tmp);
1624 break;
1625 case 0x3B:
1626 /* S8SUBQ */
1627 tmp = tcg_temp_new();
1628 tcg_gen_shli_i64(tmp, va, 3);
1629 tcg_gen_sub_i64(vc, tmp, vb);
1630 tcg_temp_free(tmp);
1631 break;
1632 case 0x3D:
1633 /* CMPULE */
1634 tcg_gen_setcond_i64(TCG_COND_LEU, vc, va, vb);
1635 break;
1636 case 0x40:
1637 /* ADDL/V */
1638 tmp = tcg_temp_new();
1639 tcg_gen_ext32s_i64(tmp, va);
1640 tcg_gen_ext32s_i64(vc, vb);
1641 tcg_gen_add_i64(tmp, tmp, vc);
1642 tcg_gen_ext32s_i64(vc, tmp);
1643 gen_helper_check_overflow(cpu_env, vc, tmp);
1644 tcg_temp_free(tmp);
1645 break;
1646 case 0x49:
1647 /* SUBL/V */
1648 tmp = tcg_temp_new();
1649 tcg_gen_ext32s_i64(tmp, va);
1650 tcg_gen_ext32s_i64(vc, vb);
1651 tcg_gen_sub_i64(tmp, tmp, vc);
1652 tcg_gen_ext32s_i64(vc, tmp);
1653 gen_helper_check_overflow(cpu_env, vc, tmp);
1654 tcg_temp_free(tmp);
1655 break;
1656 case 0x4D:
1657 /* CMPLT */
1658 tcg_gen_setcond_i64(TCG_COND_LT, vc, va, vb);
1659 break;
1660 case 0x60:
1661 /* ADDQ/V */
1662 tmp = tcg_temp_new();
1663 tmp2 = tcg_temp_new();
1664 tcg_gen_eqv_i64(tmp, va, vb);
1665 tcg_gen_mov_i64(tmp2, va);
1666 tcg_gen_add_i64(vc, va, vb);
1667 tcg_gen_xor_i64(tmp2, tmp2, vc);
1668 tcg_gen_and_i64(tmp, tmp, tmp2);
1669 tcg_gen_shri_i64(tmp, tmp, 63);
1670 tcg_gen_movi_i64(tmp2, 0);
1671 gen_helper_check_overflow(cpu_env, tmp, tmp2);
1672 tcg_temp_free(tmp);
1673 tcg_temp_free(tmp2);
1674 break;
1675 case 0x69:
1676 /* SUBQ/V */
1677 tmp = tcg_temp_new();
1678 tmp2 = tcg_temp_new();
1679 tcg_gen_xor_i64(tmp, va, vb);
1680 tcg_gen_mov_i64(tmp2, va);
1681 tcg_gen_sub_i64(vc, va, vb);
1682 tcg_gen_xor_i64(tmp2, tmp2, vc);
1683 tcg_gen_and_i64(tmp, tmp, tmp2);
1684 tcg_gen_shri_i64(tmp, tmp, 63);
1685 tcg_gen_movi_i64(tmp2, 0);
1686 gen_helper_check_overflow(cpu_env, tmp, tmp2);
1687 tcg_temp_free(tmp);
1688 tcg_temp_free(tmp2);
1689 break;
1690 case 0x6D:
1691 /* CMPLE */
1692 tcg_gen_setcond_i64(TCG_COND_LE, vc, va, vb);
1693 break;
1694 default:
1695 goto invalid_opc;
1697 break;
1699 case 0x11:
1700 if (fn7 == 0x20) {
1701 if (rc == 31) {
1702 /* Special case BIS as NOP. */
1703 break;
1705 if (ra == 31) {
1706 /* Special case BIS as MOV. */
1707 vc = dest_gpr(ctx, rc);
1708 if (islit) {
1709 tcg_gen_movi_i64(vc, lit);
1710 } else {
1711 tcg_gen_mov_i64(vc, load_gpr(ctx, rb));
1713 break;
1717 vc = dest_gpr(ctx, rc);
1718 vb = load_gpr_lit(ctx, rb, lit, islit);
1720 if (fn7 == 0x28 && ra == 31) {
1721 /* Special case ORNOT as NOT. */
1722 tcg_gen_not_i64(vc, vb);
1723 break;
1726 va = load_gpr(ctx, ra);
1727 switch (fn7) {
1728 case 0x00:
1729 /* AND */
1730 tcg_gen_and_i64(vc, va, vb);
1731 break;
1732 case 0x08:
1733 /* BIC */
1734 tcg_gen_andc_i64(vc, va, vb);
1735 break;
1736 case 0x14:
1737 /* CMOVLBS */
1738 tmp = tcg_temp_new();
1739 tcg_gen_andi_i64(tmp, va, 1);
1740 tcg_gen_movcond_i64(TCG_COND_NE, vc, tmp, load_zero(ctx),
1741 vb, load_gpr(ctx, rc));
1742 tcg_temp_free(tmp);
1743 break;
1744 case 0x16:
1745 /* CMOVLBC */
1746 tmp = tcg_temp_new();
1747 tcg_gen_andi_i64(tmp, va, 1);
1748 tcg_gen_movcond_i64(TCG_COND_EQ, vc, tmp, load_zero(ctx),
1749 vb, load_gpr(ctx, rc));
1750 tcg_temp_free(tmp);
1751 break;
1752 case 0x20:
1753 /* BIS */
1754 tcg_gen_or_i64(vc, va, vb);
1755 break;
1756 case 0x24:
1757 /* CMOVEQ */
1758 tcg_gen_movcond_i64(TCG_COND_EQ, vc, va, load_zero(ctx),
1759 vb, load_gpr(ctx, rc));
1760 break;
1761 case 0x26:
1762 /* CMOVNE */
1763 tcg_gen_movcond_i64(TCG_COND_NE, vc, va, load_zero(ctx),
1764 vb, load_gpr(ctx, rc));
1765 break;
1766 case 0x28:
1767 /* ORNOT */
1768 tcg_gen_orc_i64(vc, va, vb);
1769 break;
1770 case 0x40:
1771 /* XOR */
1772 tcg_gen_xor_i64(vc, va, vb);
1773 break;
1774 case 0x44:
1775 /* CMOVLT */
1776 tcg_gen_movcond_i64(TCG_COND_LT, vc, va, load_zero(ctx),
1777 vb, load_gpr(ctx, rc));
1778 break;
1779 case 0x46:
1780 /* CMOVGE */
1781 tcg_gen_movcond_i64(TCG_COND_GE, vc, va, load_zero(ctx),
1782 vb, load_gpr(ctx, rc));
1783 break;
1784 case 0x48:
1785 /* EQV */
1786 tcg_gen_eqv_i64(vc, va, vb);
1787 break;
1788 case 0x61:
1789 /* AMASK */
1790 REQUIRE_REG_31(ra);
1792 uint64_t amask = ctx->tb->flags >> TB_FLAGS_AMASK_SHIFT;
1793 tcg_gen_andi_i64(vc, vb, ~amask);
1795 break;
1796 case 0x64:
1797 /* CMOVLE */
1798 tcg_gen_movcond_i64(TCG_COND_LE, vc, va, load_zero(ctx),
1799 vb, load_gpr(ctx, rc));
1800 break;
1801 case 0x66:
1802 /* CMOVGT */
1803 tcg_gen_movcond_i64(TCG_COND_GT, vc, va, load_zero(ctx),
1804 vb, load_gpr(ctx, rc));
1805 break;
1806 case 0x6C:
1807 /* IMPLVER */
1808 REQUIRE_REG_31(ra);
1809 tcg_gen_movi_i64(vc, ctx->implver);
1810 break;
1811 default:
1812 goto invalid_opc;
1814 break;
1816 case 0x12:
1817 vc = dest_gpr(ctx, rc);
1818 va = load_gpr(ctx, ra);
1819 switch (fn7) {
1820 case 0x02:
1821 /* MSKBL */
1822 gen_msk_l(ctx, vc, va, rb, islit, lit, 0x01);
1823 break;
1824 case 0x06:
1825 /* EXTBL */
1826 gen_ext_l(ctx, vc, va, rb, islit, lit, 0x01);
1827 break;
1828 case 0x0B:
1829 /* INSBL */
1830 gen_ins_l(ctx, vc, va, rb, islit, lit, 0x01);
1831 break;
1832 case 0x12:
1833 /* MSKWL */
1834 gen_msk_l(ctx, vc, va, rb, islit, lit, 0x03);
1835 break;
1836 case 0x16:
1837 /* EXTWL */
1838 gen_ext_l(ctx, vc, va, rb, islit, lit, 0x03);
1839 break;
1840 case 0x1B:
1841 /* INSWL */
1842 gen_ins_l(ctx, vc, va, rb, islit, lit, 0x03);
1843 break;
1844 case 0x22:
1845 /* MSKLL */
1846 gen_msk_l(ctx, vc, va, rb, islit, lit, 0x0f);
1847 break;
1848 case 0x26:
1849 /* EXTLL */
1850 gen_ext_l(ctx, vc, va, rb, islit, lit, 0x0f);
1851 break;
1852 case 0x2B:
1853 /* INSLL */
1854 gen_ins_l(ctx, vc, va, rb, islit, lit, 0x0f);
1855 break;
1856 case 0x30:
1857 /* ZAP */
1858 if (islit) {
1859 gen_zapnoti(vc, va, ~lit);
1860 } else {
1861 gen_helper_zap(vc, va, load_gpr(ctx, rb));
1863 break;
1864 case 0x31:
1865 /* ZAPNOT */
1866 if (islit) {
1867 gen_zapnoti(vc, va, lit);
1868 } else {
1869 gen_helper_zapnot(vc, va, load_gpr(ctx, rb));
1871 break;
1872 case 0x32:
1873 /* MSKQL */
1874 gen_msk_l(ctx, vc, va, rb, islit, lit, 0xff);
1875 break;
1876 case 0x34:
1877 /* SRL */
1878 if (islit) {
1879 tcg_gen_shri_i64(vc, va, lit & 0x3f);
1880 } else {
1881 tmp = tcg_temp_new();
1882 vb = load_gpr(ctx, rb);
1883 tcg_gen_andi_i64(tmp, vb, 0x3f);
1884 tcg_gen_shr_i64(vc, va, tmp);
1885 tcg_temp_free(tmp);
1887 break;
1888 case 0x36:
1889 /* EXTQL */
1890 gen_ext_l(ctx, vc, va, rb, islit, lit, 0xff);
1891 break;
1892 case 0x39:
1893 /* SLL */
1894 if (islit) {
1895 tcg_gen_shli_i64(vc, va, lit & 0x3f);
1896 } else {
1897 tmp = tcg_temp_new();
1898 vb = load_gpr(ctx, rb);
1899 tcg_gen_andi_i64(tmp, vb, 0x3f);
1900 tcg_gen_shl_i64(vc, va, tmp);
1901 tcg_temp_free(tmp);
1903 break;
1904 case 0x3B:
1905 /* INSQL */
1906 gen_ins_l(ctx, vc, va, rb, islit, lit, 0xff);
1907 break;
1908 case 0x3C:
1909 /* SRA */
1910 if (islit) {
1911 tcg_gen_sari_i64(vc, va, lit & 0x3f);
1912 } else {
1913 tmp = tcg_temp_new();
1914 vb = load_gpr(ctx, rb);
1915 tcg_gen_andi_i64(tmp, vb, 0x3f);
1916 tcg_gen_sar_i64(vc, va, tmp);
1917 tcg_temp_free(tmp);
1919 break;
1920 case 0x52:
1921 /* MSKWH */
1922 gen_msk_h(ctx, vc, va, rb, islit, lit, 0x03);
1923 break;
1924 case 0x57:
1925 /* INSWH */
1926 gen_ins_h(ctx, vc, va, rb, islit, lit, 0x03);
1927 break;
1928 case 0x5A:
1929 /* EXTWH */
1930 gen_ext_h(ctx, vc, va, rb, islit, lit, 0x03);
1931 break;
1932 case 0x62:
1933 /* MSKLH */
1934 gen_msk_h(ctx, vc, va, rb, islit, lit, 0x0f);
1935 break;
1936 case 0x67:
1937 /* INSLH */
1938 gen_ins_h(ctx, vc, va, rb, islit, lit, 0x0f);
1939 break;
1940 case 0x6A:
1941 /* EXTLH */
1942 gen_ext_h(ctx, vc, va, rb, islit, lit, 0x0f);
1943 break;
1944 case 0x72:
1945 /* MSKQH */
1946 gen_msk_h(ctx, vc, va, rb, islit, lit, 0xff);
1947 break;
1948 case 0x77:
1949 /* INSQH */
1950 gen_ins_h(ctx, vc, va, rb, islit, lit, 0xff);
1951 break;
1952 case 0x7A:
1953 /* EXTQH */
1954 gen_ext_h(ctx, vc, va, rb, islit, lit, 0xff);
1955 break;
1956 default:
1957 goto invalid_opc;
1959 break;
1961 case 0x13:
1962 vc = dest_gpr(ctx, rc);
1963 vb = load_gpr_lit(ctx, rb, lit, islit);
1964 va = load_gpr(ctx, ra);
1965 switch (fn7) {
1966 case 0x00:
1967 /* MULL */
1968 tcg_gen_mul_i64(vc, va, vb);
1969 tcg_gen_ext32s_i64(vc, vc);
1970 break;
1971 case 0x20:
1972 /* MULQ */
1973 tcg_gen_mul_i64(vc, va, vb);
1974 break;
1975 case 0x30:
1976 /* UMULH */
1977 tmp = tcg_temp_new();
1978 tcg_gen_mulu2_i64(tmp, vc, va, vb);
1979 tcg_temp_free(tmp);
1980 break;
1981 case 0x40:
1982 /* MULL/V */
1983 tmp = tcg_temp_new();
1984 tcg_gen_ext32s_i64(tmp, va);
1985 tcg_gen_ext32s_i64(vc, vb);
1986 tcg_gen_mul_i64(tmp, tmp, vc);
1987 tcg_gen_ext32s_i64(vc, tmp);
1988 gen_helper_check_overflow(cpu_env, vc, tmp);
1989 tcg_temp_free(tmp);
1990 break;
1991 case 0x60:
1992 /* MULQ/V */
1993 tmp = tcg_temp_new();
1994 tmp2 = tcg_temp_new();
1995 tcg_gen_muls2_i64(vc, tmp, va, vb);
1996 tcg_gen_sari_i64(tmp2, vc, 63);
1997 gen_helper_check_overflow(cpu_env, tmp, tmp2);
1998 tcg_temp_free(tmp);
1999 tcg_temp_free(tmp2);
2000 break;
2001 default:
2002 goto invalid_opc;
2004 break;
2006 case 0x14:
2007 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX);
2008 vc = dest_fpr(ctx, rc);
2009 switch (fpfn) { /* fn11 & 0x3F */
2010 case 0x04:
2011 /* ITOFS */
2012 REQUIRE_REG_31(rb);
2013 t32 = tcg_temp_new_i32();
2014 va = load_gpr(ctx, ra);
2015 tcg_gen_extrl_i64_i32(t32, va);
2016 gen_helper_memory_to_s(vc, t32);
2017 tcg_temp_free_i32(t32);
2018 break;
2019 case 0x0A:
2020 /* SQRTF */
2021 REQUIRE_REG_31(ra);
2022 vb = load_fpr(ctx, rb);
2023 gen_helper_sqrtf(vc, cpu_env, vb);
2024 break;
2025 case 0x0B:
2026 /* SQRTS */
2027 REQUIRE_REG_31(ra);
2028 gen_sqrts(ctx, rb, rc, fn11);
2029 break;
2030 case 0x14:
2031 /* ITOFF */
2032 REQUIRE_REG_31(rb);
2033 t32 = tcg_temp_new_i32();
2034 va = load_gpr(ctx, ra);
2035 tcg_gen_extrl_i64_i32(t32, va);
2036 gen_helper_memory_to_f(vc, t32);
2037 tcg_temp_free_i32(t32);
2038 break;
2039 case 0x24:
2040 /* ITOFT */
2041 REQUIRE_REG_31(rb);
2042 va = load_gpr(ctx, ra);
2043 tcg_gen_mov_i64(vc, va);
2044 break;
2045 case 0x2A:
2046 /* SQRTG */
2047 REQUIRE_REG_31(ra);
2048 vb = load_fpr(ctx, rb);
2049 gen_helper_sqrtg(vc, cpu_env, vb);
2050 break;
2051 case 0x02B:
2052 /* SQRTT */
2053 REQUIRE_REG_31(ra);
2054 gen_sqrtt(ctx, rb, rc, fn11);
2055 break;
2056 default:
2057 goto invalid_opc;
2059 break;
2061 case 0x15:
2062 /* VAX floating point */
2063 /* XXX: rounding mode and trap are ignored (!) */
2064 vc = dest_fpr(ctx, rc);
2065 vb = load_fpr(ctx, rb);
2066 va = load_fpr(ctx, ra);
2067 switch (fpfn) { /* fn11 & 0x3F */
2068 case 0x00:
2069 /* ADDF */
2070 gen_helper_addf(vc, cpu_env, va, vb);
2071 break;
2072 case 0x01:
2073 /* SUBF */
2074 gen_helper_subf(vc, cpu_env, va, vb);
2075 break;
2076 case 0x02:
2077 /* MULF */
2078 gen_helper_mulf(vc, cpu_env, va, vb);
2079 break;
2080 case 0x03:
2081 /* DIVF */
2082 gen_helper_divf(vc, cpu_env, va, vb);
2083 break;
2084 case 0x1E:
2085 /* CVTDG -- TODO */
2086 REQUIRE_REG_31(ra);
2087 goto invalid_opc;
2088 case 0x20:
2089 /* ADDG */
2090 gen_helper_addg(vc, cpu_env, va, vb);
2091 break;
2092 case 0x21:
2093 /* SUBG */
2094 gen_helper_subg(vc, cpu_env, va, vb);
2095 break;
2096 case 0x22:
2097 /* MULG */
2098 gen_helper_mulg(vc, cpu_env, va, vb);
2099 break;
2100 case 0x23:
2101 /* DIVG */
2102 gen_helper_divg(vc, cpu_env, va, vb);
2103 break;
2104 case 0x25:
2105 /* CMPGEQ */
2106 gen_helper_cmpgeq(vc, cpu_env, va, vb);
2107 break;
2108 case 0x26:
2109 /* CMPGLT */
2110 gen_helper_cmpglt(vc, cpu_env, va, vb);
2111 break;
2112 case 0x27:
2113 /* CMPGLE */
2114 gen_helper_cmpgle(vc, cpu_env, va, vb);
2115 break;
2116 case 0x2C:
2117 /* CVTGF */
2118 REQUIRE_REG_31(ra);
2119 gen_helper_cvtgf(vc, cpu_env, vb);
2120 break;
2121 case 0x2D:
2122 /* CVTGD -- TODO */
2123 REQUIRE_REG_31(ra);
2124 goto invalid_opc;
2125 case 0x2F:
2126 /* CVTGQ */
2127 REQUIRE_REG_31(ra);
2128 gen_helper_cvtgq(vc, cpu_env, vb);
2129 break;
2130 case 0x3C:
2131 /* CVTQF */
2132 REQUIRE_REG_31(ra);
2133 gen_helper_cvtqf(vc, cpu_env, vb);
2134 break;
2135 case 0x3E:
2136 /* CVTQG */
2137 REQUIRE_REG_31(ra);
2138 gen_helper_cvtqg(vc, cpu_env, vb);
2139 break;
2140 default:
2141 goto invalid_opc;
2143 break;
2145 case 0x16:
2146 /* IEEE floating-point */
2147 switch (fpfn) { /* fn11 & 0x3F */
2148 case 0x00:
2149 /* ADDS */
2150 gen_adds(ctx, ra, rb, rc, fn11);
2151 break;
2152 case 0x01:
2153 /* SUBS */
2154 gen_subs(ctx, ra, rb, rc, fn11);
2155 break;
2156 case 0x02:
2157 /* MULS */
2158 gen_muls(ctx, ra, rb, rc, fn11);
2159 break;
2160 case 0x03:
2161 /* DIVS */
2162 gen_divs(ctx, ra, rb, rc, fn11);
2163 break;
2164 case 0x20:
2165 /* ADDT */
2166 gen_addt(ctx, ra, rb, rc, fn11);
2167 break;
2168 case 0x21:
2169 /* SUBT */
2170 gen_subt(ctx, ra, rb, rc, fn11);
2171 break;
2172 case 0x22:
2173 /* MULT */
2174 gen_mult(ctx, ra, rb, rc, fn11);
2175 break;
2176 case 0x23:
2177 /* DIVT */
2178 gen_divt(ctx, ra, rb, rc, fn11);
2179 break;
2180 case 0x24:
2181 /* CMPTUN */
2182 gen_cmptun(ctx, ra, rb, rc, fn11);
2183 break;
2184 case 0x25:
2185 /* CMPTEQ */
2186 gen_cmpteq(ctx, ra, rb, rc, fn11);
2187 break;
2188 case 0x26:
2189 /* CMPTLT */
2190 gen_cmptlt(ctx, ra, rb, rc, fn11);
2191 break;
2192 case 0x27:
2193 /* CMPTLE */
2194 gen_cmptle(ctx, ra, rb, rc, fn11);
2195 break;
2196 case 0x2C:
2197 REQUIRE_REG_31(ra);
2198 if (fn11 == 0x2AC || fn11 == 0x6AC) {
2199 /* CVTST */
2200 gen_cvtst(ctx, rb, rc, fn11);
2201 } else {
2202 /* CVTTS */
2203 gen_cvtts(ctx, rb, rc, fn11);
2205 break;
2206 case 0x2F:
2207 /* CVTTQ */
2208 REQUIRE_REG_31(ra);
2209 gen_cvttq(ctx, rb, rc, fn11);
2210 break;
2211 case 0x3C:
2212 /* CVTQS */
2213 REQUIRE_REG_31(ra);
2214 gen_cvtqs(ctx, rb, rc, fn11);
2215 break;
2216 case 0x3E:
2217 /* CVTQT */
2218 REQUIRE_REG_31(ra);
2219 gen_cvtqt(ctx, rb, rc, fn11);
2220 break;
2221 default:
2222 goto invalid_opc;
2224 break;
2226 case 0x17:
2227 switch (fn11) {
2228 case 0x010:
2229 /* CVTLQ */
2230 REQUIRE_REG_31(ra);
2231 vc = dest_fpr(ctx, rc);
2232 vb = load_fpr(ctx, rb);
2233 gen_cvtlq(vc, vb);
2234 break;
2235 case 0x020:
2236 /* CPYS */
2237 if (rc == 31) {
2238 /* Special case CPYS as FNOP. */
2239 } else {
2240 vc = dest_fpr(ctx, rc);
2241 va = load_fpr(ctx, ra);
2242 if (ra == rb) {
2243 /* Special case CPYS as FMOV. */
2244 tcg_gen_mov_i64(vc, va);
2245 } else {
2246 vb = load_fpr(ctx, rb);
2247 gen_cpy_mask(vc, va, vb, 0, 0x8000000000000000ULL);
2250 break;
2251 case 0x021:
2252 /* CPYSN */
2253 vc = dest_fpr(ctx, rc);
2254 vb = load_fpr(ctx, rb);
2255 va = load_fpr(ctx, ra);
2256 gen_cpy_mask(vc, va, vb, 1, 0x8000000000000000ULL);
2257 break;
2258 case 0x022:
2259 /* CPYSE */
2260 vc = dest_fpr(ctx, rc);
2261 vb = load_fpr(ctx, rb);
2262 va = load_fpr(ctx, ra);
2263 gen_cpy_mask(vc, va, vb, 0, 0xFFF0000000000000ULL);
2264 break;
2265 case 0x024:
2266 /* MT_FPCR */
2267 va = load_fpr(ctx, ra);
2268 gen_helper_store_fpcr(cpu_env, va);
2269 if (ctx->tb_rm == QUAL_RM_D) {
2270 /* Re-do the copy of the rounding mode to fp_status
2271 the next time we use dynamic rounding. */
2272 ctx->tb_rm = -1;
2274 break;
2275 case 0x025:
2276 /* MF_FPCR */
2277 va = dest_fpr(ctx, ra);
2278 gen_helper_load_fpcr(va, cpu_env);
2279 break;
2280 case 0x02A:
2281 /* FCMOVEQ */
2282 gen_fcmov(ctx, TCG_COND_EQ, ra, rb, rc);
2283 break;
2284 case 0x02B:
2285 /* FCMOVNE */
2286 gen_fcmov(ctx, TCG_COND_NE, ra, rb, rc);
2287 break;
2288 case 0x02C:
2289 /* FCMOVLT */
2290 gen_fcmov(ctx, TCG_COND_LT, ra, rb, rc);
2291 break;
2292 case 0x02D:
2293 /* FCMOVGE */
2294 gen_fcmov(ctx, TCG_COND_GE, ra, rb, rc);
2295 break;
2296 case 0x02E:
2297 /* FCMOVLE */
2298 gen_fcmov(ctx, TCG_COND_LE, ra, rb, rc);
2299 break;
2300 case 0x02F:
2301 /* FCMOVGT */
2302 gen_fcmov(ctx, TCG_COND_GT, ra, rb, rc);
2303 break;
2304 case 0x030: /* CVTQL */
2305 case 0x130: /* CVTQL/V */
2306 case 0x530: /* CVTQL/SV */
2307 REQUIRE_REG_31(ra);
2308 vc = dest_fpr(ctx, rc);
2309 vb = load_fpr(ctx, rb);
2310 gen_helper_cvtql(vc, cpu_env, vb);
2311 gen_fp_exc_raise(rc, fn11);
2312 break;
2313 default:
2314 goto invalid_opc;
2316 break;
2318 case 0x18:
2319 switch ((uint16_t)disp16) {
2320 case 0x0000:
2321 /* TRAPB */
2322 /* No-op. */
2323 break;
2324 case 0x0400:
2325 /* EXCB */
2326 /* No-op. */
2327 break;
2328 case 0x4000:
2329 /* MB */
2330 /* No-op */
2331 break;
2332 case 0x4400:
2333 /* WMB */
2334 /* No-op */
2335 break;
2336 case 0x8000:
2337 /* FETCH */
2338 /* No-op */
2339 break;
2340 case 0xA000:
2341 /* FETCH_M */
2342 /* No-op */
2343 break;
2344 case 0xC000:
2345 /* RPCC */
2346 va = dest_gpr(ctx, ra);
2347 if (ctx->tb->cflags & CF_USE_ICOUNT) {
2348 gen_io_start();
2349 gen_helper_load_pcc(va, cpu_env);
2350 gen_io_end();
2351 ret = EXIT_PC_STALE;
2352 } else {
2353 gen_helper_load_pcc(va, cpu_env);
2355 break;
2356 case 0xE000:
2357 /* RC */
2358 gen_rx(ctx, ra, 0);
2359 break;
2360 case 0xE800:
2361 /* ECB */
2362 break;
2363 case 0xF000:
2364 /* RS */
2365 gen_rx(ctx, ra, 1);
2366 break;
2367 case 0xF800:
2368 /* WH64 */
2369 /* No-op */
2370 break;
2371 case 0xFC00:
2372 /* WH64EN */
2373 /* No-op */
2374 break;
2375 default:
2376 goto invalid_opc;
2378 break;
2380 case 0x19:
2381 /* HW_MFPR (PALcode) */
2382 #ifndef CONFIG_USER_ONLY
2383 REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
2384 va = dest_gpr(ctx, ra);
2385 ret = gen_mfpr(ctx, va, insn & 0xffff);
2386 break;
2387 #else
2388 goto invalid_opc;
2389 #endif
2391 case 0x1A:
2392 /* JMP, JSR, RET, JSR_COROUTINE. These only differ by the branch
2393 prediction stack action, which of course we don't implement. */
2394 vb = load_gpr(ctx, rb);
2395 tcg_gen_andi_i64(cpu_pc, vb, ~3);
2396 if (ra != 31) {
2397 tcg_gen_movi_i64(ctx->ir[ra], ctx->pc);
2399 ret = EXIT_PC_UPDATED;
2400 break;
2402 case 0x1B:
2403 /* HW_LD (PALcode) */
2404 #ifndef CONFIG_USER_ONLY
2405 REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
2407 TCGv addr = tcg_temp_new();
2408 vb = load_gpr(ctx, rb);
2409 va = dest_gpr(ctx, ra);
2411 tcg_gen_addi_i64(addr, vb, disp12);
2412 switch ((insn >> 12) & 0xF) {
2413 case 0x0:
2414 /* Longword physical access (hw_ldl/p) */
2415 gen_helper_ldl_phys(va, cpu_env, addr);
2416 break;
2417 case 0x1:
2418 /* Quadword physical access (hw_ldq/p) */
2419 gen_helper_ldq_phys(va, cpu_env, addr);
2420 break;
2421 case 0x2:
2422 /* Longword physical access with lock (hw_ldl_l/p) */
2423 gen_helper_ldl_l_phys(va, cpu_env, addr);
2424 break;
2425 case 0x3:
2426 /* Quadword physical access with lock (hw_ldq_l/p) */
2427 gen_helper_ldq_l_phys(va, cpu_env, addr);
2428 break;
2429 case 0x4:
2430 /* Longword virtual PTE fetch (hw_ldl/v) */
2431 goto invalid_opc;
2432 case 0x5:
2433 /* Quadword virtual PTE fetch (hw_ldq/v) */
2434 goto invalid_opc;
2435 break;
2436 case 0x6:
2437 /* Invalid */
2438 goto invalid_opc;
2439 case 0x7:
2440 /* Invaliid */
2441 goto invalid_opc;
2442 case 0x8:
2443 /* Longword virtual access (hw_ldl) */
2444 goto invalid_opc;
2445 case 0x9:
2446 /* Quadword virtual access (hw_ldq) */
2447 goto invalid_opc;
2448 case 0xA:
2449 /* Longword virtual access with protection check (hw_ldl/w) */
2450 tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LESL);
2451 break;
2452 case 0xB:
2453 /* Quadword virtual access with protection check (hw_ldq/w) */
2454 tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LEQ);
2455 break;
2456 case 0xC:
2457 /* Longword virtual access with alt access mode (hw_ldl/a)*/
2458 goto invalid_opc;
2459 case 0xD:
2460 /* Quadword virtual access with alt access mode (hw_ldq/a) */
2461 goto invalid_opc;
2462 case 0xE:
2463 /* Longword virtual access with alternate access mode and
2464 protection checks (hw_ldl/wa) */
2465 tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LESL);
2466 break;
2467 case 0xF:
2468 /* Quadword virtual access with alternate access mode and
2469 protection checks (hw_ldq/wa) */
2470 tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LEQ);
2471 break;
2473 tcg_temp_free(addr);
2474 break;
2476 #else
2477 goto invalid_opc;
2478 #endif
2480 case 0x1C:
2481 vc = dest_gpr(ctx, rc);
2482 if (fn7 == 0x70) {
2483 /* FTOIT */
2484 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX);
2485 REQUIRE_REG_31(rb);
2486 va = load_fpr(ctx, ra);
2487 tcg_gen_mov_i64(vc, va);
2488 break;
2489 } else if (fn7 == 0x78) {
2490 /* FTOIS */
2491 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX);
2492 REQUIRE_REG_31(rb);
2493 t32 = tcg_temp_new_i32();
2494 va = load_fpr(ctx, ra);
2495 gen_helper_s_to_memory(t32, va);
2496 tcg_gen_ext_i32_i64(vc, t32);
2497 tcg_temp_free_i32(t32);
2498 break;
2501 vb = load_gpr_lit(ctx, rb, lit, islit);
2502 switch (fn7) {
2503 case 0x00:
2504 /* SEXTB */
2505 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
2506 REQUIRE_REG_31(ra);
2507 tcg_gen_ext8s_i64(vc, vb);
2508 break;
2509 case 0x01:
2510 /* SEXTW */
2511 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
2512 REQUIRE_REG_31(ra);
2513 tcg_gen_ext16s_i64(vc, vb);
2514 break;
2515 case 0x30:
2516 /* CTPOP */
2517 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
2518 REQUIRE_REG_31(ra);
2519 REQUIRE_NO_LIT;
2520 gen_helper_ctpop(vc, vb);
2521 break;
2522 case 0x31:
2523 /* PERR */
2524 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2525 REQUIRE_NO_LIT;
2526 va = load_gpr(ctx, ra);
2527 gen_helper_perr(vc, va, vb);
2528 break;
2529 case 0x32:
2530 /* CTLZ */
2531 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
2532 REQUIRE_REG_31(ra);
2533 REQUIRE_NO_LIT;
2534 gen_helper_ctlz(vc, vb);
2535 break;
2536 case 0x33:
2537 /* CTTZ */
2538 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
2539 REQUIRE_REG_31(ra);
2540 REQUIRE_NO_LIT;
2541 gen_helper_cttz(vc, vb);
2542 break;
2543 case 0x34:
2544 /* UNPKBW */
2545 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2546 REQUIRE_REG_31(ra);
2547 REQUIRE_NO_LIT;
2548 gen_helper_unpkbw(vc, vb);
2549 break;
2550 case 0x35:
2551 /* UNPKBL */
2552 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2553 REQUIRE_REG_31(ra);
2554 REQUIRE_NO_LIT;
2555 gen_helper_unpkbl(vc, vb);
2556 break;
2557 case 0x36:
2558 /* PKWB */
2559 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2560 REQUIRE_REG_31(ra);
2561 REQUIRE_NO_LIT;
2562 gen_helper_pkwb(vc, vb);
2563 break;
2564 case 0x37:
2565 /* PKLB */
2566 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2567 REQUIRE_REG_31(ra);
2568 REQUIRE_NO_LIT;
2569 gen_helper_pklb(vc, vb);
2570 break;
2571 case 0x38:
2572 /* MINSB8 */
2573 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2574 va = load_gpr(ctx, ra);
2575 gen_helper_minsb8(vc, va, vb);
2576 break;
2577 case 0x39:
2578 /* MINSW4 */
2579 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2580 va = load_gpr(ctx, ra);
2581 gen_helper_minsw4(vc, va, vb);
2582 break;
2583 case 0x3A:
2584 /* MINUB8 */
2585 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2586 va = load_gpr(ctx, ra);
2587 gen_helper_minub8(vc, va, vb);
2588 break;
2589 case 0x3B:
2590 /* MINUW4 */
2591 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2592 va = load_gpr(ctx, ra);
2593 gen_helper_minuw4(vc, va, vb);
2594 break;
2595 case 0x3C:
2596 /* MAXUB8 */
2597 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2598 va = load_gpr(ctx, ra);
2599 gen_helper_maxub8(vc, va, vb);
2600 break;
2601 case 0x3D:
2602 /* MAXUW4 */
2603 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2604 va = load_gpr(ctx, ra);
2605 gen_helper_maxuw4(vc, va, vb);
2606 break;
2607 case 0x3E:
2608 /* MAXSB8 */
2609 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2610 va = load_gpr(ctx, ra);
2611 gen_helper_maxsb8(vc, va, vb);
2612 break;
2613 case 0x3F:
2614 /* MAXSW4 */
2615 REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
2616 va = load_gpr(ctx, ra);
2617 gen_helper_maxsw4(vc, va, vb);
2618 break;
2619 default:
2620 goto invalid_opc;
2622 break;
2624 case 0x1D:
2625 /* HW_MTPR (PALcode) */
2626 #ifndef CONFIG_USER_ONLY
2627 REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
2628 vb = load_gpr(ctx, rb);
2629 ret = gen_mtpr(ctx, vb, insn & 0xffff);
2630 break;
2631 #else
2632 goto invalid_opc;
2633 #endif
2635 case 0x1E:
2636 /* HW_RET (PALcode) */
2637 #ifndef CONFIG_USER_ONLY
2638 REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
2639 if (rb == 31) {
2640 /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
2641 address from EXC_ADDR. This turns out to be useful for our
2642 emulation PALcode, so continue to accept it. */
2643 ctx->lit = vb = tcg_temp_new();
2644 tcg_gen_ld_i64(vb, cpu_env, offsetof(CPUAlphaState, exc_addr));
2645 } else {
2646 vb = load_gpr(ctx, rb);
2648 tmp = tcg_temp_new();
2649 tcg_gen_movi_i64(tmp, 0);
2650 tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, intr_flag));
2651 tcg_gen_movi_i64(cpu_lock_addr, -1);
2652 tcg_gen_andi_i64(tmp, vb, 1);
2653 tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, pal_mode));
2654 tcg_gen_andi_i64(cpu_pc, vb, ~3);
2655 ret = EXIT_PC_UPDATED;
2656 break;
2657 #else
2658 goto invalid_opc;
2659 #endif
2661 case 0x1F:
2662 /* HW_ST (PALcode) */
2663 #ifndef CONFIG_USER_ONLY
2664 REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
2666 TCGv addr = tcg_temp_new();
2667 va = load_gpr(ctx, ra);
2668 vb = load_gpr(ctx, rb);
2670 tcg_gen_addi_i64(addr, vb, disp12);
2671 switch ((insn >> 12) & 0xF) {
2672 case 0x0:
2673 /* Longword physical access */
2674 gen_helper_stl_phys(cpu_env, addr, va);
2675 break;
2676 case 0x1:
2677 /* Quadword physical access */
2678 gen_helper_stq_phys(cpu_env, addr, va);
2679 break;
2680 case 0x2:
2681 /* Longword physical access with lock */
2682 gen_helper_stl_c_phys(dest_gpr(ctx, ra), cpu_env, addr, va);
2683 break;
2684 case 0x3:
2685 /* Quadword physical access with lock */
2686 gen_helper_stq_c_phys(dest_gpr(ctx, ra), cpu_env, addr, va);
2687 break;
2688 case 0x4:
2689 /* Longword virtual access */
2690 goto invalid_opc;
2691 case 0x5:
2692 /* Quadword virtual access */
2693 goto invalid_opc;
2694 case 0x6:
2695 /* Invalid */
2696 goto invalid_opc;
2697 case 0x7:
2698 /* Invalid */
2699 goto invalid_opc;
2700 case 0x8:
2701 /* Invalid */
2702 goto invalid_opc;
2703 case 0x9:
2704 /* Invalid */
2705 goto invalid_opc;
2706 case 0xA:
2707 /* Invalid */
2708 goto invalid_opc;
2709 case 0xB:
2710 /* Invalid */
2711 goto invalid_opc;
2712 case 0xC:
2713 /* Longword virtual access with alternate access mode */
2714 goto invalid_opc;
2715 case 0xD:
2716 /* Quadword virtual access with alternate access mode */
2717 goto invalid_opc;
2718 case 0xE:
2719 /* Invalid */
2720 goto invalid_opc;
2721 case 0xF:
2722 /* Invalid */
2723 goto invalid_opc;
2725 tcg_temp_free(addr);
2726 break;
2728 #else
2729 goto invalid_opc;
2730 #endif
2731 case 0x20:
2732 /* LDF */
2733 gen_load_mem(ctx, &gen_qemu_ldf, ra, rb, disp16, 1, 0);
2734 break;
2735 case 0x21:
2736 /* LDG */
2737 gen_load_mem(ctx, &gen_qemu_ldg, ra, rb, disp16, 1, 0);
2738 break;
2739 case 0x22:
2740 /* LDS */
2741 gen_load_mem(ctx, &gen_qemu_lds, ra, rb, disp16, 1, 0);
2742 break;
2743 case 0x23:
2744 /* LDT */
2745 gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 1, 0);
2746 break;
2747 case 0x24:
2748 /* STF */
2749 gen_store_mem(ctx, &gen_qemu_stf, ra, rb, disp16, 1, 0);
2750 break;
2751 case 0x25:
2752 /* STG */
2753 gen_store_mem(ctx, &gen_qemu_stg, ra, rb, disp16, 1, 0);
2754 break;
2755 case 0x26:
2756 /* STS */
2757 gen_store_mem(ctx, &gen_qemu_sts, ra, rb, disp16, 1, 0);
2758 break;
2759 case 0x27:
2760 /* STT */
2761 gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0);
2762 break;
2763 case 0x28:
2764 /* LDL */
2765 gen_load_mem(ctx, &tcg_gen_qemu_ld32s, ra, rb, disp16, 0, 0);
2766 break;
2767 case 0x29:
2768 /* LDQ */
2769 gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 0);
2770 break;
2771 case 0x2A:
2772 /* LDL_L */
2773 gen_load_mem(ctx, &gen_qemu_ldl_l, ra, rb, disp16, 0, 0);
2774 break;
2775 case 0x2B:
2776 /* LDQ_L */
2777 gen_load_mem(ctx, &gen_qemu_ldq_l, ra, rb, disp16, 0, 0);
2778 break;
2779 case 0x2C:
2780 /* STL */
2781 gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp16, 0, 0);
2782 break;
2783 case 0x2D:
2784 /* STQ */
2785 gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 0);
2786 break;
2787 case 0x2E:
2788 /* STL_C */
2789 ret = gen_store_conditional(ctx, ra, rb, disp16, 0);
2790 break;
2791 case 0x2F:
2792 /* STQ_C */
2793 ret = gen_store_conditional(ctx, ra, rb, disp16, 1);
2794 break;
2795 case 0x30:
2796 /* BR */
2797 ret = gen_bdirect(ctx, ra, disp21);
2798 break;
2799 case 0x31: /* FBEQ */
2800 ret = gen_fbcond(ctx, TCG_COND_EQ, ra, disp21);
2801 break;
2802 case 0x32: /* FBLT */
2803 ret = gen_fbcond(ctx, TCG_COND_LT, ra, disp21);
2804 break;
2805 case 0x33: /* FBLE */
2806 ret = gen_fbcond(ctx, TCG_COND_LE, ra, disp21);
2807 break;
2808 case 0x34:
2809 /* BSR */
2810 ret = gen_bdirect(ctx, ra, disp21);
2811 break;
2812 case 0x35: /* FBNE */
2813 ret = gen_fbcond(ctx, TCG_COND_NE, ra, disp21);
2814 break;
2815 case 0x36: /* FBGE */
2816 ret = gen_fbcond(ctx, TCG_COND_GE, ra, disp21);
2817 break;
2818 case 0x37: /* FBGT */
2819 ret = gen_fbcond(ctx, TCG_COND_GT, ra, disp21);
2820 break;
2821 case 0x38:
2822 /* BLBC */
2823 ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1);
2824 break;
2825 case 0x39:
2826 /* BEQ */
2827 ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 0);
2828 break;
2829 case 0x3A:
2830 /* BLT */
2831 ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21, 0);
2832 break;
2833 case 0x3B:
2834 /* BLE */
2835 ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21, 0);
2836 break;
2837 case 0x3C:
2838 /* BLBS */
2839 ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1);
2840 break;
2841 case 0x3D:
2842 /* BNE */
2843 ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 0);
2844 break;
2845 case 0x3E:
2846 /* BGE */
2847 ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21, 0);
2848 break;
2849 case 0x3F:
2850 /* BGT */
2851 ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
2852 break;
2853 invalid_opc:
2854 ret = gen_invalid(ctx);
2855 break;
2858 return ret;
2861 static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
2862 TranslationBlock *tb,
2863 bool search_pc)
2865 CPUState *cs = CPU(cpu);
2866 CPUAlphaState *env = &cpu->env;
2867 DisasContext ctx, *ctxp = &ctx;
2868 target_ulong pc_start;
2869 target_ulong pc_mask;
2870 uint32_t insn;
2871 CPUBreakpoint *bp;
2872 int j, lj = -1;
2873 ExitStatus ret;
2874 int num_insns;
2875 int max_insns;
2877 pc_start = tb->pc;
2879 ctx.tb = tb;
2880 ctx.pc = pc_start;
2881 ctx.mem_idx = cpu_mmu_index(env, false);
2882 ctx.implver = env->implver;
2883 ctx.singlestep_enabled = cs->singlestep_enabled;
2885 #ifdef CONFIG_USER_ONLY
2886 ctx.ir = cpu_std_ir;
2887 #else
2888 ctx.palbr = env->palbr;
2889 ctx.ir = (tb->flags & TB_FLAGS_PAL_MODE ? cpu_pal_ir : cpu_std_ir);
2890 #endif
2892 /* ??? Every TB begins with unset rounding mode, to be initialized on
2893 the first fp insn of the TB. Alternately we could define a proper
2894 default for every TB (e.g. QUAL_RM_N or QUAL_RM_D) and make sure
2895 to reset the FP_STATUS to that default at the end of any TB that
2896 changes the default. We could even (gasp) dynamiclly figure out
2897 what default would be most efficient given the running program. */
2898 ctx.tb_rm = -1;
2899 /* Similarly for flush-to-zero. */
2900 ctx.tb_ftz = -1;
2902 num_insns = 0;
2903 max_insns = tb->cflags & CF_COUNT_MASK;
2904 if (max_insns == 0) {
2905 max_insns = CF_COUNT_MASK;
2908 if (in_superpage(&ctx, pc_start)) {
2909 pc_mask = (1ULL << 41) - 1;
2910 } else {
2911 pc_mask = ~TARGET_PAGE_MASK;
2914 gen_tb_start(tb);
2915 do {
2916 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
2917 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
2918 if (bp->pc == ctx.pc) {
2919 gen_excp(&ctx, EXCP_DEBUG, 0);
2920 break;
2924 if (search_pc) {
2925 j = tcg_op_buf_count();
2926 if (lj < j) {
2927 lj++;
2928 while (lj < j) {
2929 tcg_ctx.gen_opc_instr_start[lj++] = 0;
2932 tcg_ctx.gen_opc_pc[lj] = ctx.pc;
2933 tcg_ctx.gen_opc_instr_start[lj] = 1;
2934 tcg_ctx.gen_opc_icount[lj] = num_insns;
2936 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
2937 gen_io_start();
2939 insn = cpu_ldl_code(env, ctx.pc);
2940 num_insns++;
2942 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
2943 tcg_gen_debug_insn_start(ctx.pc);
2946 TCGV_UNUSED_I64(ctx.zero);
2947 TCGV_UNUSED_I64(ctx.sink);
2948 TCGV_UNUSED_I64(ctx.lit);
2950 ctx.pc += 4;
2951 ret = translate_one(ctxp, insn);
2953 if (!TCGV_IS_UNUSED_I64(ctx.sink)) {
2954 tcg_gen_discard_i64(ctx.sink);
2955 tcg_temp_free(ctx.sink);
2957 if (!TCGV_IS_UNUSED_I64(ctx.zero)) {
2958 tcg_temp_free(ctx.zero);
2960 if (!TCGV_IS_UNUSED_I64(ctx.lit)) {
2961 tcg_temp_free(ctx.lit);
2964 /* If we reach a page boundary, are single stepping,
2965 or exhaust instruction count, stop generation. */
2966 if (ret == NO_EXIT
2967 && ((ctx.pc & pc_mask) == 0
2968 || tcg_op_buf_full()
2969 || num_insns >= max_insns
2970 || singlestep
2971 || ctx.singlestep_enabled)) {
2972 ret = EXIT_PC_STALE;
2974 } while (ret == NO_EXIT);
2976 if (tb->cflags & CF_LAST_IO) {
2977 gen_io_end();
2980 switch (ret) {
2981 case EXIT_GOTO_TB:
2982 case EXIT_NORETURN:
2983 break;
2984 case EXIT_PC_STALE:
2985 tcg_gen_movi_i64(cpu_pc, ctx.pc);
2986 /* FALLTHRU */
2987 case EXIT_PC_UPDATED:
2988 if (ctx.singlestep_enabled) {
2989 gen_excp_1(EXCP_DEBUG, 0);
2990 } else {
2991 tcg_gen_exit_tb(0);
2993 break;
2994 default:
2995 abort();
2998 gen_tb_end(tb, num_insns);
3000 if (search_pc) {
3001 j = tcg_op_buf_count();
3002 lj++;
3003 while (lj <= j) {
3004 tcg_ctx.gen_opc_instr_start[lj++] = 0;
3006 } else {
3007 tb->size = ctx.pc - pc_start;
3008 tb->icount = num_insns;
3011 #ifdef DEBUG_DISAS
3012 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
3013 qemu_log("IN: %s\n", lookup_symbol(pc_start));
3014 log_target_disas(cs, pc_start, ctx.pc - pc_start, 1);
3015 qemu_log("\n");
3017 #endif
3020 void gen_intermediate_code (CPUAlphaState *env, struct TranslationBlock *tb)
3022 gen_intermediate_code_internal(alpha_env_get_cpu(env), tb, false);
3025 void gen_intermediate_code_pc (CPUAlphaState *env, struct TranslationBlock *tb)
3027 gen_intermediate_code_internal(alpha_env_get_cpu(env), tb, true);
3030 void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, int pc_pos)
3032 env->pc = tcg_ctx.gen_opc_pc[pc_pos];