qcow2: Add incompatibility note between backing files and raw external data files
[qemu/ar7.git] / target / alpha / translate.c
blob8870284f5742fd4576e174fad1d5a734b061729e
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 "qemu/osdep.h"
21 #include "cpu.h"
22 #include "sysemu/cpus.h"
23 #include "disas/disas.h"
24 #include "qemu/host-utils.h"
25 #include "exec/exec-all.h"
26 #include "tcg/tcg-op.h"
27 #include "exec/cpu_ldst.h"
28 #include "exec/helper-proto.h"
29 #include "exec/helper-gen.h"
30 #include "trace-tcg.h"
31 #include "exec/translator.h"
32 #include "exec/log.h"
35 #undef ALPHA_DEBUG_DISAS
36 #define CONFIG_SOFTFLOAT_INLINE
38 #ifdef ALPHA_DEBUG_DISAS
39 # define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
40 #else
41 # define LOG_DISAS(...) do { } while (0)
42 #endif
44 typedef struct DisasContext DisasContext;
45 struct DisasContext {
46 DisasContextBase base;
48 #ifndef CONFIG_USER_ONLY
49 uint64_t palbr;
50 #endif
51 uint32_t tbflags;
52 int mem_idx;
54 /* implver and amask values for this CPU. */
55 int implver;
56 int amask;
58 /* Current rounding mode for this TB. */
59 int tb_rm;
60 /* Current flush-to-zero setting for this TB. */
61 int tb_ftz;
63 /* The set of registers active in the current context. */
64 TCGv *ir;
66 /* Temporaries for $31 and $f31 as source and destination. */
67 TCGv zero;
68 TCGv sink;
69 /* Temporary for immediate constants. */
70 TCGv lit;
73 /* Target-specific return values from translate_one, indicating the
74 state of the TB. Note that DISAS_NEXT indicates that we are not
75 exiting the TB. */
76 #define DISAS_PC_UPDATED_NOCHAIN DISAS_TARGET_0
77 #define DISAS_PC_UPDATED DISAS_TARGET_1
78 #define DISAS_PC_STALE DISAS_TARGET_2
80 /* global register indexes */
81 static TCGv cpu_std_ir[31];
82 static TCGv cpu_fir[31];
83 static TCGv cpu_pc;
84 static TCGv cpu_lock_addr;
85 static TCGv cpu_lock_value;
87 #ifndef CONFIG_USER_ONLY
88 static TCGv cpu_pal_ir[31];
89 #endif
91 #include "exec/gen-icount.h"
93 void alpha_translate_init(void)
95 #define DEF_VAR(V) { &cpu_##V, #V, offsetof(CPUAlphaState, V) }
97 typedef struct { TCGv *var; const char *name; int ofs; } GlobalVar;
98 static const GlobalVar vars[] = {
99 DEF_VAR(pc),
100 DEF_VAR(lock_addr),
101 DEF_VAR(lock_value),
104 #undef DEF_VAR
106 /* Use the symbolic register names that match the disassembler. */
107 static const char greg_names[31][4] = {
108 "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
109 "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp",
110 "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
111 "t10", "t11", "ra", "t12", "at", "gp", "sp"
113 static const char freg_names[31][4] = {
114 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
115 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
116 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
117 "f24", "f25", "f26", "f27", "f28", "f29", "f30"
119 #ifndef CONFIG_USER_ONLY
120 static const char shadow_names[8][8] = {
121 "pal_t7", "pal_s0", "pal_s1", "pal_s2",
122 "pal_s3", "pal_s4", "pal_s5", "pal_t11"
124 #endif
126 int i;
128 for (i = 0; i < 31; i++) {
129 cpu_std_ir[i] = tcg_global_mem_new_i64(cpu_env,
130 offsetof(CPUAlphaState, ir[i]),
131 greg_names[i]);
134 for (i = 0; i < 31; i++) {
135 cpu_fir[i] = tcg_global_mem_new_i64(cpu_env,
136 offsetof(CPUAlphaState, fir[i]),
137 freg_names[i]);
140 #ifndef CONFIG_USER_ONLY
141 memcpy(cpu_pal_ir, cpu_std_ir, sizeof(cpu_pal_ir));
142 for (i = 0; i < 8; i++) {
143 int r = (i == 7 ? 25 : i + 8);
144 cpu_pal_ir[r] = tcg_global_mem_new_i64(cpu_env,
145 offsetof(CPUAlphaState,
146 shadow[i]),
147 shadow_names[i]);
149 #endif
151 for (i = 0; i < ARRAY_SIZE(vars); ++i) {
152 const GlobalVar *v = &vars[i];
153 *v->var = tcg_global_mem_new_i64(cpu_env, v->ofs, v->name);
157 static TCGv load_zero(DisasContext *ctx)
159 if (!ctx->zero) {
160 ctx->zero = tcg_const_i64(0);
162 return ctx->zero;
165 static TCGv dest_sink(DisasContext *ctx)
167 if (!ctx->sink) {
168 ctx->sink = tcg_temp_new();
170 return ctx->sink;
173 static void free_context_temps(DisasContext *ctx)
175 if (ctx->sink) {
176 tcg_gen_discard_i64(ctx->sink);
177 tcg_temp_free(ctx->sink);
178 ctx->sink = NULL;
180 if (ctx->zero) {
181 tcg_temp_free(ctx->zero);
182 ctx->zero = NULL;
184 if (ctx->lit) {
185 tcg_temp_free(ctx->lit);
186 ctx->lit = NULL;
190 static TCGv load_gpr(DisasContext *ctx, unsigned reg)
192 if (likely(reg < 31)) {
193 return ctx->ir[reg];
194 } else {
195 return load_zero(ctx);
199 static TCGv load_gpr_lit(DisasContext *ctx, unsigned reg,
200 uint8_t lit, bool islit)
202 if (islit) {
203 ctx->lit = tcg_const_i64(lit);
204 return ctx->lit;
205 } else if (likely(reg < 31)) {
206 return ctx->ir[reg];
207 } else {
208 return load_zero(ctx);
212 static TCGv dest_gpr(DisasContext *ctx, unsigned reg)
214 if (likely(reg < 31)) {
215 return ctx->ir[reg];
216 } else {
217 return dest_sink(ctx);
221 static TCGv load_fpr(DisasContext *ctx, unsigned reg)
223 if (likely(reg < 31)) {
224 return cpu_fir[reg];
225 } else {
226 return load_zero(ctx);
230 static TCGv dest_fpr(DisasContext *ctx, unsigned reg)
232 if (likely(reg < 31)) {
233 return cpu_fir[reg];
234 } else {
235 return dest_sink(ctx);
239 static int get_flag_ofs(unsigned shift)
241 int ofs = offsetof(CPUAlphaState, flags);
242 #ifdef HOST_WORDS_BIGENDIAN
243 ofs += 3 - (shift / 8);
244 #else
245 ofs += shift / 8;
246 #endif
247 return ofs;
250 static void ld_flag_byte(TCGv val, unsigned shift)
252 tcg_gen_ld8u_i64(val, cpu_env, get_flag_ofs(shift));
255 static void st_flag_byte(TCGv val, unsigned shift)
257 tcg_gen_st8_i64(val, cpu_env, get_flag_ofs(shift));
260 static void gen_excp_1(int exception, int error_code)
262 TCGv_i32 tmp1, tmp2;
264 tmp1 = tcg_const_i32(exception);
265 tmp2 = tcg_const_i32(error_code);
266 gen_helper_excp(cpu_env, tmp1, tmp2);
267 tcg_temp_free_i32(tmp2);
268 tcg_temp_free_i32(tmp1);
271 static DisasJumpType gen_excp(DisasContext *ctx, int exception, int error_code)
273 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
274 gen_excp_1(exception, error_code);
275 return DISAS_NORETURN;
278 static inline DisasJumpType gen_invalid(DisasContext *ctx)
280 return gen_excp(ctx, EXCP_OPCDEC, 0);
283 static inline void gen_qemu_ldf(TCGv t0, TCGv t1, int flags)
285 TCGv_i32 tmp32 = tcg_temp_new_i32();
286 tcg_gen_qemu_ld_i32(tmp32, t1, flags, MO_LEUL);
287 gen_helper_memory_to_f(t0, tmp32);
288 tcg_temp_free_i32(tmp32);
291 static inline void gen_qemu_ldg(TCGv t0, TCGv t1, int flags)
293 TCGv tmp = tcg_temp_new();
294 tcg_gen_qemu_ld_i64(tmp, t1, flags, MO_LEQ);
295 gen_helper_memory_to_g(t0, tmp);
296 tcg_temp_free(tmp);
299 static inline void gen_qemu_lds(TCGv t0, TCGv t1, int flags)
301 TCGv_i32 tmp32 = tcg_temp_new_i32();
302 tcg_gen_qemu_ld_i32(tmp32, t1, flags, MO_LEUL);
303 gen_helper_memory_to_s(t0, tmp32);
304 tcg_temp_free_i32(tmp32);
307 static inline void gen_qemu_ldl_l(TCGv t0, TCGv t1, int flags)
309 tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LESL);
310 tcg_gen_mov_i64(cpu_lock_addr, t1);
311 tcg_gen_mov_i64(cpu_lock_value, t0);
314 static inline void gen_qemu_ldq_l(TCGv t0, TCGv t1, int flags)
316 tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LEQ);
317 tcg_gen_mov_i64(cpu_lock_addr, t1);
318 tcg_gen_mov_i64(cpu_lock_value, t0);
321 static inline void gen_load_mem(DisasContext *ctx,
322 void (*tcg_gen_qemu_load)(TCGv t0, TCGv t1,
323 int flags),
324 int ra, int rb, int32_t disp16, bool fp,
325 bool clear)
327 TCGv tmp, addr, va;
329 /* LDQ_U with ra $31 is UNOP. Other various loads are forms of
330 prefetches, which we can treat as nops. No worries about
331 missed exceptions here. */
332 if (unlikely(ra == 31)) {
333 return;
336 tmp = tcg_temp_new();
337 addr = load_gpr(ctx, rb);
339 if (disp16) {
340 tcg_gen_addi_i64(tmp, addr, disp16);
341 addr = tmp;
343 if (clear) {
344 tcg_gen_andi_i64(tmp, addr, ~0x7);
345 addr = tmp;
348 va = (fp ? cpu_fir[ra] : ctx->ir[ra]);
349 tcg_gen_qemu_load(va, addr, ctx->mem_idx);
351 tcg_temp_free(tmp);
354 static inline void gen_qemu_stf(TCGv t0, TCGv t1, int flags)
356 TCGv_i32 tmp32 = tcg_temp_new_i32();
357 gen_helper_f_to_memory(tmp32, t0);
358 tcg_gen_qemu_st_i32(tmp32, t1, flags, MO_LEUL);
359 tcg_temp_free_i32(tmp32);
362 static inline void gen_qemu_stg(TCGv t0, TCGv t1, int flags)
364 TCGv tmp = tcg_temp_new();
365 gen_helper_g_to_memory(tmp, t0);
366 tcg_gen_qemu_st_i64(tmp, t1, flags, MO_LEQ);
367 tcg_temp_free(tmp);
370 static inline void gen_qemu_sts(TCGv t0, TCGv t1, int flags)
372 TCGv_i32 tmp32 = tcg_temp_new_i32();
373 gen_helper_s_to_memory(tmp32, t0);
374 tcg_gen_qemu_st_i32(tmp32, t1, flags, MO_LEUL);
375 tcg_temp_free_i32(tmp32);
378 static inline void gen_store_mem(DisasContext *ctx,
379 void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1,
380 int flags),
381 int ra, int rb, int32_t disp16, bool fp,
382 bool clear)
384 TCGv tmp, addr, va;
386 tmp = tcg_temp_new();
387 addr = load_gpr(ctx, rb);
389 if (disp16) {
390 tcg_gen_addi_i64(tmp, addr, disp16);
391 addr = tmp;
393 if (clear) {
394 tcg_gen_andi_i64(tmp, addr, ~0x7);
395 addr = tmp;
398 va = (fp ? load_fpr(ctx, ra) : load_gpr(ctx, ra));
399 tcg_gen_qemu_store(va, addr, ctx->mem_idx);
401 tcg_temp_free(tmp);
404 static DisasJumpType gen_store_conditional(DisasContext *ctx, int ra, int rb,
405 int32_t disp16, int mem_idx,
406 MemOp op)
408 TCGLabel *lab_fail, *lab_done;
409 TCGv addr, val;
411 addr = tcg_temp_new_i64();
412 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
413 free_context_temps(ctx);
415 lab_fail = gen_new_label();
416 lab_done = gen_new_label();
417 tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
418 tcg_temp_free_i64(addr);
420 val = tcg_temp_new_i64();
421 tcg_gen_atomic_cmpxchg_i64(val, cpu_lock_addr, cpu_lock_value,
422 load_gpr(ctx, ra), mem_idx, op);
423 free_context_temps(ctx);
425 if (ra != 31) {
426 tcg_gen_setcond_i64(TCG_COND_EQ, ctx->ir[ra], val, cpu_lock_value);
428 tcg_temp_free_i64(val);
429 tcg_gen_br(lab_done);
431 gen_set_label(lab_fail);
432 if (ra != 31) {
433 tcg_gen_movi_i64(ctx->ir[ra], 0);
436 gen_set_label(lab_done);
437 tcg_gen_movi_i64(cpu_lock_addr, -1);
438 return DISAS_NEXT;
441 static bool in_superpage(DisasContext *ctx, int64_t addr)
443 #ifndef CONFIG_USER_ONLY
444 return ((ctx->tbflags & ENV_FLAG_PS_USER) == 0
445 && addr >> TARGET_VIRT_ADDR_SPACE_BITS == -1
446 && ((addr >> 41) & 3) == 2);
447 #else
448 return false;
449 #endif
452 static bool use_exit_tb(DisasContext *ctx)
454 return ((tb_cflags(ctx->base.tb) & CF_LAST_IO)
455 || ctx->base.singlestep_enabled
456 || singlestep);
459 static bool use_goto_tb(DisasContext *ctx, uint64_t dest)
461 /* Suppress goto_tb in the case of single-steping and IO. */
462 if (unlikely(use_exit_tb(ctx))) {
463 return false;
465 #ifndef CONFIG_USER_ONLY
466 /* If the destination is in the superpage, the page perms can't change. */
467 if (in_superpage(ctx, dest)) {
468 return true;
470 /* Check for the dest on the same page as the start of the TB. */
471 return ((ctx->base.tb->pc ^ dest) & TARGET_PAGE_MASK) == 0;
472 #else
473 return true;
474 #endif
477 static DisasJumpType gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
479 uint64_t dest = ctx->base.pc_next + (disp << 2);
481 if (ra != 31) {
482 tcg_gen_movi_i64(ctx->ir[ra], ctx->base.pc_next);
485 /* Notice branch-to-next; used to initialize RA with the PC. */
486 if (disp == 0) {
487 return 0;
488 } else if (use_goto_tb(ctx, dest)) {
489 tcg_gen_goto_tb(0);
490 tcg_gen_movi_i64(cpu_pc, dest);
491 tcg_gen_exit_tb(ctx->base.tb, 0);
492 return DISAS_NORETURN;
493 } else {
494 tcg_gen_movi_i64(cpu_pc, dest);
495 return DISAS_PC_UPDATED;
499 static DisasJumpType gen_bcond_internal(DisasContext *ctx, TCGCond cond,
500 TCGv cmp, int32_t disp)
502 uint64_t dest = ctx->base.pc_next + (disp << 2);
503 TCGLabel *lab_true = gen_new_label();
505 if (use_goto_tb(ctx, dest)) {
506 tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
508 tcg_gen_goto_tb(0);
509 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
510 tcg_gen_exit_tb(ctx->base.tb, 0);
512 gen_set_label(lab_true);
513 tcg_gen_goto_tb(1);
514 tcg_gen_movi_i64(cpu_pc, dest);
515 tcg_gen_exit_tb(ctx->base.tb, 1);
517 return DISAS_NORETURN;
518 } else {
519 TCGv_i64 z = tcg_const_i64(0);
520 TCGv_i64 d = tcg_const_i64(dest);
521 TCGv_i64 p = tcg_const_i64(ctx->base.pc_next);
523 tcg_gen_movcond_i64(cond, cpu_pc, cmp, z, d, p);
525 tcg_temp_free_i64(z);
526 tcg_temp_free_i64(d);
527 tcg_temp_free_i64(p);
528 return DISAS_PC_UPDATED;
532 static DisasJumpType gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
533 int32_t disp, int mask)
535 if (mask) {
536 TCGv tmp = tcg_temp_new();
537 DisasJumpType ret;
539 tcg_gen_andi_i64(tmp, load_gpr(ctx, ra), 1);
540 ret = gen_bcond_internal(ctx, cond, tmp, disp);
541 tcg_temp_free(tmp);
542 return ret;
544 return gen_bcond_internal(ctx, cond, load_gpr(ctx, ra), disp);
547 /* Fold -0.0 for comparison with COND. */
549 static void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src)
551 uint64_t mzero = 1ull << 63;
553 switch (cond) {
554 case TCG_COND_LE:
555 case TCG_COND_GT:
556 /* For <= or >, the -0.0 value directly compares the way we want. */
557 tcg_gen_mov_i64(dest, src);
558 break;
560 case TCG_COND_EQ:
561 case TCG_COND_NE:
562 /* For == or !=, we can simply mask off the sign bit and compare. */
563 tcg_gen_andi_i64(dest, src, mzero - 1);
564 break;
566 case TCG_COND_GE:
567 case TCG_COND_LT:
568 /* For >= or <, map -0.0 to +0.0 via comparison and mask. */
569 tcg_gen_setcondi_i64(TCG_COND_NE, dest, src, mzero);
570 tcg_gen_neg_i64(dest, dest);
571 tcg_gen_and_i64(dest, dest, src);
572 break;
574 default:
575 abort();
579 static DisasJumpType gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
580 int32_t disp)
582 TCGv cmp_tmp = tcg_temp_new();
583 DisasJumpType ret;
585 gen_fold_mzero(cond, cmp_tmp, load_fpr(ctx, ra));
586 ret = gen_bcond_internal(ctx, cond, cmp_tmp, disp);
587 tcg_temp_free(cmp_tmp);
588 return ret;
591 static void gen_fcmov(DisasContext *ctx, TCGCond cond, int ra, int rb, int rc)
593 TCGv_i64 va, vb, z;
595 z = load_zero(ctx);
596 vb = load_fpr(ctx, rb);
597 va = tcg_temp_new();
598 gen_fold_mzero(cond, va, load_fpr(ctx, ra));
600 tcg_gen_movcond_i64(cond, dest_fpr(ctx, rc), va, z, vb, load_fpr(ctx, rc));
602 tcg_temp_free(va);
605 #define QUAL_RM_N 0x080 /* Round mode nearest even */
606 #define QUAL_RM_C 0x000 /* Round mode chopped */
607 #define QUAL_RM_M 0x040 /* Round mode minus infinity */
608 #define QUAL_RM_D 0x0c0 /* Round mode dynamic */
609 #define QUAL_RM_MASK 0x0c0
611 #define QUAL_U 0x100 /* Underflow enable (fp output) */
612 #define QUAL_V 0x100 /* Overflow enable (int output) */
613 #define QUAL_S 0x400 /* Software completion enable */
614 #define QUAL_I 0x200 /* Inexact detection enable */
616 static void gen_qual_roundmode(DisasContext *ctx, int fn11)
618 TCGv_i32 tmp;
620 fn11 &= QUAL_RM_MASK;
621 if (fn11 == ctx->tb_rm) {
622 return;
624 ctx->tb_rm = fn11;
626 tmp = tcg_temp_new_i32();
627 switch (fn11) {
628 case QUAL_RM_N:
629 tcg_gen_movi_i32(tmp, float_round_nearest_even);
630 break;
631 case QUAL_RM_C:
632 tcg_gen_movi_i32(tmp, float_round_to_zero);
633 break;
634 case QUAL_RM_M:
635 tcg_gen_movi_i32(tmp, float_round_down);
636 break;
637 case QUAL_RM_D:
638 tcg_gen_ld8u_i32(tmp, cpu_env,
639 offsetof(CPUAlphaState, fpcr_dyn_round));
640 break;
643 #if defined(CONFIG_SOFTFLOAT_INLINE)
644 /* ??? The "fpu/softfloat.h" interface is to call set_float_rounding_mode.
645 With CONFIG_SOFTFLOAT that expands to an out-of-line call that just
646 sets the one field. */
647 tcg_gen_st8_i32(tmp, cpu_env,
648 offsetof(CPUAlphaState, fp_status.float_rounding_mode));
649 #else
650 gen_helper_setroundmode(tmp);
651 #endif
653 tcg_temp_free_i32(tmp);
656 static void gen_qual_flushzero(DisasContext *ctx, int fn11)
658 TCGv_i32 tmp;
660 fn11 &= QUAL_U;
661 if (fn11 == ctx->tb_ftz) {
662 return;
664 ctx->tb_ftz = fn11;
666 tmp = tcg_temp_new_i32();
667 if (fn11) {
668 /* Underflow is enabled, use the FPCR setting. */
669 tcg_gen_ld8u_i32(tmp, cpu_env,
670 offsetof(CPUAlphaState, fpcr_flush_to_zero));
671 } else {
672 /* Underflow is disabled, force flush-to-zero. */
673 tcg_gen_movi_i32(tmp, 1);
676 #if defined(CONFIG_SOFTFLOAT_INLINE)
677 tcg_gen_st8_i32(tmp, cpu_env,
678 offsetof(CPUAlphaState, fp_status.flush_to_zero));
679 #else
680 gen_helper_setflushzero(tmp);
681 #endif
683 tcg_temp_free_i32(tmp);
686 static TCGv gen_ieee_input(DisasContext *ctx, int reg, int fn11, int is_cmp)
688 TCGv val;
690 if (unlikely(reg == 31)) {
691 val = load_zero(ctx);
692 } else {
693 val = cpu_fir[reg];
694 if ((fn11 & QUAL_S) == 0) {
695 if (is_cmp) {
696 gen_helper_ieee_input_cmp(cpu_env, val);
697 } else {
698 gen_helper_ieee_input(cpu_env, val);
700 } else {
701 #ifndef CONFIG_USER_ONLY
702 /* In system mode, raise exceptions for denormals like real
703 hardware. In user mode, proceed as if the OS completion
704 handler is handling the denormal as per spec. */
705 gen_helper_ieee_input_s(cpu_env, val);
706 #endif
709 return val;
712 static void gen_fp_exc_raise(int rc, int fn11)
714 /* ??? We ought to be able to do something with imprecise exceptions.
715 E.g. notice we're still in the trap shadow of something within the
716 TB and do not generate the code to signal the exception; end the TB
717 when an exception is forced to arrive, either by consumption of a
718 register value or TRAPB or EXCB. */
719 TCGv_i32 reg, ign;
720 uint32_t ignore = 0;
722 if (!(fn11 & QUAL_U)) {
723 /* Note that QUAL_U == QUAL_V, so ignore either. */
724 ignore |= FPCR_UNF | FPCR_IOV;
726 if (!(fn11 & QUAL_I)) {
727 ignore |= FPCR_INE;
729 ign = tcg_const_i32(ignore);
731 /* ??? Pass in the regno of the destination so that the helper can
732 set EXC_MASK, which contains a bitmask of destination registers
733 that have caused arithmetic traps. A simple userspace emulation
734 does not require this. We do need it for a guest kernel's entArith,
735 or if we were to do something clever with imprecise exceptions. */
736 reg = tcg_const_i32(rc + 32);
737 if (fn11 & QUAL_S) {
738 gen_helper_fp_exc_raise_s(cpu_env, ign, reg);
739 } else {
740 gen_helper_fp_exc_raise(cpu_env, ign, reg);
743 tcg_temp_free_i32(reg);
744 tcg_temp_free_i32(ign);
747 static void gen_cvtlq(TCGv vc, TCGv vb)
749 TCGv tmp = tcg_temp_new();
751 /* The arithmetic right shift here, plus the sign-extended mask below
752 yields a sign-extended result without an explicit ext32s_i64. */
753 tcg_gen_shri_i64(tmp, vb, 29);
754 tcg_gen_sari_i64(vc, vb, 32);
755 tcg_gen_deposit_i64(vc, vc, tmp, 0, 30);
757 tcg_temp_free(tmp);
760 static void gen_ieee_arith2(DisasContext *ctx,
761 void (*helper)(TCGv, TCGv_ptr, TCGv),
762 int rb, int rc, int fn11)
764 TCGv vb;
766 gen_qual_roundmode(ctx, fn11);
767 gen_qual_flushzero(ctx, fn11);
769 vb = gen_ieee_input(ctx, rb, fn11, 0);
770 helper(dest_fpr(ctx, rc), cpu_env, vb);
772 gen_fp_exc_raise(rc, fn11);
775 #define IEEE_ARITH2(name) \
776 static inline void glue(gen_, name)(DisasContext *ctx, \
777 int rb, int rc, int fn11) \
779 gen_ieee_arith2(ctx, gen_helper_##name, rb, rc, fn11); \
781 IEEE_ARITH2(sqrts)
782 IEEE_ARITH2(sqrtt)
783 IEEE_ARITH2(cvtst)
784 IEEE_ARITH2(cvtts)
786 static void gen_cvttq(DisasContext *ctx, int rb, int rc, int fn11)
788 TCGv vb, vc;
790 /* No need to set flushzero, since we have an integer output. */
791 vb = gen_ieee_input(ctx, rb, fn11, 0);
792 vc = dest_fpr(ctx, rc);
794 /* Almost all integer conversions use cropped rounding;
795 special case that. */
796 if ((fn11 & QUAL_RM_MASK) == QUAL_RM_C) {
797 gen_helper_cvttq_c(vc, cpu_env, vb);
798 } else {
799 gen_qual_roundmode(ctx, fn11);
800 gen_helper_cvttq(vc, cpu_env, vb);
802 gen_fp_exc_raise(rc, fn11);
805 static void gen_ieee_intcvt(DisasContext *ctx,
806 void (*helper)(TCGv, TCGv_ptr, TCGv),
807 int rb, int rc, int fn11)
809 TCGv vb, vc;
811 gen_qual_roundmode(ctx, fn11);
812 vb = load_fpr(ctx, rb);
813 vc = dest_fpr(ctx, rc);
815 /* The only exception that can be raised by integer conversion
816 is inexact. Thus we only need to worry about exceptions when
817 inexact handling is requested. */
818 if (fn11 & QUAL_I) {
819 helper(vc, cpu_env, vb);
820 gen_fp_exc_raise(rc, fn11);
821 } else {
822 helper(vc, cpu_env, vb);
826 #define IEEE_INTCVT(name) \
827 static inline void glue(gen_, name)(DisasContext *ctx, \
828 int rb, int rc, int fn11) \
830 gen_ieee_intcvt(ctx, gen_helper_##name, rb, rc, fn11); \
832 IEEE_INTCVT(cvtqs)
833 IEEE_INTCVT(cvtqt)
835 static void gen_cpy_mask(TCGv vc, TCGv va, TCGv vb, bool inv_a, uint64_t mask)
837 TCGv vmask = tcg_const_i64(mask);
838 TCGv tmp = tcg_temp_new_i64();
840 if (inv_a) {
841 tcg_gen_andc_i64(tmp, vmask, va);
842 } else {
843 tcg_gen_and_i64(tmp, va, vmask);
846 tcg_gen_andc_i64(vc, vb, vmask);
847 tcg_gen_or_i64(vc, vc, tmp);
849 tcg_temp_free(vmask);
850 tcg_temp_free(tmp);
853 static void gen_ieee_arith3(DisasContext *ctx,
854 void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
855 int ra, int rb, int rc, int fn11)
857 TCGv va, vb, vc;
859 gen_qual_roundmode(ctx, fn11);
860 gen_qual_flushzero(ctx, fn11);
862 va = gen_ieee_input(ctx, ra, fn11, 0);
863 vb = gen_ieee_input(ctx, rb, fn11, 0);
864 vc = dest_fpr(ctx, rc);
865 helper(vc, cpu_env, va, vb);
867 gen_fp_exc_raise(rc, fn11);
870 #define IEEE_ARITH3(name) \
871 static inline void glue(gen_, name)(DisasContext *ctx, \
872 int ra, int rb, int rc, int fn11) \
874 gen_ieee_arith3(ctx, gen_helper_##name, ra, rb, rc, fn11); \
876 IEEE_ARITH3(adds)
877 IEEE_ARITH3(subs)
878 IEEE_ARITH3(muls)
879 IEEE_ARITH3(divs)
880 IEEE_ARITH3(addt)
881 IEEE_ARITH3(subt)
882 IEEE_ARITH3(mult)
883 IEEE_ARITH3(divt)
885 static void gen_ieee_compare(DisasContext *ctx,
886 void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
887 int ra, int rb, int rc, int fn11)
889 TCGv va, vb, vc;
891 va = gen_ieee_input(ctx, ra, fn11, 1);
892 vb = gen_ieee_input(ctx, rb, fn11, 1);
893 vc = dest_fpr(ctx, rc);
894 helper(vc, cpu_env, va, vb);
896 gen_fp_exc_raise(rc, fn11);
899 #define IEEE_CMP3(name) \
900 static inline void glue(gen_, name)(DisasContext *ctx, \
901 int ra, int rb, int rc, int fn11) \
903 gen_ieee_compare(ctx, gen_helper_##name, ra, rb, rc, fn11); \
905 IEEE_CMP3(cmptun)
906 IEEE_CMP3(cmpteq)
907 IEEE_CMP3(cmptlt)
908 IEEE_CMP3(cmptle)
910 static inline uint64_t zapnot_mask(uint8_t lit)
912 uint64_t mask = 0;
913 int i;
915 for (i = 0; i < 8; ++i) {
916 if ((lit >> i) & 1) {
917 mask |= 0xffull << (i * 8);
920 return mask;
923 /* Implement zapnot with an immediate operand, which expands to some
924 form of immediate AND. This is a basic building block in the
925 definition of many of the other byte manipulation instructions. */
926 static void gen_zapnoti(TCGv dest, TCGv src, uint8_t lit)
928 switch (lit) {
929 case 0x00:
930 tcg_gen_movi_i64(dest, 0);
931 break;
932 case 0x01:
933 tcg_gen_ext8u_i64(dest, src);
934 break;
935 case 0x03:
936 tcg_gen_ext16u_i64(dest, src);
937 break;
938 case 0x0f:
939 tcg_gen_ext32u_i64(dest, src);
940 break;
941 case 0xff:
942 tcg_gen_mov_i64(dest, src);
943 break;
944 default:
945 tcg_gen_andi_i64(dest, src, zapnot_mask(lit));
946 break;
950 /* EXTWH, EXTLH, EXTQH */
951 static void gen_ext_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
952 uint8_t lit, uint8_t byte_mask)
954 if (islit) {
955 int pos = (64 - lit * 8) & 0x3f;
956 int len = cto32(byte_mask) * 8;
957 if (pos < len) {
958 tcg_gen_deposit_z_i64(vc, va, pos, len - pos);
959 } else {
960 tcg_gen_movi_i64(vc, 0);
962 } else {
963 TCGv tmp = tcg_temp_new();
964 tcg_gen_shli_i64(tmp, load_gpr(ctx, rb), 3);
965 tcg_gen_neg_i64(tmp, tmp);
966 tcg_gen_andi_i64(tmp, tmp, 0x3f);
967 tcg_gen_shl_i64(vc, va, tmp);
968 tcg_temp_free(tmp);
970 gen_zapnoti(vc, vc, byte_mask);
973 /* EXTBL, EXTWL, EXTLL, EXTQL */
974 static void gen_ext_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
975 uint8_t lit, uint8_t byte_mask)
977 if (islit) {
978 int pos = (lit & 7) * 8;
979 int len = cto32(byte_mask) * 8;
980 if (pos + len >= 64) {
981 len = 64 - pos;
983 tcg_gen_extract_i64(vc, va, pos, len);
984 } else {
985 TCGv tmp = tcg_temp_new();
986 tcg_gen_andi_i64(tmp, load_gpr(ctx, rb), 7);
987 tcg_gen_shli_i64(tmp, tmp, 3);
988 tcg_gen_shr_i64(vc, va, tmp);
989 tcg_temp_free(tmp);
990 gen_zapnoti(vc, vc, byte_mask);
994 /* INSWH, INSLH, INSQH */
995 static void gen_ins_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
996 uint8_t lit, uint8_t byte_mask)
998 if (islit) {
999 int pos = 64 - (lit & 7) * 8;
1000 int len = cto32(byte_mask) * 8;
1001 if (pos < len) {
1002 tcg_gen_extract_i64(vc, va, pos, len - pos);
1003 } else {
1004 tcg_gen_movi_i64(vc, 0);
1006 } else {
1007 TCGv tmp = tcg_temp_new();
1008 TCGv shift = tcg_temp_new();
1010 /* The instruction description has us left-shift the byte mask
1011 and extract bits <15:8> and apply that zap at the end. This
1012 is equivalent to simply performing the zap first and shifting
1013 afterward. */
1014 gen_zapnoti(tmp, va, byte_mask);
1016 /* If (B & 7) == 0, we need to shift by 64 and leave a zero. Do this
1017 portably by splitting the shift into two parts: shift_count-1 and 1.
1018 Arrange for the -1 by using ones-complement instead of
1019 twos-complement in the negation: ~(B * 8) & 63. */
1021 tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3);
1022 tcg_gen_not_i64(shift, shift);
1023 tcg_gen_andi_i64(shift, shift, 0x3f);
1025 tcg_gen_shr_i64(vc, tmp, shift);
1026 tcg_gen_shri_i64(vc, vc, 1);
1027 tcg_temp_free(shift);
1028 tcg_temp_free(tmp);
1032 /* INSBL, INSWL, INSLL, INSQL */
1033 static void gen_ins_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
1034 uint8_t lit, uint8_t byte_mask)
1036 if (islit) {
1037 int pos = (lit & 7) * 8;
1038 int len = cto32(byte_mask) * 8;
1039 if (pos + len > 64) {
1040 len = 64 - pos;
1042 tcg_gen_deposit_z_i64(vc, va, pos, len);
1043 } else {
1044 TCGv tmp = tcg_temp_new();
1045 TCGv shift = tcg_temp_new();
1047 /* The instruction description has us left-shift the byte mask
1048 and extract bits <15:8> and apply that zap at the end. This
1049 is equivalent to simply performing the zap first and shifting
1050 afterward. */
1051 gen_zapnoti(tmp, va, byte_mask);
1053 tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
1054 tcg_gen_shli_i64(shift, shift, 3);
1055 tcg_gen_shl_i64(vc, tmp, shift);
1056 tcg_temp_free(shift);
1057 tcg_temp_free(tmp);
1061 /* MSKWH, MSKLH, MSKQH */
1062 static void gen_msk_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
1063 uint8_t lit, uint8_t byte_mask)
1065 if (islit) {
1066 gen_zapnoti(vc, va, ~((byte_mask << (lit & 7)) >> 8));
1067 } else {
1068 TCGv shift = tcg_temp_new();
1069 TCGv mask = tcg_temp_new();
1071 /* The instruction description is as above, where the byte_mask
1072 is shifted left, and then we extract bits <15:8>. This can be
1073 emulated with a right-shift on the expanded byte mask. This
1074 requires extra care because for an input <2:0> == 0 we need a
1075 shift of 64 bits in order to generate a zero. This is done by
1076 splitting the shift into two parts, the variable shift - 1
1077 followed by a constant 1 shift. The code we expand below is
1078 equivalent to ~(B * 8) & 63. */
1080 tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3);
1081 tcg_gen_not_i64(shift, shift);
1082 tcg_gen_andi_i64(shift, shift, 0x3f);
1083 tcg_gen_movi_i64(mask, zapnot_mask (byte_mask));
1084 tcg_gen_shr_i64(mask, mask, shift);
1085 tcg_gen_shri_i64(mask, mask, 1);
1087 tcg_gen_andc_i64(vc, va, mask);
1089 tcg_temp_free(mask);
1090 tcg_temp_free(shift);
1094 /* MSKBL, MSKWL, MSKLL, MSKQL */
1095 static void gen_msk_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
1096 uint8_t lit, uint8_t byte_mask)
1098 if (islit) {
1099 gen_zapnoti(vc, va, ~(byte_mask << (lit & 7)));
1100 } else {
1101 TCGv shift = tcg_temp_new();
1102 TCGv mask = tcg_temp_new();
1104 tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
1105 tcg_gen_shli_i64(shift, shift, 3);
1106 tcg_gen_movi_i64(mask, zapnot_mask(byte_mask));
1107 tcg_gen_shl_i64(mask, mask, shift);
1109 tcg_gen_andc_i64(vc, va, mask);
1111 tcg_temp_free(mask);
1112 tcg_temp_free(shift);
1116 static void gen_rx(DisasContext *ctx, int ra, int set)
1118 TCGv tmp;
1120 if (ra != 31) {
1121 ld_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT);
1124 tmp = tcg_const_i64(set);
1125 st_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT);
1126 tcg_temp_free(tmp);
1129 static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode)
1131 /* We're emulating OSF/1 PALcode. Many of these are trivial access
1132 to internal cpu registers. */
1134 /* Unprivileged PAL call */
1135 if (palcode >= 0x80 && palcode < 0xC0) {
1136 switch (palcode) {
1137 case 0x86:
1138 /* IMB */
1139 /* No-op inside QEMU. */
1140 break;
1141 case 0x9E:
1142 /* RDUNIQUE */
1143 tcg_gen_ld_i64(ctx->ir[IR_V0], cpu_env,
1144 offsetof(CPUAlphaState, unique));
1145 break;
1146 case 0x9F:
1147 /* WRUNIQUE */
1148 tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env,
1149 offsetof(CPUAlphaState, unique));
1150 break;
1151 default:
1152 palcode &= 0xbf;
1153 goto do_call_pal;
1155 return DISAS_NEXT;
1158 #ifndef CONFIG_USER_ONLY
1159 /* Privileged PAL code */
1160 if (palcode < 0x40 && (ctx->tbflags & ENV_FLAG_PS_USER) == 0) {
1161 switch (palcode) {
1162 case 0x01:
1163 /* CFLUSH */
1164 /* No-op inside QEMU. */
1165 break;
1166 case 0x02:
1167 /* DRAINA */
1168 /* No-op inside QEMU. */
1169 break;
1170 case 0x2D:
1171 /* WRVPTPTR */
1172 tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env,
1173 offsetof(CPUAlphaState, vptptr));
1174 break;
1175 case 0x31:
1176 /* WRVAL */
1177 tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env,
1178 offsetof(CPUAlphaState, sysval));
1179 break;
1180 case 0x32:
1181 /* RDVAL */
1182 tcg_gen_ld_i64(ctx->ir[IR_V0], cpu_env,
1183 offsetof(CPUAlphaState, sysval));
1184 break;
1186 case 0x35:
1187 /* SWPIPL */
1188 /* Note that we already know we're in kernel mode, so we know
1189 that PS only contains the 3 IPL bits. */
1190 ld_flag_byte(ctx->ir[IR_V0], ENV_FLAG_PS_SHIFT);
1192 /* But make sure and store only the 3 IPL bits from the user. */
1194 TCGv tmp = tcg_temp_new();
1195 tcg_gen_andi_i64(tmp, ctx->ir[IR_A0], PS_INT_MASK);
1196 st_flag_byte(tmp, ENV_FLAG_PS_SHIFT);
1197 tcg_temp_free(tmp);
1200 /* Allow interrupts to be recognized right away. */
1201 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
1202 return DISAS_PC_UPDATED_NOCHAIN;
1204 case 0x36:
1205 /* RDPS */
1206 ld_flag_byte(ctx->ir[IR_V0], ENV_FLAG_PS_SHIFT);
1207 break;
1209 case 0x38:
1210 /* WRUSP */
1211 tcg_gen_st_i64(ctx->ir[IR_A0], cpu_env,
1212 offsetof(CPUAlphaState, usp));
1213 break;
1214 case 0x3A:
1215 /* RDUSP */
1216 tcg_gen_ld_i64(ctx->ir[IR_V0], cpu_env,
1217 offsetof(CPUAlphaState, usp));
1218 break;
1219 case 0x3C:
1220 /* WHAMI */
1221 tcg_gen_ld32s_i64(ctx->ir[IR_V0], cpu_env,
1222 -offsetof(AlphaCPU, env) + offsetof(CPUState, cpu_index));
1223 break;
1225 case 0x3E:
1226 /* WTINT */
1228 TCGv_i32 tmp = tcg_const_i32(1);
1229 tcg_gen_st_i32(tmp, cpu_env, -offsetof(AlphaCPU, env) +
1230 offsetof(CPUState, halted));
1231 tcg_temp_free_i32(tmp);
1233 tcg_gen_movi_i64(ctx->ir[IR_V0], 0);
1234 return gen_excp(ctx, EXCP_HALTED, 0);
1236 default:
1237 palcode &= 0x3f;
1238 goto do_call_pal;
1240 return DISAS_NEXT;
1242 #endif
1243 return gen_invalid(ctx);
1245 do_call_pal:
1246 #ifdef CONFIG_USER_ONLY
1247 return gen_excp(ctx, EXCP_CALL_PAL, palcode);
1248 #else
1250 TCGv tmp = tcg_temp_new();
1251 uint64_t exc_addr = ctx->base.pc_next;
1252 uint64_t entry = ctx->palbr;
1254 if (ctx->tbflags & ENV_FLAG_PAL_MODE) {
1255 exc_addr |= 1;
1256 } else {
1257 tcg_gen_movi_i64(tmp, 1);
1258 st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT);
1261 tcg_gen_movi_i64(tmp, exc_addr);
1262 tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUAlphaState, exc_addr));
1263 tcg_temp_free(tmp);
1265 entry += (palcode & 0x80
1266 ? 0x2000 + (palcode - 0x80) * 64
1267 : 0x1000 + palcode * 64);
1269 /* Since the destination is running in PALmode, we don't really
1270 need the page permissions check. We'll see the existence of
1271 the page when we create the TB, and we'll flush all TBs if
1272 we change the PAL base register. */
1273 if (!use_exit_tb(ctx)) {
1274 tcg_gen_goto_tb(0);
1275 tcg_gen_movi_i64(cpu_pc, entry);
1276 tcg_gen_exit_tb(ctx->base.tb, 0);
1277 return DISAS_NORETURN;
1278 } else {
1279 tcg_gen_movi_i64(cpu_pc, entry);
1280 return DISAS_PC_UPDATED;
1283 #endif
1286 #ifndef CONFIG_USER_ONLY
1288 #define PR_LONG 0x200000
1290 static int cpu_pr_data(int pr)
1292 switch (pr) {
1293 case 2: return offsetof(CPUAlphaState, pcc_ofs) | PR_LONG;
1294 case 3: return offsetof(CPUAlphaState, trap_arg0);
1295 case 4: return offsetof(CPUAlphaState, trap_arg1);
1296 case 5: return offsetof(CPUAlphaState, trap_arg2);
1297 case 6: return offsetof(CPUAlphaState, exc_addr);
1298 case 7: return offsetof(CPUAlphaState, palbr);
1299 case 8: return offsetof(CPUAlphaState, ptbr);
1300 case 9: return offsetof(CPUAlphaState, vptptr);
1301 case 10: return offsetof(CPUAlphaState, unique);
1302 case 11: return offsetof(CPUAlphaState, sysval);
1303 case 12: return offsetof(CPUAlphaState, usp);
1305 case 40 ... 63:
1306 return offsetof(CPUAlphaState, scratch[pr - 40]);
1308 case 251:
1309 return offsetof(CPUAlphaState, alarm_expire);
1311 return 0;
1314 static DisasJumpType gen_mfpr(DisasContext *ctx, TCGv va, int regno)
1316 void (*helper)(TCGv);
1317 int data;
1319 switch (regno) {
1320 case 32 ... 39:
1321 /* Accessing the "non-shadow" general registers. */
1322 regno = regno == 39 ? 25 : regno - 32 + 8;
1323 tcg_gen_mov_i64(va, cpu_std_ir[regno]);
1324 break;
1326 case 250: /* WALLTIME */
1327 helper = gen_helper_get_walltime;
1328 goto do_helper;
1329 case 249: /* VMTIME */
1330 helper = gen_helper_get_vmtime;
1331 do_helper:
1332 if (use_icount) {
1333 gen_io_start();
1334 helper(va);
1335 return DISAS_PC_STALE;
1336 } else {
1337 helper(va);
1339 break;
1341 case 0: /* PS */
1342 ld_flag_byte(va, ENV_FLAG_PS_SHIFT);
1343 break;
1344 case 1: /* FEN */
1345 ld_flag_byte(va, ENV_FLAG_FEN_SHIFT);
1346 break;
1348 default:
1349 /* The basic registers are data only, and unknown registers
1350 are read-zero, write-ignore. */
1351 data = cpu_pr_data(regno);
1352 if (data == 0) {
1353 tcg_gen_movi_i64(va, 0);
1354 } else if (data & PR_LONG) {
1355 tcg_gen_ld32s_i64(va, cpu_env, data & ~PR_LONG);
1356 } else {
1357 tcg_gen_ld_i64(va, cpu_env, data);
1359 break;
1362 return DISAS_NEXT;
1365 static DisasJumpType gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
1367 int data;
1369 switch (regno) {
1370 case 255:
1371 /* TBIA */
1372 gen_helper_tbia(cpu_env);
1373 break;
1375 case 254:
1376 /* TBIS */
1377 gen_helper_tbis(cpu_env, vb);
1378 break;
1380 case 253:
1381 /* WAIT */
1383 TCGv_i32 tmp = tcg_const_i32(1);
1384 tcg_gen_st_i32(tmp, cpu_env, -offsetof(AlphaCPU, env) +
1385 offsetof(CPUState, halted));
1386 tcg_temp_free_i32(tmp);
1388 return gen_excp(ctx, EXCP_HALTED, 0);
1390 case 252:
1391 /* HALT */
1392 gen_helper_halt(vb);
1393 return DISAS_PC_STALE;
1395 case 251:
1396 /* ALARM */
1397 gen_helper_set_alarm(cpu_env, vb);
1398 break;
1400 case 7:
1401 /* PALBR */
1402 tcg_gen_st_i64(vb, cpu_env, offsetof(CPUAlphaState, palbr));
1403 /* Changing the PAL base register implies un-chaining all of the TBs
1404 that ended with a CALL_PAL. Since the base register usually only
1405 changes during boot, flushing everything works well. */
1406 gen_helper_tb_flush(cpu_env);
1407 return DISAS_PC_STALE;
1409 case 32 ... 39:
1410 /* Accessing the "non-shadow" general registers. */
1411 regno = regno == 39 ? 25 : regno - 32 + 8;
1412 tcg_gen_mov_i64(cpu_std_ir[regno], vb);
1413 break;
1415 case 0: /* PS */
1416 st_flag_byte(vb, ENV_FLAG_PS_SHIFT);
1417 break;
1418 case 1: /* FEN */
1419 st_flag_byte(vb, ENV_FLAG_FEN_SHIFT);
1420 break;
1422 default:
1423 /* The basic registers are data only, and unknown registers
1424 are read-zero, write-ignore. */
1425 data = cpu_pr_data(regno);
1426 if (data != 0) {
1427 if (data & PR_LONG) {
1428 tcg_gen_st32_i64(vb, cpu_env, data & ~PR_LONG);
1429 } else {
1430 tcg_gen_st_i64(vb, cpu_env, data);
1433 break;
1436 return DISAS_NEXT;
1438 #endif /* !USER_ONLY*/
1440 #define REQUIRE_NO_LIT \
1441 do { \
1442 if (real_islit) { \
1443 goto invalid_opc; \
1445 } while (0)
1447 #define REQUIRE_AMASK(FLAG) \
1448 do { \
1449 if ((ctx->amask & AMASK_##FLAG) == 0) { \
1450 goto invalid_opc; \
1452 } while (0)
1454 #define REQUIRE_TB_FLAG(FLAG) \
1455 do { \
1456 if ((ctx->tbflags & (FLAG)) == 0) { \
1457 goto invalid_opc; \
1459 } while (0)
1461 #define REQUIRE_REG_31(WHICH) \
1462 do { \
1463 if (WHICH != 31) { \
1464 goto invalid_opc; \
1466 } while (0)
1468 static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
1470 int32_t disp21, disp16, disp12 __attribute__((unused));
1471 uint16_t fn11;
1472 uint8_t opc, ra, rb, rc, fpfn, fn7, lit;
1473 bool islit, real_islit;
1474 TCGv va, vb, vc, tmp, tmp2;
1475 TCGv_i32 t32;
1476 DisasJumpType ret;
1478 /* Decode all instruction fields */
1479 opc = extract32(insn, 26, 6);
1480 ra = extract32(insn, 21, 5);
1481 rb = extract32(insn, 16, 5);
1482 rc = extract32(insn, 0, 5);
1483 real_islit = islit = extract32(insn, 12, 1);
1484 lit = extract32(insn, 13, 8);
1486 disp21 = sextract32(insn, 0, 21);
1487 disp16 = sextract32(insn, 0, 16);
1488 disp12 = sextract32(insn, 0, 12);
1490 fn11 = extract32(insn, 5, 11);
1491 fpfn = extract32(insn, 5, 6);
1492 fn7 = extract32(insn, 5, 7);
1494 if (rb == 31 && !islit) {
1495 islit = true;
1496 lit = 0;
1499 ret = DISAS_NEXT;
1500 switch (opc) {
1501 case 0x00:
1502 /* CALL_PAL */
1503 ret = gen_call_pal(ctx, insn & 0x03ffffff);
1504 break;
1505 case 0x01:
1506 /* OPC01 */
1507 goto invalid_opc;
1508 case 0x02:
1509 /* OPC02 */
1510 goto invalid_opc;
1511 case 0x03:
1512 /* OPC03 */
1513 goto invalid_opc;
1514 case 0x04:
1515 /* OPC04 */
1516 goto invalid_opc;
1517 case 0x05:
1518 /* OPC05 */
1519 goto invalid_opc;
1520 case 0x06:
1521 /* OPC06 */
1522 goto invalid_opc;
1523 case 0x07:
1524 /* OPC07 */
1525 goto invalid_opc;
1527 case 0x09:
1528 /* LDAH */
1529 disp16 = (uint32_t)disp16 << 16;
1530 /* fall through */
1531 case 0x08:
1532 /* LDA */
1533 va = dest_gpr(ctx, ra);
1534 /* It's worth special-casing immediate loads. */
1535 if (rb == 31) {
1536 tcg_gen_movi_i64(va, disp16);
1537 } else {
1538 tcg_gen_addi_i64(va, load_gpr(ctx, rb), disp16);
1540 break;
1542 case 0x0A:
1543 /* LDBU */
1544 REQUIRE_AMASK(BWX);
1545 gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
1546 break;
1547 case 0x0B:
1548 /* LDQ_U */
1549 gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 1);
1550 break;
1551 case 0x0C:
1552 /* LDWU */
1553 REQUIRE_AMASK(BWX);
1554 gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 0);
1555 break;
1556 case 0x0D:
1557 /* STW */
1558 REQUIRE_AMASK(BWX);
1559 gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0);
1560 break;
1561 case 0x0E:
1562 /* STB */
1563 REQUIRE_AMASK(BWX);
1564 gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0);
1565 break;
1566 case 0x0F:
1567 /* STQ_U */
1568 gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1);
1569 break;
1571 case 0x10:
1572 vc = dest_gpr(ctx, rc);
1573 vb = load_gpr_lit(ctx, rb, lit, islit);
1575 if (ra == 31) {
1576 if (fn7 == 0x00) {
1577 /* Special case ADDL as SEXTL. */
1578 tcg_gen_ext32s_i64(vc, vb);
1579 break;
1581 if (fn7 == 0x29) {
1582 /* Special case SUBQ as NEGQ. */
1583 tcg_gen_neg_i64(vc, vb);
1584 break;
1588 va = load_gpr(ctx, ra);
1589 switch (fn7) {
1590 case 0x00:
1591 /* ADDL */
1592 tcg_gen_add_i64(vc, va, vb);
1593 tcg_gen_ext32s_i64(vc, vc);
1594 break;
1595 case 0x02:
1596 /* S4ADDL */
1597 tmp = tcg_temp_new();
1598 tcg_gen_shli_i64(tmp, va, 2);
1599 tcg_gen_add_i64(tmp, tmp, vb);
1600 tcg_gen_ext32s_i64(vc, tmp);
1601 tcg_temp_free(tmp);
1602 break;
1603 case 0x09:
1604 /* SUBL */
1605 tcg_gen_sub_i64(vc, va, vb);
1606 tcg_gen_ext32s_i64(vc, vc);
1607 break;
1608 case 0x0B:
1609 /* S4SUBL */
1610 tmp = tcg_temp_new();
1611 tcg_gen_shli_i64(tmp, va, 2);
1612 tcg_gen_sub_i64(tmp, tmp, vb);
1613 tcg_gen_ext32s_i64(vc, tmp);
1614 tcg_temp_free(tmp);
1615 break;
1616 case 0x0F:
1617 /* CMPBGE */
1618 if (ra == 31) {
1619 /* Special case 0 >= X as X == 0. */
1620 gen_helper_cmpbe0(vc, vb);
1621 } else {
1622 gen_helper_cmpbge(vc, va, vb);
1624 break;
1625 case 0x12:
1626 /* S8ADDL */
1627 tmp = tcg_temp_new();
1628 tcg_gen_shli_i64(tmp, va, 3);
1629 tcg_gen_add_i64(tmp, tmp, vb);
1630 tcg_gen_ext32s_i64(vc, tmp);
1631 tcg_temp_free(tmp);
1632 break;
1633 case 0x1B:
1634 /* S8SUBL */
1635 tmp = tcg_temp_new();
1636 tcg_gen_shli_i64(tmp, va, 3);
1637 tcg_gen_sub_i64(tmp, tmp, vb);
1638 tcg_gen_ext32s_i64(vc, tmp);
1639 tcg_temp_free(tmp);
1640 break;
1641 case 0x1D:
1642 /* CMPULT */
1643 tcg_gen_setcond_i64(TCG_COND_LTU, vc, va, vb);
1644 break;
1645 case 0x20:
1646 /* ADDQ */
1647 tcg_gen_add_i64(vc, va, vb);
1648 break;
1649 case 0x22:
1650 /* S4ADDQ */
1651 tmp = tcg_temp_new();
1652 tcg_gen_shli_i64(tmp, va, 2);
1653 tcg_gen_add_i64(vc, tmp, vb);
1654 tcg_temp_free(tmp);
1655 break;
1656 case 0x29:
1657 /* SUBQ */
1658 tcg_gen_sub_i64(vc, va, vb);
1659 break;
1660 case 0x2B:
1661 /* S4SUBQ */
1662 tmp = tcg_temp_new();
1663 tcg_gen_shli_i64(tmp, va, 2);
1664 tcg_gen_sub_i64(vc, tmp, vb);
1665 tcg_temp_free(tmp);
1666 break;
1667 case 0x2D:
1668 /* CMPEQ */
1669 tcg_gen_setcond_i64(TCG_COND_EQ, vc, va, vb);
1670 break;
1671 case 0x32:
1672 /* S8ADDQ */
1673 tmp = tcg_temp_new();
1674 tcg_gen_shli_i64(tmp, va, 3);
1675 tcg_gen_add_i64(vc, tmp, vb);
1676 tcg_temp_free(tmp);
1677 break;
1678 case 0x3B:
1679 /* S8SUBQ */
1680 tmp = tcg_temp_new();
1681 tcg_gen_shli_i64(tmp, va, 3);
1682 tcg_gen_sub_i64(vc, tmp, vb);
1683 tcg_temp_free(tmp);
1684 break;
1685 case 0x3D:
1686 /* CMPULE */
1687 tcg_gen_setcond_i64(TCG_COND_LEU, vc, va, vb);
1688 break;
1689 case 0x40:
1690 /* ADDL/V */
1691 tmp = tcg_temp_new();
1692 tcg_gen_ext32s_i64(tmp, va);
1693 tcg_gen_ext32s_i64(vc, vb);
1694 tcg_gen_add_i64(tmp, tmp, vc);
1695 tcg_gen_ext32s_i64(vc, tmp);
1696 gen_helper_check_overflow(cpu_env, vc, tmp);
1697 tcg_temp_free(tmp);
1698 break;
1699 case 0x49:
1700 /* SUBL/V */
1701 tmp = tcg_temp_new();
1702 tcg_gen_ext32s_i64(tmp, va);
1703 tcg_gen_ext32s_i64(vc, vb);
1704 tcg_gen_sub_i64(tmp, tmp, vc);
1705 tcg_gen_ext32s_i64(vc, tmp);
1706 gen_helper_check_overflow(cpu_env, vc, tmp);
1707 tcg_temp_free(tmp);
1708 break;
1709 case 0x4D:
1710 /* CMPLT */
1711 tcg_gen_setcond_i64(TCG_COND_LT, vc, va, vb);
1712 break;
1713 case 0x60:
1714 /* ADDQ/V */
1715 tmp = tcg_temp_new();
1716 tmp2 = tcg_temp_new();
1717 tcg_gen_eqv_i64(tmp, va, vb);
1718 tcg_gen_mov_i64(tmp2, va);
1719 tcg_gen_add_i64(vc, va, vb);
1720 tcg_gen_xor_i64(tmp2, tmp2, vc);
1721 tcg_gen_and_i64(tmp, tmp, tmp2);
1722 tcg_gen_shri_i64(tmp, tmp, 63);
1723 tcg_gen_movi_i64(tmp2, 0);
1724 gen_helper_check_overflow(cpu_env, tmp, tmp2);
1725 tcg_temp_free(tmp);
1726 tcg_temp_free(tmp2);
1727 break;
1728 case 0x69:
1729 /* SUBQ/V */
1730 tmp = tcg_temp_new();
1731 tmp2 = tcg_temp_new();
1732 tcg_gen_xor_i64(tmp, va, vb);
1733 tcg_gen_mov_i64(tmp2, va);
1734 tcg_gen_sub_i64(vc, va, vb);
1735 tcg_gen_xor_i64(tmp2, tmp2, vc);
1736 tcg_gen_and_i64(tmp, tmp, tmp2);
1737 tcg_gen_shri_i64(tmp, tmp, 63);
1738 tcg_gen_movi_i64(tmp2, 0);
1739 gen_helper_check_overflow(cpu_env, tmp, tmp2);
1740 tcg_temp_free(tmp);
1741 tcg_temp_free(tmp2);
1742 break;
1743 case 0x6D:
1744 /* CMPLE */
1745 tcg_gen_setcond_i64(TCG_COND_LE, vc, va, vb);
1746 break;
1747 default:
1748 goto invalid_opc;
1750 break;
1752 case 0x11:
1753 if (fn7 == 0x20) {
1754 if (rc == 31) {
1755 /* Special case BIS as NOP. */
1756 break;
1758 if (ra == 31) {
1759 /* Special case BIS as MOV. */
1760 vc = dest_gpr(ctx, rc);
1761 if (islit) {
1762 tcg_gen_movi_i64(vc, lit);
1763 } else {
1764 tcg_gen_mov_i64(vc, load_gpr(ctx, rb));
1766 break;
1770 vc = dest_gpr(ctx, rc);
1771 vb = load_gpr_lit(ctx, rb, lit, islit);
1773 if (fn7 == 0x28 && ra == 31) {
1774 /* Special case ORNOT as NOT. */
1775 tcg_gen_not_i64(vc, vb);
1776 break;
1779 va = load_gpr(ctx, ra);
1780 switch (fn7) {
1781 case 0x00:
1782 /* AND */
1783 tcg_gen_and_i64(vc, va, vb);
1784 break;
1785 case 0x08:
1786 /* BIC */
1787 tcg_gen_andc_i64(vc, va, vb);
1788 break;
1789 case 0x14:
1790 /* CMOVLBS */
1791 tmp = tcg_temp_new();
1792 tcg_gen_andi_i64(tmp, va, 1);
1793 tcg_gen_movcond_i64(TCG_COND_NE, vc, tmp, load_zero(ctx),
1794 vb, load_gpr(ctx, rc));
1795 tcg_temp_free(tmp);
1796 break;
1797 case 0x16:
1798 /* CMOVLBC */
1799 tmp = tcg_temp_new();
1800 tcg_gen_andi_i64(tmp, va, 1);
1801 tcg_gen_movcond_i64(TCG_COND_EQ, vc, tmp, load_zero(ctx),
1802 vb, load_gpr(ctx, rc));
1803 tcg_temp_free(tmp);
1804 break;
1805 case 0x20:
1806 /* BIS */
1807 tcg_gen_or_i64(vc, va, vb);
1808 break;
1809 case 0x24:
1810 /* CMOVEQ */
1811 tcg_gen_movcond_i64(TCG_COND_EQ, vc, va, load_zero(ctx),
1812 vb, load_gpr(ctx, rc));
1813 break;
1814 case 0x26:
1815 /* CMOVNE */
1816 tcg_gen_movcond_i64(TCG_COND_NE, vc, va, load_zero(ctx),
1817 vb, load_gpr(ctx, rc));
1818 break;
1819 case 0x28:
1820 /* ORNOT */
1821 tcg_gen_orc_i64(vc, va, vb);
1822 break;
1823 case 0x40:
1824 /* XOR */
1825 tcg_gen_xor_i64(vc, va, vb);
1826 break;
1827 case 0x44:
1828 /* CMOVLT */
1829 tcg_gen_movcond_i64(TCG_COND_LT, vc, va, load_zero(ctx),
1830 vb, load_gpr(ctx, rc));
1831 break;
1832 case 0x46:
1833 /* CMOVGE */
1834 tcg_gen_movcond_i64(TCG_COND_GE, vc, va, load_zero(ctx),
1835 vb, load_gpr(ctx, rc));
1836 break;
1837 case 0x48:
1838 /* EQV */
1839 tcg_gen_eqv_i64(vc, va, vb);
1840 break;
1841 case 0x61:
1842 /* AMASK */
1843 REQUIRE_REG_31(ra);
1844 tcg_gen_andi_i64(vc, vb, ~ctx->amask);
1845 break;
1846 case 0x64:
1847 /* CMOVLE */
1848 tcg_gen_movcond_i64(TCG_COND_LE, vc, va, load_zero(ctx),
1849 vb, load_gpr(ctx, rc));
1850 break;
1851 case 0x66:
1852 /* CMOVGT */
1853 tcg_gen_movcond_i64(TCG_COND_GT, vc, va, load_zero(ctx),
1854 vb, load_gpr(ctx, rc));
1855 break;
1856 case 0x6C:
1857 /* IMPLVER */
1858 REQUIRE_REG_31(ra);
1859 tcg_gen_movi_i64(vc, ctx->implver);
1860 break;
1861 default:
1862 goto invalid_opc;
1864 break;
1866 case 0x12:
1867 vc = dest_gpr(ctx, rc);
1868 va = load_gpr(ctx, ra);
1869 switch (fn7) {
1870 case 0x02:
1871 /* MSKBL */
1872 gen_msk_l(ctx, vc, va, rb, islit, lit, 0x01);
1873 break;
1874 case 0x06:
1875 /* EXTBL */
1876 gen_ext_l(ctx, vc, va, rb, islit, lit, 0x01);
1877 break;
1878 case 0x0B:
1879 /* INSBL */
1880 gen_ins_l(ctx, vc, va, rb, islit, lit, 0x01);
1881 break;
1882 case 0x12:
1883 /* MSKWL */
1884 gen_msk_l(ctx, vc, va, rb, islit, lit, 0x03);
1885 break;
1886 case 0x16:
1887 /* EXTWL */
1888 gen_ext_l(ctx, vc, va, rb, islit, lit, 0x03);
1889 break;
1890 case 0x1B:
1891 /* INSWL */
1892 gen_ins_l(ctx, vc, va, rb, islit, lit, 0x03);
1893 break;
1894 case 0x22:
1895 /* MSKLL */
1896 gen_msk_l(ctx, vc, va, rb, islit, lit, 0x0f);
1897 break;
1898 case 0x26:
1899 /* EXTLL */
1900 gen_ext_l(ctx, vc, va, rb, islit, lit, 0x0f);
1901 break;
1902 case 0x2B:
1903 /* INSLL */
1904 gen_ins_l(ctx, vc, va, rb, islit, lit, 0x0f);
1905 break;
1906 case 0x30:
1907 /* ZAP */
1908 if (islit) {
1909 gen_zapnoti(vc, va, ~lit);
1910 } else {
1911 gen_helper_zap(vc, va, load_gpr(ctx, rb));
1913 break;
1914 case 0x31:
1915 /* ZAPNOT */
1916 if (islit) {
1917 gen_zapnoti(vc, va, lit);
1918 } else {
1919 gen_helper_zapnot(vc, va, load_gpr(ctx, rb));
1921 break;
1922 case 0x32:
1923 /* MSKQL */
1924 gen_msk_l(ctx, vc, va, rb, islit, lit, 0xff);
1925 break;
1926 case 0x34:
1927 /* SRL */
1928 if (islit) {
1929 tcg_gen_shri_i64(vc, va, lit & 0x3f);
1930 } else {
1931 tmp = tcg_temp_new();
1932 vb = load_gpr(ctx, rb);
1933 tcg_gen_andi_i64(tmp, vb, 0x3f);
1934 tcg_gen_shr_i64(vc, va, tmp);
1935 tcg_temp_free(tmp);
1937 break;
1938 case 0x36:
1939 /* EXTQL */
1940 gen_ext_l(ctx, vc, va, rb, islit, lit, 0xff);
1941 break;
1942 case 0x39:
1943 /* SLL */
1944 if (islit) {
1945 tcg_gen_shli_i64(vc, va, lit & 0x3f);
1946 } else {
1947 tmp = tcg_temp_new();
1948 vb = load_gpr(ctx, rb);
1949 tcg_gen_andi_i64(tmp, vb, 0x3f);
1950 tcg_gen_shl_i64(vc, va, tmp);
1951 tcg_temp_free(tmp);
1953 break;
1954 case 0x3B:
1955 /* INSQL */
1956 gen_ins_l(ctx, vc, va, rb, islit, lit, 0xff);
1957 break;
1958 case 0x3C:
1959 /* SRA */
1960 if (islit) {
1961 tcg_gen_sari_i64(vc, va, lit & 0x3f);
1962 } else {
1963 tmp = tcg_temp_new();
1964 vb = load_gpr(ctx, rb);
1965 tcg_gen_andi_i64(tmp, vb, 0x3f);
1966 tcg_gen_sar_i64(vc, va, tmp);
1967 tcg_temp_free(tmp);
1969 break;
1970 case 0x52:
1971 /* MSKWH */
1972 gen_msk_h(ctx, vc, va, rb, islit, lit, 0x03);
1973 break;
1974 case 0x57:
1975 /* INSWH */
1976 gen_ins_h(ctx, vc, va, rb, islit, lit, 0x03);
1977 break;
1978 case 0x5A:
1979 /* EXTWH */
1980 gen_ext_h(ctx, vc, va, rb, islit, lit, 0x03);
1981 break;
1982 case 0x62:
1983 /* MSKLH */
1984 gen_msk_h(ctx, vc, va, rb, islit, lit, 0x0f);
1985 break;
1986 case 0x67:
1987 /* INSLH */
1988 gen_ins_h(ctx, vc, va, rb, islit, lit, 0x0f);
1989 break;
1990 case 0x6A:
1991 /* EXTLH */
1992 gen_ext_h(ctx, vc, va, rb, islit, lit, 0x0f);
1993 break;
1994 case 0x72:
1995 /* MSKQH */
1996 gen_msk_h(ctx, vc, va, rb, islit, lit, 0xff);
1997 break;
1998 case 0x77:
1999 /* INSQH */
2000 gen_ins_h(ctx, vc, va, rb, islit, lit, 0xff);
2001 break;
2002 case 0x7A:
2003 /* EXTQH */
2004 gen_ext_h(ctx, vc, va, rb, islit, lit, 0xff);
2005 break;
2006 default:
2007 goto invalid_opc;
2009 break;
2011 case 0x13:
2012 vc = dest_gpr(ctx, rc);
2013 vb = load_gpr_lit(ctx, rb, lit, islit);
2014 va = load_gpr(ctx, ra);
2015 switch (fn7) {
2016 case 0x00:
2017 /* MULL */
2018 tcg_gen_mul_i64(vc, va, vb);
2019 tcg_gen_ext32s_i64(vc, vc);
2020 break;
2021 case 0x20:
2022 /* MULQ */
2023 tcg_gen_mul_i64(vc, va, vb);
2024 break;
2025 case 0x30:
2026 /* UMULH */
2027 tmp = tcg_temp_new();
2028 tcg_gen_mulu2_i64(tmp, vc, va, vb);
2029 tcg_temp_free(tmp);
2030 break;
2031 case 0x40:
2032 /* MULL/V */
2033 tmp = tcg_temp_new();
2034 tcg_gen_ext32s_i64(tmp, va);
2035 tcg_gen_ext32s_i64(vc, vb);
2036 tcg_gen_mul_i64(tmp, tmp, vc);
2037 tcg_gen_ext32s_i64(vc, tmp);
2038 gen_helper_check_overflow(cpu_env, vc, tmp);
2039 tcg_temp_free(tmp);
2040 break;
2041 case 0x60:
2042 /* MULQ/V */
2043 tmp = tcg_temp_new();
2044 tmp2 = tcg_temp_new();
2045 tcg_gen_muls2_i64(vc, tmp, va, vb);
2046 tcg_gen_sari_i64(tmp2, vc, 63);
2047 gen_helper_check_overflow(cpu_env, tmp, tmp2);
2048 tcg_temp_free(tmp);
2049 tcg_temp_free(tmp2);
2050 break;
2051 default:
2052 goto invalid_opc;
2054 break;
2056 case 0x14:
2057 REQUIRE_AMASK(FIX);
2058 vc = dest_fpr(ctx, rc);
2059 switch (fpfn) { /* fn11 & 0x3F */
2060 case 0x04:
2061 /* ITOFS */
2062 REQUIRE_REG_31(rb);
2063 t32 = tcg_temp_new_i32();
2064 va = load_gpr(ctx, ra);
2065 tcg_gen_extrl_i64_i32(t32, va);
2066 gen_helper_memory_to_s(vc, t32);
2067 tcg_temp_free_i32(t32);
2068 break;
2069 case 0x0A:
2070 /* SQRTF */
2071 REQUIRE_REG_31(ra);
2072 vb = load_fpr(ctx, rb);
2073 gen_helper_sqrtf(vc, cpu_env, vb);
2074 break;
2075 case 0x0B:
2076 /* SQRTS */
2077 REQUIRE_REG_31(ra);
2078 gen_sqrts(ctx, rb, rc, fn11);
2079 break;
2080 case 0x14:
2081 /* ITOFF */
2082 REQUIRE_REG_31(rb);
2083 t32 = tcg_temp_new_i32();
2084 va = load_gpr(ctx, ra);
2085 tcg_gen_extrl_i64_i32(t32, va);
2086 gen_helper_memory_to_f(vc, t32);
2087 tcg_temp_free_i32(t32);
2088 break;
2089 case 0x24:
2090 /* ITOFT */
2091 REQUIRE_REG_31(rb);
2092 va = load_gpr(ctx, ra);
2093 tcg_gen_mov_i64(vc, va);
2094 break;
2095 case 0x2A:
2096 /* SQRTG */
2097 REQUIRE_REG_31(ra);
2098 vb = load_fpr(ctx, rb);
2099 gen_helper_sqrtg(vc, cpu_env, vb);
2100 break;
2101 case 0x02B:
2102 /* SQRTT */
2103 REQUIRE_REG_31(ra);
2104 gen_sqrtt(ctx, rb, rc, fn11);
2105 break;
2106 default:
2107 goto invalid_opc;
2109 break;
2111 case 0x15:
2112 /* VAX floating point */
2113 /* XXX: rounding mode and trap are ignored (!) */
2114 vc = dest_fpr(ctx, rc);
2115 vb = load_fpr(ctx, rb);
2116 va = load_fpr(ctx, ra);
2117 switch (fpfn) { /* fn11 & 0x3F */
2118 case 0x00:
2119 /* ADDF */
2120 gen_helper_addf(vc, cpu_env, va, vb);
2121 break;
2122 case 0x01:
2123 /* SUBF */
2124 gen_helper_subf(vc, cpu_env, va, vb);
2125 break;
2126 case 0x02:
2127 /* MULF */
2128 gen_helper_mulf(vc, cpu_env, va, vb);
2129 break;
2130 case 0x03:
2131 /* DIVF */
2132 gen_helper_divf(vc, cpu_env, va, vb);
2133 break;
2134 case 0x1E:
2135 /* CVTDG -- TODO */
2136 REQUIRE_REG_31(ra);
2137 goto invalid_opc;
2138 case 0x20:
2139 /* ADDG */
2140 gen_helper_addg(vc, cpu_env, va, vb);
2141 break;
2142 case 0x21:
2143 /* SUBG */
2144 gen_helper_subg(vc, cpu_env, va, vb);
2145 break;
2146 case 0x22:
2147 /* MULG */
2148 gen_helper_mulg(vc, cpu_env, va, vb);
2149 break;
2150 case 0x23:
2151 /* DIVG */
2152 gen_helper_divg(vc, cpu_env, va, vb);
2153 break;
2154 case 0x25:
2155 /* CMPGEQ */
2156 gen_helper_cmpgeq(vc, cpu_env, va, vb);
2157 break;
2158 case 0x26:
2159 /* CMPGLT */
2160 gen_helper_cmpglt(vc, cpu_env, va, vb);
2161 break;
2162 case 0x27:
2163 /* CMPGLE */
2164 gen_helper_cmpgle(vc, cpu_env, va, vb);
2165 break;
2166 case 0x2C:
2167 /* CVTGF */
2168 REQUIRE_REG_31(ra);
2169 gen_helper_cvtgf(vc, cpu_env, vb);
2170 break;
2171 case 0x2D:
2172 /* CVTGD -- TODO */
2173 REQUIRE_REG_31(ra);
2174 goto invalid_opc;
2175 case 0x2F:
2176 /* CVTGQ */
2177 REQUIRE_REG_31(ra);
2178 gen_helper_cvtgq(vc, cpu_env, vb);
2179 break;
2180 case 0x3C:
2181 /* CVTQF */
2182 REQUIRE_REG_31(ra);
2183 gen_helper_cvtqf(vc, cpu_env, vb);
2184 break;
2185 case 0x3E:
2186 /* CVTQG */
2187 REQUIRE_REG_31(ra);
2188 gen_helper_cvtqg(vc, cpu_env, vb);
2189 break;
2190 default:
2191 goto invalid_opc;
2193 break;
2195 case 0x16:
2196 /* IEEE floating-point */
2197 switch (fpfn) { /* fn11 & 0x3F */
2198 case 0x00:
2199 /* ADDS */
2200 gen_adds(ctx, ra, rb, rc, fn11);
2201 break;
2202 case 0x01:
2203 /* SUBS */
2204 gen_subs(ctx, ra, rb, rc, fn11);
2205 break;
2206 case 0x02:
2207 /* MULS */
2208 gen_muls(ctx, ra, rb, rc, fn11);
2209 break;
2210 case 0x03:
2211 /* DIVS */
2212 gen_divs(ctx, ra, rb, rc, fn11);
2213 break;
2214 case 0x20:
2215 /* ADDT */
2216 gen_addt(ctx, ra, rb, rc, fn11);
2217 break;
2218 case 0x21:
2219 /* SUBT */
2220 gen_subt(ctx, ra, rb, rc, fn11);
2221 break;
2222 case 0x22:
2223 /* MULT */
2224 gen_mult(ctx, ra, rb, rc, fn11);
2225 break;
2226 case 0x23:
2227 /* DIVT */
2228 gen_divt(ctx, ra, rb, rc, fn11);
2229 break;
2230 case 0x24:
2231 /* CMPTUN */
2232 gen_cmptun(ctx, ra, rb, rc, fn11);
2233 break;
2234 case 0x25:
2235 /* CMPTEQ */
2236 gen_cmpteq(ctx, ra, rb, rc, fn11);
2237 break;
2238 case 0x26:
2239 /* CMPTLT */
2240 gen_cmptlt(ctx, ra, rb, rc, fn11);
2241 break;
2242 case 0x27:
2243 /* CMPTLE */
2244 gen_cmptle(ctx, ra, rb, rc, fn11);
2245 break;
2246 case 0x2C:
2247 REQUIRE_REG_31(ra);
2248 if (fn11 == 0x2AC || fn11 == 0x6AC) {
2249 /* CVTST */
2250 gen_cvtst(ctx, rb, rc, fn11);
2251 } else {
2252 /* CVTTS */
2253 gen_cvtts(ctx, rb, rc, fn11);
2255 break;
2256 case 0x2F:
2257 /* CVTTQ */
2258 REQUIRE_REG_31(ra);
2259 gen_cvttq(ctx, rb, rc, fn11);
2260 break;
2261 case 0x3C:
2262 /* CVTQS */
2263 REQUIRE_REG_31(ra);
2264 gen_cvtqs(ctx, rb, rc, fn11);
2265 break;
2266 case 0x3E:
2267 /* CVTQT */
2268 REQUIRE_REG_31(ra);
2269 gen_cvtqt(ctx, rb, rc, fn11);
2270 break;
2271 default:
2272 goto invalid_opc;
2274 break;
2276 case 0x17:
2277 switch (fn11) {
2278 case 0x010:
2279 /* CVTLQ */
2280 REQUIRE_REG_31(ra);
2281 vc = dest_fpr(ctx, rc);
2282 vb = load_fpr(ctx, rb);
2283 gen_cvtlq(vc, vb);
2284 break;
2285 case 0x020:
2286 /* CPYS */
2287 if (rc == 31) {
2288 /* Special case CPYS as FNOP. */
2289 } else {
2290 vc = dest_fpr(ctx, rc);
2291 va = load_fpr(ctx, ra);
2292 if (ra == rb) {
2293 /* Special case CPYS as FMOV. */
2294 tcg_gen_mov_i64(vc, va);
2295 } else {
2296 vb = load_fpr(ctx, rb);
2297 gen_cpy_mask(vc, va, vb, 0, 0x8000000000000000ULL);
2300 break;
2301 case 0x021:
2302 /* CPYSN */
2303 vc = dest_fpr(ctx, rc);
2304 vb = load_fpr(ctx, rb);
2305 va = load_fpr(ctx, ra);
2306 gen_cpy_mask(vc, va, vb, 1, 0x8000000000000000ULL);
2307 break;
2308 case 0x022:
2309 /* CPYSE */
2310 vc = dest_fpr(ctx, rc);
2311 vb = load_fpr(ctx, rb);
2312 va = load_fpr(ctx, ra);
2313 gen_cpy_mask(vc, va, vb, 0, 0xFFF0000000000000ULL);
2314 break;
2315 case 0x024:
2316 /* MT_FPCR */
2317 va = load_fpr(ctx, ra);
2318 gen_helper_store_fpcr(cpu_env, va);
2319 if (ctx->tb_rm == QUAL_RM_D) {
2320 /* Re-do the copy of the rounding mode to fp_status
2321 the next time we use dynamic rounding. */
2322 ctx->tb_rm = -1;
2324 break;
2325 case 0x025:
2326 /* MF_FPCR */
2327 va = dest_fpr(ctx, ra);
2328 gen_helper_load_fpcr(va, cpu_env);
2329 break;
2330 case 0x02A:
2331 /* FCMOVEQ */
2332 gen_fcmov(ctx, TCG_COND_EQ, ra, rb, rc);
2333 break;
2334 case 0x02B:
2335 /* FCMOVNE */
2336 gen_fcmov(ctx, TCG_COND_NE, ra, rb, rc);
2337 break;
2338 case 0x02C:
2339 /* FCMOVLT */
2340 gen_fcmov(ctx, TCG_COND_LT, ra, rb, rc);
2341 break;
2342 case 0x02D:
2343 /* FCMOVGE */
2344 gen_fcmov(ctx, TCG_COND_GE, ra, rb, rc);
2345 break;
2346 case 0x02E:
2347 /* FCMOVLE */
2348 gen_fcmov(ctx, TCG_COND_LE, ra, rb, rc);
2349 break;
2350 case 0x02F:
2351 /* FCMOVGT */
2352 gen_fcmov(ctx, TCG_COND_GT, ra, rb, rc);
2353 break;
2354 case 0x030: /* CVTQL */
2355 case 0x130: /* CVTQL/V */
2356 case 0x530: /* CVTQL/SV */
2357 REQUIRE_REG_31(ra);
2358 vc = dest_fpr(ctx, rc);
2359 vb = load_fpr(ctx, rb);
2360 gen_helper_cvtql(vc, cpu_env, vb);
2361 gen_fp_exc_raise(rc, fn11);
2362 break;
2363 default:
2364 goto invalid_opc;
2366 break;
2368 case 0x18:
2369 switch ((uint16_t)disp16) {
2370 case 0x0000:
2371 /* TRAPB */
2372 /* No-op. */
2373 break;
2374 case 0x0400:
2375 /* EXCB */
2376 /* No-op. */
2377 break;
2378 case 0x4000:
2379 /* MB */
2380 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
2381 break;
2382 case 0x4400:
2383 /* WMB */
2384 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
2385 break;
2386 case 0x8000:
2387 /* FETCH */
2388 /* No-op */
2389 break;
2390 case 0xA000:
2391 /* FETCH_M */
2392 /* No-op */
2393 break;
2394 case 0xC000:
2395 /* RPCC */
2396 va = dest_gpr(ctx, ra);
2397 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2398 gen_io_start();
2399 gen_helper_load_pcc(va, cpu_env);
2400 ret = DISAS_PC_STALE;
2401 } else {
2402 gen_helper_load_pcc(va, cpu_env);
2404 break;
2405 case 0xE000:
2406 /* RC */
2407 gen_rx(ctx, ra, 0);
2408 break;
2409 case 0xE800:
2410 /* ECB */
2411 break;
2412 case 0xF000:
2413 /* RS */
2414 gen_rx(ctx, ra, 1);
2415 break;
2416 case 0xF800:
2417 /* WH64 */
2418 /* No-op */
2419 break;
2420 case 0xFC00:
2421 /* WH64EN */
2422 /* No-op */
2423 break;
2424 default:
2425 goto invalid_opc;
2427 break;
2429 case 0x19:
2430 /* HW_MFPR (PALcode) */
2431 #ifndef CONFIG_USER_ONLY
2432 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
2433 va = dest_gpr(ctx, ra);
2434 ret = gen_mfpr(ctx, va, insn & 0xffff);
2435 break;
2436 #else
2437 goto invalid_opc;
2438 #endif
2440 case 0x1A:
2441 /* JMP, JSR, RET, JSR_COROUTINE. These only differ by the branch
2442 prediction stack action, which of course we don't implement. */
2443 vb = load_gpr(ctx, rb);
2444 tcg_gen_andi_i64(cpu_pc, vb, ~3);
2445 if (ra != 31) {
2446 tcg_gen_movi_i64(ctx->ir[ra], ctx->base.pc_next);
2448 ret = DISAS_PC_UPDATED;
2449 break;
2451 case 0x1B:
2452 /* HW_LD (PALcode) */
2453 #ifndef CONFIG_USER_ONLY
2454 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
2456 TCGv addr = tcg_temp_new();
2457 vb = load_gpr(ctx, rb);
2458 va = dest_gpr(ctx, ra);
2460 tcg_gen_addi_i64(addr, vb, disp12);
2461 switch ((insn >> 12) & 0xF) {
2462 case 0x0:
2463 /* Longword physical access (hw_ldl/p) */
2464 tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL);
2465 break;
2466 case 0x1:
2467 /* Quadword physical access (hw_ldq/p) */
2468 tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEQ);
2469 break;
2470 case 0x2:
2471 /* Longword physical access with lock (hw_ldl_l/p) */
2472 gen_qemu_ldl_l(va, addr, MMU_PHYS_IDX);
2473 break;
2474 case 0x3:
2475 /* Quadword physical access with lock (hw_ldq_l/p) */
2476 gen_qemu_ldq_l(va, addr, MMU_PHYS_IDX);
2477 break;
2478 case 0x4:
2479 /* Longword virtual PTE fetch (hw_ldl/v) */
2480 goto invalid_opc;
2481 case 0x5:
2482 /* Quadword virtual PTE fetch (hw_ldq/v) */
2483 goto invalid_opc;
2484 break;
2485 case 0x6:
2486 /* Invalid */
2487 goto invalid_opc;
2488 case 0x7:
2489 /* Invaliid */
2490 goto invalid_opc;
2491 case 0x8:
2492 /* Longword virtual access (hw_ldl) */
2493 goto invalid_opc;
2494 case 0x9:
2495 /* Quadword virtual access (hw_ldq) */
2496 goto invalid_opc;
2497 case 0xA:
2498 /* Longword virtual access with protection check (hw_ldl/w) */
2499 tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LESL);
2500 break;
2501 case 0xB:
2502 /* Quadword virtual access with protection check (hw_ldq/w) */
2503 tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LEQ);
2504 break;
2505 case 0xC:
2506 /* Longword virtual access with alt access mode (hw_ldl/a)*/
2507 goto invalid_opc;
2508 case 0xD:
2509 /* Quadword virtual access with alt access mode (hw_ldq/a) */
2510 goto invalid_opc;
2511 case 0xE:
2512 /* Longword virtual access with alternate access mode and
2513 protection checks (hw_ldl/wa) */
2514 tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LESL);
2515 break;
2516 case 0xF:
2517 /* Quadword virtual access with alternate access mode and
2518 protection checks (hw_ldq/wa) */
2519 tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LEQ);
2520 break;
2522 tcg_temp_free(addr);
2523 break;
2525 #else
2526 goto invalid_opc;
2527 #endif
2529 case 0x1C:
2530 vc = dest_gpr(ctx, rc);
2531 if (fn7 == 0x70) {
2532 /* FTOIT */
2533 REQUIRE_AMASK(FIX);
2534 REQUIRE_REG_31(rb);
2535 va = load_fpr(ctx, ra);
2536 tcg_gen_mov_i64(vc, va);
2537 break;
2538 } else if (fn7 == 0x78) {
2539 /* FTOIS */
2540 REQUIRE_AMASK(FIX);
2541 REQUIRE_REG_31(rb);
2542 t32 = tcg_temp_new_i32();
2543 va = load_fpr(ctx, ra);
2544 gen_helper_s_to_memory(t32, va);
2545 tcg_gen_ext_i32_i64(vc, t32);
2546 tcg_temp_free_i32(t32);
2547 break;
2550 vb = load_gpr_lit(ctx, rb, lit, islit);
2551 switch (fn7) {
2552 case 0x00:
2553 /* SEXTB */
2554 REQUIRE_AMASK(BWX);
2555 REQUIRE_REG_31(ra);
2556 tcg_gen_ext8s_i64(vc, vb);
2557 break;
2558 case 0x01:
2559 /* SEXTW */
2560 REQUIRE_AMASK(BWX);
2561 REQUIRE_REG_31(ra);
2562 tcg_gen_ext16s_i64(vc, vb);
2563 break;
2564 case 0x30:
2565 /* CTPOP */
2566 REQUIRE_AMASK(CIX);
2567 REQUIRE_REG_31(ra);
2568 REQUIRE_NO_LIT;
2569 tcg_gen_ctpop_i64(vc, vb);
2570 break;
2571 case 0x31:
2572 /* PERR */
2573 REQUIRE_AMASK(MVI);
2574 REQUIRE_NO_LIT;
2575 va = load_gpr(ctx, ra);
2576 gen_helper_perr(vc, va, vb);
2577 break;
2578 case 0x32:
2579 /* CTLZ */
2580 REQUIRE_AMASK(CIX);
2581 REQUIRE_REG_31(ra);
2582 REQUIRE_NO_LIT;
2583 tcg_gen_clzi_i64(vc, vb, 64);
2584 break;
2585 case 0x33:
2586 /* CTTZ */
2587 REQUIRE_AMASK(CIX);
2588 REQUIRE_REG_31(ra);
2589 REQUIRE_NO_LIT;
2590 tcg_gen_ctzi_i64(vc, vb, 64);
2591 break;
2592 case 0x34:
2593 /* UNPKBW */
2594 REQUIRE_AMASK(MVI);
2595 REQUIRE_REG_31(ra);
2596 REQUIRE_NO_LIT;
2597 gen_helper_unpkbw(vc, vb);
2598 break;
2599 case 0x35:
2600 /* UNPKBL */
2601 REQUIRE_AMASK(MVI);
2602 REQUIRE_REG_31(ra);
2603 REQUIRE_NO_LIT;
2604 gen_helper_unpkbl(vc, vb);
2605 break;
2606 case 0x36:
2607 /* PKWB */
2608 REQUIRE_AMASK(MVI);
2609 REQUIRE_REG_31(ra);
2610 REQUIRE_NO_LIT;
2611 gen_helper_pkwb(vc, vb);
2612 break;
2613 case 0x37:
2614 /* PKLB */
2615 REQUIRE_AMASK(MVI);
2616 REQUIRE_REG_31(ra);
2617 REQUIRE_NO_LIT;
2618 gen_helper_pklb(vc, vb);
2619 break;
2620 case 0x38:
2621 /* MINSB8 */
2622 REQUIRE_AMASK(MVI);
2623 va = load_gpr(ctx, ra);
2624 gen_helper_minsb8(vc, va, vb);
2625 break;
2626 case 0x39:
2627 /* MINSW4 */
2628 REQUIRE_AMASK(MVI);
2629 va = load_gpr(ctx, ra);
2630 gen_helper_minsw4(vc, va, vb);
2631 break;
2632 case 0x3A:
2633 /* MINUB8 */
2634 REQUIRE_AMASK(MVI);
2635 va = load_gpr(ctx, ra);
2636 gen_helper_minub8(vc, va, vb);
2637 break;
2638 case 0x3B:
2639 /* MINUW4 */
2640 REQUIRE_AMASK(MVI);
2641 va = load_gpr(ctx, ra);
2642 gen_helper_minuw4(vc, va, vb);
2643 break;
2644 case 0x3C:
2645 /* MAXUB8 */
2646 REQUIRE_AMASK(MVI);
2647 va = load_gpr(ctx, ra);
2648 gen_helper_maxub8(vc, va, vb);
2649 break;
2650 case 0x3D:
2651 /* MAXUW4 */
2652 REQUIRE_AMASK(MVI);
2653 va = load_gpr(ctx, ra);
2654 gen_helper_maxuw4(vc, va, vb);
2655 break;
2656 case 0x3E:
2657 /* MAXSB8 */
2658 REQUIRE_AMASK(MVI);
2659 va = load_gpr(ctx, ra);
2660 gen_helper_maxsb8(vc, va, vb);
2661 break;
2662 case 0x3F:
2663 /* MAXSW4 */
2664 REQUIRE_AMASK(MVI);
2665 va = load_gpr(ctx, ra);
2666 gen_helper_maxsw4(vc, va, vb);
2667 break;
2668 default:
2669 goto invalid_opc;
2671 break;
2673 case 0x1D:
2674 /* HW_MTPR (PALcode) */
2675 #ifndef CONFIG_USER_ONLY
2676 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
2677 vb = load_gpr(ctx, rb);
2678 ret = gen_mtpr(ctx, vb, insn & 0xffff);
2679 break;
2680 #else
2681 goto invalid_opc;
2682 #endif
2684 case 0x1E:
2685 /* HW_RET (PALcode) */
2686 #ifndef CONFIG_USER_ONLY
2687 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
2688 if (rb == 31) {
2689 /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
2690 address from EXC_ADDR. This turns out to be useful for our
2691 emulation PALcode, so continue to accept it. */
2692 ctx->lit = vb = tcg_temp_new();
2693 tcg_gen_ld_i64(vb, cpu_env, offsetof(CPUAlphaState, exc_addr));
2694 } else {
2695 vb = load_gpr(ctx, rb);
2697 tcg_gen_movi_i64(cpu_lock_addr, -1);
2698 tmp = tcg_temp_new();
2699 tcg_gen_movi_i64(tmp, 0);
2700 st_flag_byte(tmp, ENV_FLAG_RX_SHIFT);
2701 tcg_gen_andi_i64(tmp, vb, 1);
2702 st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT);
2703 tcg_temp_free(tmp);
2704 tcg_gen_andi_i64(cpu_pc, vb, ~3);
2705 /* Allow interrupts to be recognized right away. */
2706 ret = DISAS_PC_UPDATED_NOCHAIN;
2707 break;
2708 #else
2709 goto invalid_opc;
2710 #endif
2712 case 0x1F:
2713 /* HW_ST (PALcode) */
2714 #ifndef CONFIG_USER_ONLY
2715 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
2717 switch ((insn >> 12) & 0xF) {
2718 case 0x0:
2719 /* Longword physical access */
2720 va = load_gpr(ctx, ra);
2721 vb = load_gpr(ctx, rb);
2722 tmp = tcg_temp_new();
2723 tcg_gen_addi_i64(tmp, vb, disp12);
2724 tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LESL);
2725 tcg_temp_free(tmp);
2726 break;
2727 case 0x1:
2728 /* Quadword physical access */
2729 va = load_gpr(ctx, ra);
2730 vb = load_gpr(ctx, rb);
2731 tmp = tcg_temp_new();
2732 tcg_gen_addi_i64(tmp, vb, disp12);
2733 tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LEQ);
2734 tcg_temp_free(tmp);
2735 break;
2736 case 0x2:
2737 /* Longword physical access with lock */
2738 ret = gen_store_conditional(ctx, ra, rb, disp12,
2739 MMU_PHYS_IDX, MO_LESL);
2740 break;
2741 case 0x3:
2742 /* Quadword physical access with lock */
2743 ret = gen_store_conditional(ctx, ra, rb, disp12,
2744 MMU_PHYS_IDX, MO_LEQ);
2745 break;
2746 case 0x4:
2747 /* Longword virtual access */
2748 goto invalid_opc;
2749 case 0x5:
2750 /* Quadword virtual access */
2751 goto invalid_opc;
2752 case 0x6:
2753 /* Invalid */
2754 goto invalid_opc;
2755 case 0x7:
2756 /* Invalid */
2757 goto invalid_opc;
2758 case 0x8:
2759 /* Invalid */
2760 goto invalid_opc;
2761 case 0x9:
2762 /* Invalid */
2763 goto invalid_opc;
2764 case 0xA:
2765 /* Invalid */
2766 goto invalid_opc;
2767 case 0xB:
2768 /* Invalid */
2769 goto invalid_opc;
2770 case 0xC:
2771 /* Longword virtual access with alternate access mode */
2772 goto invalid_opc;
2773 case 0xD:
2774 /* Quadword virtual access with alternate access mode */
2775 goto invalid_opc;
2776 case 0xE:
2777 /* Invalid */
2778 goto invalid_opc;
2779 case 0xF:
2780 /* Invalid */
2781 goto invalid_opc;
2783 break;
2785 #else
2786 goto invalid_opc;
2787 #endif
2788 case 0x20:
2789 /* LDF */
2790 gen_load_mem(ctx, &gen_qemu_ldf, ra, rb, disp16, 1, 0);
2791 break;
2792 case 0x21:
2793 /* LDG */
2794 gen_load_mem(ctx, &gen_qemu_ldg, ra, rb, disp16, 1, 0);
2795 break;
2796 case 0x22:
2797 /* LDS */
2798 gen_load_mem(ctx, &gen_qemu_lds, ra, rb, disp16, 1, 0);
2799 break;
2800 case 0x23:
2801 /* LDT */
2802 gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 1, 0);
2803 break;
2804 case 0x24:
2805 /* STF */
2806 gen_store_mem(ctx, &gen_qemu_stf, ra, rb, disp16, 1, 0);
2807 break;
2808 case 0x25:
2809 /* STG */
2810 gen_store_mem(ctx, &gen_qemu_stg, ra, rb, disp16, 1, 0);
2811 break;
2812 case 0x26:
2813 /* STS */
2814 gen_store_mem(ctx, &gen_qemu_sts, ra, rb, disp16, 1, 0);
2815 break;
2816 case 0x27:
2817 /* STT */
2818 gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0);
2819 break;
2820 case 0x28:
2821 /* LDL */
2822 gen_load_mem(ctx, &tcg_gen_qemu_ld32s, ra, rb, disp16, 0, 0);
2823 break;
2824 case 0x29:
2825 /* LDQ */
2826 gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 0);
2827 break;
2828 case 0x2A:
2829 /* LDL_L */
2830 gen_load_mem(ctx, &gen_qemu_ldl_l, ra, rb, disp16, 0, 0);
2831 break;
2832 case 0x2B:
2833 /* LDQ_L */
2834 gen_load_mem(ctx, &gen_qemu_ldq_l, ra, rb, disp16, 0, 0);
2835 break;
2836 case 0x2C:
2837 /* STL */
2838 gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp16, 0, 0);
2839 break;
2840 case 0x2D:
2841 /* STQ */
2842 gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 0);
2843 break;
2844 case 0x2E:
2845 /* STL_C */
2846 ret = gen_store_conditional(ctx, ra, rb, disp16,
2847 ctx->mem_idx, MO_LESL);
2848 break;
2849 case 0x2F:
2850 /* STQ_C */
2851 ret = gen_store_conditional(ctx, ra, rb, disp16,
2852 ctx->mem_idx, MO_LEQ);
2853 break;
2854 case 0x30:
2855 /* BR */
2856 ret = gen_bdirect(ctx, ra, disp21);
2857 break;
2858 case 0x31: /* FBEQ */
2859 ret = gen_fbcond(ctx, TCG_COND_EQ, ra, disp21);
2860 break;
2861 case 0x32: /* FBLT */
2862 ret = gen_fbcond(ctx, TCG_COND_LT, ra, disp21);
2863 break;
2864 case 0x33: /* FBLE */
2865 ret = gen_fbcond(ctx, TCG_COND_LE, ra, disp21);
2866 break;
2867 case 0x34:
2868 /* BSR */
2869 ret = gen_bdirect(ctx, ra, disp21);
2870 break;
2871 case 0x35: /* FBNE */
2872 ret = gen_fbcond(ctx, TCG_COND_NE, ra, disp21);
2873 break;
2874 case 0x36: /* FBGE */
2875 ret = gen_fbcond(ctx, TCG_COND_GE, ra, disp21);
2876 break;
2877 case 0x37: /* FBGT */
2878 ret = gen_fbcond(ctx, TCG_COND_GT, ra, disp21);
2879 break;
2880 case 0x38:
2881 /* BLBC */
2882 ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1);
2883 break;
2884 case 0x39:
2885 /* BEQ */
2886 ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 0);
2887 break;
2888 case 0x3A:
2889 /* BLT */
2890 ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21, 0);
2891 break;
2892 case 0x3B:
2893 /* BLE */
2894 ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21, 0);
2895 break;
2896 case 0x3C:
2897 /* BLBS */
2898 ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1);
2899 break;
2900 case 0x3D:
2901 /* BNE */
2902 ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 0);
2903 break;
2904 case 0x3E:
2905 /* BGE */
2906 ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21, 0);
2907 break;
2908 case 0x3F:
2909 /* BGT */
2910 ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
2911 break;
2912 invalid_opc:
2913 ret = gen_invalid(ctx);
2914 break;
2917 return ret;
2920 static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
2922 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2923 CPUAlphaState *env = cpu->env_ptr;
2924 int64_t bound, mask;
2926 ctx->tbflags = ctx->base.tb->flags;
2927 ctx->mem_idx = cpu_mmu_index(env, false);
2928 ctx->implver = env->implver;
2929 ctx->amask = env->amask;
2931 #ifdef CONFIG_USER_ONLY
2932 ctx->ir = cpu_std_ir;
2933 #else
2934 ctx->palbr = env->palbr;
2935 ctx->ir = (ctx->tbflags & ENV_FLAG_PAL_MODE ? cpu_pal_ir : cpu_std_ir);
2936 #endif
2938 /* ??? Every TB begins with unset rounding mode, to be initialized on
2939 the first fp insn of the TB. Alternately we could define a proper
2940 default for every TB (e.g. QUAL_RM_N or QUAL_RM_D) and make sure
2941 to reset the FP_STATUS to that default at the end of any TB that
2942 changes the default. We could even (gasp) dynamiclly figure out
2943 what default would be most efficient given the running program. */
2944 ctx->tb_rm = -1;
2945 /* Similarly for flush-to-zero. */
2946 ctx->tb_ftz = -1;
2948 ctx->zero = NULL;
2949 ctx->sink = NULL;
2950 ctx->lit = NULL;
2952 /* Bound the number of insns to execute to those left on the page. */
2953 if (in_superpage(ctx, ctx->base.pc_first)) {
2954 mask = -1ULL << 41;
2955 } else {
2956 mask = TARGET_PAGE_MASK;
2958 bound = -(ctx->base.pc_first | mask) / 4;
2959 ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
2962 static void alpha_tr_tb_start(DisasContextBase *db, CPUState *cpu)
2966 static void alpha_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
2968 tcg_gen_insn_start(dcbase->pc_next);
2971 static bool alpha_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
2972 const CPUBreakpoint *bp)
2974 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2976 ctx->base.is_jmp = gen_excp(ctx, EXCP_DEBUG, 0);
2978 /* The address covered by the breakpoint must be included in
2979 [tb->pc, tb->pc + tb->size) in order to for it to be
2980 properly cleared -- thus we increment the PC here so that
2981 the logic setting tb->size below does the right thing. */
2982 ctx->base.pc_next += 4;
2983 return true;
2986 static void alpha_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
2988 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2989 CPUAlphaState *env = cpu->env_ptr;
2990 uint32_t insn = translator_ldl(env, ctx->base.pc_next);
2992 ctx->base.pc_next += 4;
2993 ctx->base.is_jmp = translate_one(ctx, insn);
2995 free_context_temps(ctx);
2996 translator_loop_temp_check(&ctx->base);
2999 static void alpha_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
3001 DisasContext *ctx = container_of(dcbase, DisasContext, base);
3003 switch (ctx->base.is_jmp) {
3004 case DISAS_NORETURN:
3005 break;
3006 case DISAS_TOO_MANY:
3007 if (use_goto_tb(ctx, ctx->base.pc_next)) {
3008 tcg_gen_goto_tb(0);
3009 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
3010 tcg_gen_exit_tb(ctx->base.tb, 0);
3012 /* FALLTHRU */
3013 case DISAS_PC_STALE:
3014 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
3015 /* FALLTHRU */
3016 case DISAS_PC_UPDATED:
3017 if (!use_exit_tb(ctx)) {
3018 tcg_gen_lookup_and_goto_ptr();
3019 break;
3021 /* FALLTHRU */
3022 case DISAS_PC_UPDATED_NOCHAIN:
3023 if (ctx->base.singlestep_enabled) {
3024 gen_excp_1(EXCP_DEBUG, 0);
3025 } else {
3026 tcg_gen_exit_tb(NULL, 0);
3028 break;
3029 default:
3030 g_assert_not_reached();
3034 static void alpha_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
3036 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
3037 log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size);
3040 static const TranslatorOps alpha_tr_ops = {
3041 .init_disas_context = alpha_tr_init_disas_context,
3042 .tb_start = alpha_tr_tb_start,
3043 .insn_start = alpha_tr_insn_start,
3044 .breakpoint_check = alpha_tr_breakpoint_check,
3045 .translate_insn = alpha_tr_translate_insn,
3046 .tb_stop = alpha_tr_tb_stop,
3047 .disas_log = alpha_tr_disas_log,
3050 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
3052 DisasContext dc;
3053 translator_loop(&alpha_tr_ops, &dc.base, cpu, tb, max_insns);
3056 void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb,
3057 target_ulong *data)
3059 env->pc = data[0];