target/alpha: Hoist branch shift to initial decode
[qemu/armbru.git] / target / alpha / translate.c
blob52c2e6248b8d42e022e9f31d035402ab75eabf91
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.1 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/helper-proto.h"
28 #include "exec/helper-gen.h"
29 #include "exec/translator.h"
30 #include "exec/log.h"
32 #define HELPER_H "helper.h"
33 #include "exec/helper-info.c.inc"
34 #undef HELPER_H
36 #undef ALPHA_DEBUG_DISAS
37 #define CONFIG_SOFTFLOAT_INLINE
39 #ifdef ALPHA_DEBUG_DISAS
40 # define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
41 #else
42 # define LOG_DISAS(...) do { } while (0)
43 #endif
45 typedef struct DisasContext DisasContext;
46 struct DisasContext {
47 DisasContextBase base;
49 #ifdef CONFIG_USER_ONLY
50 MemOp unalign;
51 #else
52 uint64_t palbr;
53 #endif
54 uint32_t tbflags;
55 int mem_idx;
57 /* implver and amask values for this CPU. */
58 int implver;
59 int amask;
61 /* Current rounding mode for this TB. */
62 int tb_rm;
63 /* Current flush-to-zero setting for this TB. */
64 int tb_ftz;
66 /* The set of registers active in the current context. */
67 TCGv *ir;
69 /* Temporaries for $31 and $f31 as source and destination. */
70 TCGv zero;
71 TCGv sink;
74 #ifdef CONFIG_USER_ONLY
75 #define UNALIGN(C) (C)->unalign
76 #else
77 #define UNALIGN(C) MO_ALIGN
78 #endif
80 /* Target-specific return values from translate_one, indicating the
81 state of the TB. Note that DISAS_NEXT indicates that we are not
82 exiting the TB. */
83 #define DISAS_PC_UPDATED_NOCHAIN DISAS_TARGET_0
84 #define DISAS_PC_UPDATED DISAS_TARGET_1
85 #define DISAS_PC_STALE DISAS_TARGET_2
87 /* global register indexes */
88 static TCGv cpu_std_ir[31];
89 static TCGv cpu_fir[31];
90 static TCGv cpu_pc;
91 static TCGv cpu_lock_addr;
92 static TCGv cpu_lock_value;
94 #ifndef CONFIG_USER_ONLY
95 static TCGv cpu_pal_ir[31];
96 #endif
98 void alpha_translate_init(void)
100 #define DEF_VAR(V) { &cpu_##V, #V, offsetof(CPUAlphaState, V) }
102 typedef struct { TCGv *var; const char *name; int ofs; } GlobalVar;
103 static const GlobalVar vars[] = {
104 DEF_VAR(pc),
105 DEF_VAR(lock_addr),
106 DEF_VAR(lock_value),
109 #undef DEF_VAR
111 /* Use the symbolic register names that match the disassembler. */
112 static const char greg_names[31][4] = {
113 "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
114 "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp",
115 "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
116 "t10", "t11", "ra", "t12", "at", "gp", "sp"
118 static const char freg_names[31][4] = {
119 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
120 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
121 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
122 "f24", "f25", "f26", "f27", "f28", "f29", "f30"
124 #ifndef CONFIG_USER_ONLY
125 static const char shadow_names[8][8] = {
126 "pal_t7", "pal_s0", "pal_s1", "pal_s2",
127 "pal_s3", "pal_s4", "pal_s5", "pal_t11"
129 #endif
131 int i;
133 for (i = 0; i < 31; i++) {
134 cpu_std_ir[i] = tcg_global_mem_new_i64(tcg_env,
135 offsetof(CPUAlphaState, ir[i]),
136 greg_names[i]);
139 for (i = 0; i < 31; i++) {
140 cpu_fir[i] = tcg_global_mem_new_i64(tcg_env,
141 offsetof(CPUAlphaState, fir[i]),
142 freg_names[i]);
145 #ifndef CONFIG_USER_ONLY
146 memcpy(cpu_pal_ir, cpu_std_ir, sizeof(cpu_pal_ir));
147 for (i = 0; i < 8; i++) {
148 int r = (i == 7 ? 25 : i + 8);
149 cpu_pal_ir[r] = tcg_global_mem_new_i64(tcg_env,
150 offsetof(CPUAlphaState,
151 shadow[i]),
152 shadow_names[i]);
154 #endif
156 for (i = 0; i < ARRAY_SIZE(vars); ++i) {
157 const GlobalVar *v = &vars[i];
158 *v->var = tcg_global_mem_new_i64(tcg_env, v->ofs, v->name);
162 static TCGv load_zero(DisasContext *ctx)
164 if (!ctx->zero) {
165 ctx->zero = tcg_constant_i64(0);
167 return ctx->zero;
170 static TCGv dest_sink(DisasContext *ctx)
172 if (!ctx->sink) {
173 ctx->sink = tcg_temp_new();
175 return ctx->sink;
178 static void free_context_temps(DisasContext *ctx)
180 if (ctx->sink) {
181 tcg_gen_discard_i64(ctx->sink);
182 ctx->sink = NULL;
186 static TCGv load_gpr(DisasContext *ctx, unsigned reg)
188 if (likely(reg < 31)) {
189 return ctx->ir[reg];
190 } else {
191 return load_zero(ctx);
195 static TCGv load_gpr_lit(DisasContext *ctx, unsigned reg,
196 uint8_t lit, bool islit)
198 if (islit) {
199 return tcg_constant_i64(lit);
200 } else if (likely(reg < 31)) {
201 return ctx->ir[reg];
202 } else {
203 return load_zero(ctx);
207 static TCGv dest_gpr(DisasContext *ctx, unsigned reg)
209 if (likely(reg < 31)) {
210 return ctx->ir[reg];
211 } else {
212 return dest_sink(ctx);
216 static TCGv load_fpr(DisasContext *ctx, unsigned reg)
218 if (likely(reg < 31)) {
219 return cpu_fir[reg];
220 } else {
221 return load_zero(ctx);
225 static TCGv dest_fpr(DisasContext *ctx, unsigned reg)
227 if (likely(reg < 31)) {
228 return cpu_fir[reg];
229 } else {
230 return dest_sink(ctx);
234 static int get_flag_ofs(unsigned shift)
236 int ofs = offsetof(CPUAlphaState, flags);
237 #if HOST_BIG_ENDIAN
238 ofs += 3 - (shift / 8);
239 #else
240 ofs += shift / 8;
241 #endif
242 return ofs;
245 static void ld_flag_byte(TCGv val, unsigned shift)
247 tcg_gen_ld8u_i64(val, tcg_env, get_flag_ofs(shift));
250 static void st_flag_byte(TCGv val, unsigned shift)
252 tcg_gen_st8_i64(val, tcg_env, get_flag_ofs(shift));
255 static void gen_excp_1(int exception, int error_code)
257 TCGv_i32 tmp1, tmp2;
259 tmp1 = tcg_constant_i32(exception);
260 tmp2 = tcg_constant_i32(error_code);
261 gen_helper_excp(tcg_env, tmp1, tmp2);
264 static DisasJumpType gen_excp(DisasContext *ctx, int exception, int error_code)
266 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
267 gen_excp_1(exception, error_code);
268 return DISAS_NORETURN;
271 static inline DisasJumpType gen_invalid(DisasContext *ctx)
273 return gen_excp(ctx, EXCP_OPCDEC, 0);
276 static void gen_ldf(DisasContext *ctx, TCGv dest, TCGv addr)
278 TCGv_i32 tmp32 = tcg_temp_new_i32();
279 tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
280 gen_helper_memory_to_f(dest, tmp32);
283 static void gen_ldg(DisasContext *ctx, TCGv dest, TCGv addr)
285 TCGv tmp = tcg_temp_new();
286 tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
287 gen_helper_memory_to_g(dest, tmp);
290 static void gen_lds(DisasContext *ctx, TCGv dest, TCGv addr)
292 TCGv_i32 tmp32 = tcg_temp_new_i32();
293 tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
294 gen_helper_memory_to_s(dest, tmp32);
297 static void gen_ldt(DisasContext *ctx, TCGv dest, TCGv addr)
299 tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
302 static void gen_load_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
303 void (*func)(DisasContext *, TCGv, TCGv))
305 /* Loads to $f31 are prefetches, which we can treat as nops. */
306 if (likely(ra != 31)) {
307 TCGv addr = tcg_temp_new();
308 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
309 func(ctx, cpu_fir[ra], addr);
313 static void gen_load_int(DisasContext *ctx, int ra, int rb, int32_t disp16,
314 MemOp op, bool clear, bool locked)
316 TCGv addr, dest;
318 /* LDQ_U with ra $31 is UNOP. Other various loads are forms of
319 prefetches, which we can treat as nops. No worries about
320 missed exceptions here. */
321 if (unlikely(ra == 31)) {
322 return;
325 addr = tcg_temp_new();
326 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
327 if (clear) {
328 tcg_gen_andi_i64(addr, addr, ~0x7);
329 } else if (!locked) {
330 op |= UNALIGN(ctx);
333 dest = ctx->ir[ra];
334 tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, op);
336 if (locked) {
337 tcg_gen_mov_i64(cpu_lock_addr, addr);
338 tcg_gen_mov_i64(cpu_lock_value, dest);
342 static void gen_stf(DisasContext *ctx, TCGv src, TCGv addr)
344 TCGv_i32 tmp32 = tcg_temp_new_i32();
345 gen_helper_f_to_memory(tmp32, addr);
346 tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
349 static void gen_stg(DisasContext *ctx, TCGv src, TCGv addr)
351 TCGv tmp = tcg_temp_new();
352 gen_helper_g_to_memory(tmp, src);
353 tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
356 static void gen_sts(DisasContext *ctx, TCGv src, TCGv addr)
358 TCGv_i32 tmp32 = tcg_temp_new_i32();
359 gen_helper_s_to_memory(tmp32, src);
360 tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
363 static void gen_stt(DisasContext *ctx, TCGv src, TCGv addr)
365 tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
368 static void gen_store_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
369 void (*func)(DisasContext *, TCGv, TCGv))
371 TCGv addr = tcg_temp_new();
372 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
373 func(ctx, load_fpr(ctx, ra), addr);
376 static void gen_store_int(DisasContext *ctx, int ra, int rb, int32_t disp16,
377 MemOp op, bool clear)
379 TCGv addr, src;
381 addr = tcg_temp_new();
382 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
383 if (clear) {
384 tcg_gen_andi_i64(addr, addr, ~0x7);
385 } else {
386 op |= UNALIGN(ctx);
389 src = load_gpr(ctx, ra);
390 tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, op);
393 static DisasJumpType gen_store_conditional(DisasContext *ctx, int ra, int rb,
394 int32_t disp16, int mem_idx,
395 MemOp op)
397 TCGLabel *lab_fail, *lab_done;
398 TCGv addr, val;
400 addr = tcg_temp_new_i64();
401 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
402 free_context_temps(ctx);
404 lab_fail = gen_new_label();
405 lab_done = gen_new_label();
406 tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
408 val = tcg_temp_new_i64();
409 tcg_gen_atomic_cmpxchg_i64(val, cpu_lock_addr, cpu_lock_value,
410 load_gpr(ctx, ra), mem_idx, op);
411 free_context_temps(ctx);
413 if (ra != 31) {
414 tcg_gen_setcond_i64(TCG_COND_EQ, ctx->ir[ra], val, cpu_lock_value);
416 tcg_gen_br(lab_done);
418 gen_set_label(lab_fail);
419 if (ra != 31) {
420 tcg_gen_movi_i64(ctx->ir[ra], 0);
423 gen_set_label(lab_done);
424 tcg_gen_movi_i64(cpu_lock_addr, -1);
425 return DISAS_NEXT;
428 static bool use_goto_tb(DisasContext *ctx, uint64_t dest)
430 return translator_use_goto_tb(&ctx->base, dest);
433 static DisasJumpType gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
435 uint64_t dest = ctx->base.pc_next + disp;
437 if (ra != 31) {
438 tcg_gen_movi_i64(ctx->ir[ra], ctx->base.pc_next);
441 /* Notice branch-to-next; used to initialize RA with the PC. */
442 if (disp == 0) {
443 return 0;
444 } else if (use_goto_tb(ctx, dest)) {
445 tcg_gen_goto_tb(0);
446 tcg_gen_movi_i64(cpu_pc, dest);
447 tcg_gen_exit_tb(ctx->base.tb, 0);
448 return DISAS_NORETURN;
449 } else {
450 tcg_gen_movi_i64(cpu_pc, dest);
451 return DISAS_PC_UPDATED;
455 static DisasJumpType gen_bcond_internal(DisasContext *ctx, TCGCond cond,
456 TCGv cmp, uint64_t imm, int32_t disp)
458 uint64_t dest = ctx->base.pc_next + disp;
459 TCGLabel *lab_true = gen_new_label();
461 if (use_goto_tb(ctx, dest)) {
462 tcg_gen_brcondi_i64(cond, cmp, imm, lab_true);
464 tcg_gen_goto_tb(0);
465 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
466 tcg_gen_exit_tb(ctx->base.tb, 0);
468 gen_set_label(lab_true);
469 tcg_gen_goto_tb(1);
470 tcg_gen_movi_i64(cpu_pc, dest);
471 tcg_gen_exit_tb(ctx->base.tb, 1);
473 return DISAS_NORETURN;
474 } else {
475 TCGv_i64 i = tcg_constant_i64(imm);
476 TCGv_i64 d = tcg_constant_i64(dest);
477 TCGv_i64 p = tcg_constant_i64(ctx->base.pc_next);
479 tcg_gen_movcond_i64(cond, cpu_pc, cmp, i, d, p);
480 return DISAS_PC_UPDATED;
484 static DisasJumpType gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
485 int32_t disp)
487 return gen_bcond_internal(ctx, cond, load_gpr(ctx, ra),
488 is_tst_cond(cond), disp);
491 /* Fold -0.0 for comparison with COND. */
493 static TCGv_i64 gen_fold_mzero(TCGCond *pcond, uint64_t *pimm, TCGv_i64 src)
495 TCGv_i64 tmp;
497 *pimm = 0;
498 switch (*pcond) {
499 case TCG_COND_LE:
500 case TCG_COND_GT:
501 /* For <= or >, the -0.0 value directly compares the way we want. */
502 return src;
504 case TCG_COND_EQ:
505 case TCG_COND_NE:
506 /* For == or !=, we can compare without the sign bit. */
507 *pcond = *pcond == TCG_COND_EQ ? TCG_COND_TSTEQ : TCG_COND_TSTNE;
508 *pimm = INT64_MAX;
509 return src;
511 case TCG_COND_GE:
512 case TCG_COND_LT:
513 /* For >= or <, map -0.0 to +0.0. */
514 tmp = tcg_temp_new_i64();
515 tcg_gen_movcond_i64(TCG_COND_EQ, tmp,
516 src, tcg_constant_i64(INT64_MIN),
517 tcg_constant_i64(0), src);
518 return tmp;
520 default:
521 g_assert_not_reached();
525 static DisasJumpType gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
526 int32_t disp)
528 uint64_t imm;
529 TCGv_i64 tmp = gen_fold_mzero(&cond, &imm, load_fpr(ctx, ra));
530 return gen_bcond_internal(ctx, cond, tmp, imm, disp);
533 static void gen_fcmov(DisasContext *ctx, TCGCond cond, int ra, int rb, int rc)
535 uint64_t imm;
536 TCGv_i64 tmp = gen_fold_mzero(&cond, &imm, load_fpr(ctx, ra));
537 tcg_gen_movcond_i64(cond, dest_fpr(ctx, rc),
538 tmp, tcg_constant_i64(imm),
539 load_fpr(ctx, rb), load_fpr(ctx, rc));
542 #define QUAL_RM_N 0x080 /* Round mode nearest even */
543 #define QUAL_RM_C 0x000 /* Round mode chopped */
544 #define QUAL_RM_M 0x040 /* Round mode minus infinity */
545 #define QUAL_RM_D 0x0c0 /* Round mode dynamic */
546 #define QUAL_RM_MASK 0x0c0
548 #define QUAL_U 0x100 /* Underflow enable (fp output) */
549 #define QUAL_V 0x100 /* Overflow enable (int output) */
550 #define QUAL_S 0x400 /* Software completion enable */
551 #define QUAL_I 0x200 /* Inexact detection enable */
553 static void gen_qual_roundmode(DisasContext *ctx, int fn11)
555 TCGv_i32 tmp;
557 fn11 &= QUAL_RM_MASK;
558 if (fn11 == ctx->tb_rm) {
559 return;
561 ctx->tb_rm = fn11;
563 tmp = tcg_temp_new_i32();
564 switch (fn11) {
565 case QUAL_RM_N:
566 tcg_gen_movi_i32(tmp, float_round_nearest_even);
567 break;
568 case QUAL_RM_C:
569 tcg_gen_movi_i32(tmp, float_round_to_zero);
570 break;
571 case QUAL_RM_M:
572 tcg_gen_movi_i32(tmp, float_round_down);
573 break;
574 case QUAL_RM_D:
575 tcg_gen_ld8u_i32(tmp, tcg_env,
576 offsetof(CPUAlphaState, fpcr_dyn_round));
577 break;
580 #if defined(CONFIG_SOFTFLOAT_INLINE)
581 /* ??? The "fpu/softfloat.h" interface is to call set_float_rounding_mode.
582 With CONFIG_SOFTFLOAT that expands to an out-of-line call that just
583 sets the one field. */
584 tcg_gen_st8_i32(tmp, tcg_env,
585 offsetof(CPUAlphaState, fp_status.float_rounding_mode));
586 #else
587 gen_helper_setroundmode(tmp);
588 #endif
591 static void gen_qual_flushzero(DisasContext *ctx, int fn11)
593 TCGv_i32 tmp;
595 fn11 &= QUAL_U;
596 if (fn11 == ctx->tb_ftz) {
597 return;
599 ctx->tb_ftz = fn11;
601 tmp = tcg_temp_new_i32();
602 if (fn11) {
603 /* Underflow is enabled, use the FPCR setting. */
604 tcg_gen_ld8u_i32(tmp, tcg_env,
605 offsetof(CPUAlphaState, fpcr_flush_to_zero));
606 } else {
607 /* Underflow is disabled, force flush-to-zero. */
608 tcg_gen_movi_i32(tmp, 1);
611 #if defined(CONFIG_SOFTFLOAT_INLINE)
612 tcg_gen_st8_i32(tmp, tcg_env,
613 offsetof(CPUAlphaState, fp_status.flush_to_zero));
614 #else
615 gen_helper_setflushzero(tmp);
616 #endif
619 static TCGv gen_ieee_input(DisasContext *ctx, int reg, int fn11, int is_cmp)
621 TCGv val;
623 if (unlikely(reg == 31)) {
624 val = load_zero(ctx);
625 } else {
626 val = cpu_fir[reg];
627 if ((fn11 & QUAL_S) == 0) {
628 if (is_cmp) {
629 gen_helper_ieee_input_cmp(tcg_env, val);
630 } else {
631 gen_helper_ieee_input(tcg_env, val);
633 } else {
634 #ifndef CONFIG_USER_ONLY
635 /* In system mode, raise exceptions for denormals like real
636 hardware. In user mode, proceed as if the OS completion
637 handler is handling the denormal as per spec. */
638 gen_helper_ieee_input_s(tcg_env, val);
639 #endif
642 return val;
645 static void gen_fp_exc_raise(int rc, int fn11)
647 /* ??? We ought to be able to do something with imprecise exceptions.
648 E.g. notice we're still in the trap shadow of something within the
649 TB and do not generate the code to signal the exception; end the TB
650 when an exception is forced to arrive, either by consumption of a
651 register value or TRAPB or EXCB. */
652 TCGv_i32 reg, ign;
653 uint32_t ignore = 0;
655 if (!(fn11 & QUAL_U)) {
656 /* Note that QUAL_U == QUAL_V, so ignore either. */
657 ignore |= FPCR_UNF | FPCR_IOV;
659 if (!(fn11 & QUAL_I)) {
660 ignore |= FPCR_INE;
662 ign = tcg_constant_i32(ignore);
664 /* ??? Pass in the regno of the destination so that the helper can
665 set EXC_MASK, which contains a bitmask of destination registers
666 that have caused arithmetic traps. A simple userspace emulation
667 does not require this. We do need it for a guest kernel's entArith,
668 or if we were to do something clever with imprecise exceptions. */
669 reg = tcg_constant_i32(rc + 32);
670 if (fn11 & QUAL_S) {
671 gen_helper_fp_exc_raise_s(tcg_env, ign, reg);
672 } else {
673 gen_helper_fp_exc_raise(tcg_env, ign, reg);
677 static void gen_cvtlq(TCGv vc, TCGv vb)
679 TCGv tmp = tcg_temp_new();
681 /* The arithmetic right shift here, plus the sign-extended mask below
682 yields a sign-extended result without an explicit ext32s_i64. */
683 tcg_gen_shri_i64(tmp, vb, 29);
684 tcg_gen_sari_i64(vc, vb, 32);
685 tcg_gen_deposit_i64(vc, vc, tmp, 0, 30);
688 static void gen_ieee_arith2(DisasContext *ctx,
689 void (*helper)(TCGv, TCGv_ptr, TCGv),
690 int rb, int rc, int fn11)
692 TCGv vb;
694 gen_qual_roundmode(ctx, fn11);
695 gen_qual_flushzero(ctx, fn11);
697 vb = gen_ieee_input(ctx, rb, fn11, 0);
698 helper(dest_fpr(ctx, rc), tcg_env, vb);
700 gen_fp_exc_raise(rc, fn11);
703 #define IEEE_ARITH2(name) \
704 static inline void glue(gen_, name)(DisasContext *ctx, \
705 int rb, int rc, int fn11) \
707 gen_ieee_arith2(ctx, gen_helper_##name, rb, rc, fn11); \
709 IEEE_ARITH2(sqrts)
710 IEEE_ARITH2(sqrtt)
711 IEEE_ARITH2(cvtst)
712 IEEE_ARITH2(cvtts)
714 static void gen_cvttq(DisasContext *ctx, int rb, int rc, int fn11)
716 TCGv vb, vc;
718 /* No need to set flushzero, since we have an integer output. */
719 vb = gen_ieee_input(ctx, rb, fn11, 0);
720 vc = dest_fpr(ctx, rc);
722 /* Almost all integer conversions use cropped rounding;
723 special case that. */
724 if ((fn11 & QUAL_RM_MASK) == QUAL_RM_C) {
725 gen_helper_cvttq_c(vc, tcg_env, vb);
726 } else {
727 gen_qual_roundmode(ctx, fn11);
728 gen_helper_cvttq(vc, tcg_env, vb);
730 gen_fp_exc_raise(rc, fn11);
733 static void gen_ieee_intcvt(DisasContext *ctx,
734 void (*helper)(TCGv, TCGv_ptr, TCGv),
735 int rb, int rc, int fn11)
737 TCGv vb, vc;
739 gen_qual_roundmode(ctx, fn11);
740 vb = load_fpr(ctx, rb);
741 vc = dest_fpr(ctx, rc);
743 /* The only exception that can be raised by integer conversion
744 is inexact. Thus we only need to worry about exceptions when
745 inexact handling is requested. */
746 if (fn11 & QUAL_I) {
747 helper(vc, tcg_env, vb);
748 gen_fp_exc_raise(rc, fn11);
749 } else {
750 helper(vc, tcg_env, vb);
754 #define IEEE_INTCVT(name) \
755 static inline void glue(gen_, name)(DisasContext *ctx, \
756 int rb, int rc, int fn11) \
758 gen_ieee_intcvt(ctx, gen_helper_##name, rb, rc, fn11); \
760 IEEE_INTCVT(cvtqs)
761 IEEE_INTCVT(cvtqt)
763 static void gen_cpy_mask(TCGv vc, TCGv va, TCGv vb, bool inv_a, uint64_t mask)
765 TCGv vmask = tcg_constant_i64(mask);
766 TCGv tmp = tcg_temp_new_i64();
768 if (inv_a) {
769 tcg_gen_andc_i64(tmp, vmask, va);
770 } else {
771 tcg_gen_and_i64(tmp, va, vmask);
774 tcg_gen_andc_i64(vc, vb, vmask);
775 tcg_gen_or_i64(vc, vc, tmp);
778 static void gen_ieee_arith3(DisasContext *ctx,
779 void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
780 int ra, int rb, int rc, int fn11)
782 TCGv va, vb, vc;
784 gen_qual_roundmode(ctx, fn11);
785 gen_qual_flushzero(ctx, fn11);
787 va = gen_ieee_input(ctx, ra, fn11, 0);
788 vb = gen_ieee_input(ctx, rb, fn11, 0);
789 vc = dest_fpr(ctx, rc);
790 helper(vc, tcg_env, va, vb);
792 gen_fp_exc_raise(rc, fn11);
795 #define IEEE_ARITH3(name) \
796 static inline void glue(gen_, name)(DisasContext *ctx, \
797 int ra, int rb, int rc, int fn11) \
799 gen_ieee_arith3(ctx, gen_helper_##name, ra, rb, rc, fn11); \
801 IEEE_ARITH3(adds)
802 IEEE_ARITH3(subs)
803 IEEE_ARITH3(muls)
804 IEEE_ARITH3(divs)
805 IEEE_ARITH3(addt)
806 IEEE_ARITH3(subt)
807 IEEE_ARITH3(mult)
808 IEEE_ARITH3(divt)
810 static void gen_ieee_compare(DisasContext *ctx,
811 void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
812 int ra, int rb, int rc, int fn11)
814 TCGv va, vb, vc;
816 va = gen_ieee_input(ctx, ra, fn11, 1);
817 vb = gen_ieee_input(ctx, rb, fn11, 1);
818 vc = dest_fpr(ctx, rc);
819 helper(vc, tcg_env, va, vb);
821 gen_fp_exc_raise(rc, fn11);
824 #define IEEE_CMP3(name) \
825 static inline void glue(gen_, name)(DisasContext *ctx, \
826 int ra, int rb, int rc, int fn11) \
828 gen_ieee_compare(ctx, gen_helper_##name, ra, rb, rc, fn11); \
830 IEEE_CMP3(cmptun)
831 IEEE_CMP3(cmpteq)
832 IEEE_CMP3(cmptlt)
833 IEEE_CMP3(cmptle)
835 static inline uint64_t zapnot_mask(uint8_t lit)
837 uint64_t mask = 0;
838 int i;
840 for (i = 0; i < 8; ++i) {
841 if ((lit >> i) & 1) {
842 mask |= 0xffull << (i * 8);
845 return mask;
848 /* Implement zapnot with an immediate operand, which expands to some
849 form of immediate AND. This is a basic building block in the
850 definition of many of the other byte manipulation instructions. */
851 static void gen_zapnoti(TCGv dest, TCGv src, uint8_t lit)
853 switch (lit) {
854 case 0x00:
855 tcg_gen_movi_i64(dest, 0);
856 break;
857 case 0x01:
858 tcg_gen_ext8u_i64(dest, src);
859 break;
860 case 0x03:
861 tcg_gen_ext16u_i64(dest, src);
862 break;
863 case 0x0f:
864 tcg_gen_ext32u_i64(dest, src);
865 break;
866 case 0xff:
867 tcg_gen_mov_i64(dest, src);
868 break;
869 default:
870 tcg_gen_andi_i64(dest, src, zapnot_mask(lit));
871 break;
875 /* EXTWH, EXTLH, EXTQH */
876 static void gen_ext_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
877 uint8_t lit, uint8_t byte_mask)
879 if (islit) {
880 int pos = (64 - lit * 8) & 0x3f;
881 int len = cto32(byte_mask) * 8;
882 if (pos < len) {
883 tcg_gen_deposit_z_i64(vc, va, pos, len - pos);
884 } else {
885 tcg_gen_movi_i64(vc, 0);
887 } else {
888 TCGv tmp = tcg_temp_new();
889 tcg_gen_shli_i64(tmp, load_gpr(ctx, rb), 3);
890 tcg_gen_neg_i64(tmp, tmp);
891 tcg_gen_andi_i64(tmp, tmp, 0x3f);
892 tcg_gen_shl_i64(vc, va, tmp);
894 gen_zapnoti(vc, vc, byte_mask);
897 /* EXTBL, EXTWL, EXTLL, EXTQL */
898 static void gen_ext_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
899 uint8_t lit, uint8_t byte_mask)
901 if (islit) {
902 int pos = (lit & 7) * 8;
903 int len = cto32(byte_mask) * 8;
904 if (pos + len >= 64) {
905 len = 64 - pos;
907 tcg_gen_extract_i64(vc, va, pos, len);
908 } else {
909 TCGv tmp = tcg_temp_new();
910 tcg_gen_andi_i64(tmp, load_gpr(ctx, rb), 7);
911 tcg_gen_shli_i64(tmp, tmp, 3);
912 tcg_gen_shr_i64(vc, va, tmp);
913 gen_zapnoti(vc, vc, byte_mask);
917 /* INSWH, INSLH, INSQH */
918 static void gen_ins_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
919 uint8_t lit, uint8_t byte_mask)
921 if (islit) {
922 int pos = 64 - (lit & 7) * 8;
923 int len = cto32(byte_mask) * 8;
924 if (pos < len) {
925 tcg_gen_extract_i64(vc, va, pos, len - pos);
926 } else {
927 tcg_gen_movi_i64(vc, 0);
929 } else {
930 TCGv tmp = tcg_temp_new();
931 TCGv shift = tcg_temp_new();
933 /* The instruction description has us left-shift the byte mask
934 and extract bits <15:8> and apply that zap at the end. This
935 is equivalent to simply performing the zap first and shifting
936 afterward. */
937 gen_zapnoti(tmp, va, byte_mask);
939 /* If (B & 7) == 0, we need to shift by 64 and leave a zero. Do this
940 portably by splitting the shift into two parts: shift_count-1 and 1.
941 Arrange for the -1 by using ones-complement instead of
942 twos-complement in the negation: ~(B * 8) & 63. */
944 tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3);
945 tcg_gen_not_i64(shift, shift);
946 tcg_gen_andi_i64(shift, shift, 0x3f);
948 tcg_gen_shr_i64(vc, tmp, shift);
949 tcg_gen_shri_i64(vc, vc, 1);
953 /* INSBL, INSWL, INSLL, INSQL */
954 static void gen_ins_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
955 uint8_t lit, uint8_t byte_mask)
957 if (islit) {
958 int pos = (lit & 7) * 8;
959 int len = cto32(byte_mask) * 8;
960 if (pos + len > 64) {
961 len = 64 - pos;
963 tcg_gen_deposit_z_i64(vc, va, pos, len);
964 } else {
965 TCGv tmp = tcg_temp_new();
966 TCGv shift = tcg_temp_new();
968 /* The instruction description has us left-shift the byte mask
969 and extract bits <15:8> and apply that zap at the end. This
970 is equivalent to simply performing the zap first and shifting
971 afterward. */
972 gen_zapnoti(tmp, va, byte_mask);
974 tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
975 tcg_gen_shli_i64(shift, shift, 3);
976 tcg_gen_shl_i64(vc, tmp, shift);
980 /* MSKWH, MSKLH, MSKQH */
981 static void gen_msk_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
982 uint8_t lit, uint8_t byte_mask)
984 if (islit) {
985 gen_zapnoti(vc, va, ~((byte_mask << (lit & 7)) >> 8));
986 } else {
987 TCGv shift = tcg_temp_new();
988 TCGv mask = tcg_temp_new();
990 /* The instruction description is as above, where the byte_mask
991 is shifted left, and then we extract bits <15:8>. This can be
992 emulated with a right-shift on the expanded byte mask. This
993 requires extra care because for an input <2:0> == 0 we need a
994 shift of 64 bits in order to generate a zero. This is done by
995 splitting the shift into two parts, the variable shift - 1
996 followed by a constant 1 shift. The code we expand below is
997 equivalent to ~(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);
1002 tcg_gen_movi_i64(mask, zapnot_mask (byte_mask));
1003 tcg_gen_shr_i64(mask, mask, shift);
1004 tcg_gen_shri_i64(mask, mask, 1);
1006 tcg_gen_andc_i64(vc, va, mask);
1010 /* MSKBL, MSKWL, MSKLL, MSKQL */
1011 static void gen_msk_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
1012 uint8_t lit, uint8_t byte_mask)
1014 if (islit) {
1015 gen_zapnoti(vc, va, ~(byte_mask << (lit & 7)));
1016 } else {
1017 TCGv shift = tcg_temp_new();
1018 TCGv mask = tcg_temp_new();
1020 tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
1021 tcg_gen_shli_i64(shift, shift, 3);
1022 tcg_gen_movi_i64(mask, zapnot_mask(byte_mask));
1023 tcg_gen_shl_i64(mask, mask, shift);
1025 tcg_gen_andc_i64(vc, va, mask);
1029 static void gen_rx(DisasContext *ctx, int ra, int set)
1031 if (ra != 31) {
1032 ld_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT);
1035 st_flag_byte(tcg_constant_i64(set), ENV_FLAG_RX_SHIFT);
1038 static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode)
1040 /* We're emulating OSF/1 PALcode. Many of these are trivial access
1041 to internal cpu registers. */
1043 /* Unprivileged PAL call */
1044 if (palcode >= 0x80 && palcode < 0xC0) {
1045 switch (palcode) {
1046 case 0x86:
1047 /* IMB */
1048 /* No-op inside QEMU. */
1049 break;
1050 case 0x9E:
1051 /* RDUNIQUE */
1052 tcg_gen_ld_i64(ctx->ir[IR_V0], tcg_env,
1053 offsetof(CPUAlphaState, unique));
1054 break;
1055 case 0x9F:
1056 /* WRUNIQUE */
1057 tcg_gen_st_i64(ctx->ir[IR_A0], tcg_env,
1058 offsetof(CPUAlphaState, unique));
1059 break;
1060 default:
1061 palcode &= 0xbf;
1062 goto do_call_pal;
1064 return DISAS_NEXT;
1067 #ifndef CONFIG_USER_ONLY
1068 /* Privileged PAL code */
1069 if (palcode < 0x40 && (ctx->tbflags & ENV_FLAG_PS_USER) == 0) {
1070 switch (palcode) {
1071 case 0x01:
1072 /* CFLUSH */
1073 /* No-op inside QEMU. */
1074 break;
1075 case 0x02:
1076 /* DRAINA */
1077 /* No-op inside QEMU. */
1078 break;
1079 case 0x2D:
1080 /* WRVPTPTR */
1081 tcg_gen_st_i64(ctx->ir[IR_A0], tcg_env,
1082 offsetof(CPUAlphaState, vptptr));
1083 break;
1084 case 0x31:
1085 /* WRVAL */
1086 tcg_gen_st_i64(ctx->ir[IR_A0], tcg_env,
1087 offsetof(CPUAlphaState, sysval));
1088 break;
1089 case 0x32:
1090 /* RDVAL */
1091 tcg_gen_ld_i64(ctx->ir[IR_V0], tcg_env,
1092 offsetof(CPUAlphaState, sysval));
1093 break;
1095 case 0x35:
1096 /* SWPIPL */
1097 /* Note that we already know we're in kernel mode, so we know
1098 that PS only contains the 3 IPL bits. */
1099 ld_flag_byte(ctx->ir[IR_V0], ENV_FLAG_PS_SHIFT);
1101 /* But make sure and store only the 3 IPL bits from the user. */
1103 TCGv tmp = tcg_temp_new();
1104 tcg_gen_andi_i64(tmp, ctx->ir[IR_A0], PS_INT_MASK);
1105 st_flag_byte(tmp, ENV_FLAG_PS_SHIFT);
1108 /* Allow interrupts to be recognized right away. */
1109 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
1110 return DISAS_PC_UPDATED_NOCHAIN;
1112 case 0x36:
1113 /* RDPS */
1114 ld_flag_byte(ctx->ir[IR_V0], ENV_FLAG_PS_SHIFT);
1115 break;
1117 case 0x38:
1118 /* WRUSP */
1119 tcg_gen_st_i64(ctx->ir[IR_A0], tcg_env,
1120 offsetof(CPUAlphaState, usp));
1121 break;
1122 case 0x3A:
1123 /* RDUSP */
1124 tcg_gen_ld_i64(ctx->ir[IR_V0], tcg_env,
1125 offsetof(CPUAlphaState, usp));
1126 break;
1127 case 0x3C:
1128 /* WHAMI */
1129 tcg_gen_ld32s_i64(ctx->ir[IR_V0], tcg_env,
1130 -offsetof(AlphaCPU, env) + offsetof(CPUState, cpu_index));
1131 break;
1133 case 0x3E:
1134 /* WTINT */
1135 tcg_gen_st_i32(tcg_constant_i32(1), tcg_env,
1136 -offsetof(AlphaCPU, env) +
1137 offsetof(CPUState, halted));
1138 tcg_gen_movi_i64(ctx->ir[IR_V0], 0);
1139 return gen_excp(ctx, EXCP_HALTED, 0);
1141 default:
1142 palcode &= 0x3f;
1143 goto do_call_pal;
1145 return DISAS_NEXT;
1147 #endif
1148 return gen_invalid(ctx);
1150 do_call_pal:
1151 #ifdef CONFIG_USER_ONLY
1152 return gen_excp(ctx, EXCP_CALL_PAL, palcode);
1153 #else
1155 TCGv tmp = tcg_temp_new();
1156 uint64_t exc_addr = ctx->base.pc_next;
1157 uint64_t entry = ctx->palbr;
1159 if (ctx->tbflags & ENV_FLAG_PAL_MODE) {
1160 exc_addr |= 1;
1161 } else {
1162 tcg_gen_movi_i64(tmp, 1);
1163 st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT);
1166 tcg_gen_movi_i64(tmp, exc_addr);
1167 tcg_gen_st_i64(tmp, tcg_env, offsetof(CPUAlphaState, exc_addr));
1169 entry += (palcode & 0x80
1170 ? 0x2000 + (palcode - 0x80) * 64
1171 : 0x1000 + palcode * 64);
1173 tcg_gen_movi_i64(cpu_pc, entry);
1174 return DISAS_PC_UPDATED;
1176 #endif
1179 #ifndef CONFIG_USER_ONLY
1181 #define PR_LONG 0x200000
1183 static int cpu_pr_data(int pr)
1185 switch (pr) {
1186 case 2: return offsetof(CPUAlphaState, pcc_ofs) | PR_LONG;
1187 case 3: return offsetof(CPUAlphaState, trap_arg0);
1188 case 4: return offsetof(CPUAlphaState, trap_arg1);
1189 case 5: return offsetof(CPUAlphaState, trap_arg2);
1190 case 6: return offsetof(CPUAlphaState, exc_addr);
1191 case 7: return offsetof(CPUAlphaState, palbr);
1192 case 8: return offsetof(CPUAlphaState, ptbr);
1193 case 9: return offsetof(CPUAlphaState, vptptr);
1194 case 10: return offsetof(CPUAlphaState, unique);
1195 case 11: return offsetof(CPUAlphaState, sysval);
1196 case 12: return offsetof(CPUAlphaState, usp);
1198 case 40 ... 63:
1199 return offsetof(CPUAlphaState, scratch[pr - 40]);
1201 case 251:
1202 return offsetof(CPUAlphaState, alarm_expire);
1204 return 0;
1207 static DisasJumpType gen_mfpr(DisasContext *ctx, TCGv va, int regno)
1209 void (*helper)(TCGv);
1210 int data;
1212 switch (regno) {
1213 case 32 ... 39:
1214 /* Accessing the "non-shadow" general registers. */
1215 regno = regno == 39 ? 25 : regno - 32 + 8;
1216 tcg_gen_mov_i64(va, cpu_std_ir[regno]);
1217 break;
1219 case 250: /* WALLTIME */
1220 helper = gen_helper_get_walltime;
1221 goto do_helper;
1222 case 249: /* VMTIME */
1223 helper = gen_helper_get_vmtime;
1224 do_helper:
1225 if (translator_io_start(&ctx->base)) {
1226 helper(va);
1227 return DISAS_PC_STALE;
1228 } else {
1229 helper(va);
1231 break;
1233 case 0: /* PS */
1234 ld_flag_byte(va, ENV_FLAG_PS_SHIFT);
1235 break;
1236 case 1: /* FEN */
1237 ld_flag_byte(va, ENV_FLAG_FEN_SHIFT);
1238 break;
1240 default:
1241 /* The basic registers are data only, and unknown registers
1242 are read-zero, write-ignore. */
1243 data = cpu_pr_data(regno);
1244 if (data == 0) {
1245 tcg_gen_movi_i64(va, 0);
1246 } else if (data & PR_LONG) {
1247 tcg_gen_ld32s_i64(va, tcg_env, data & ~PR_LONG);
1248 } else {
1249 tcg_gen_ld_i64(va, tcg_env, data);
1251 break;
1254 return DISAS_NEXT;
1257 static DisasJumpType gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
1259 int data;
1260 DisasJumpType ret = DISAS_NEXT;
1262 switch (regno) {
1263 case 255:
1264 /* TBIA */
1265 gen_helper_tbia(tcg_env);
1266 break;
1268 case 254:
1269 /* TBIS */
1270 gen_helper_tbis(tcg_env, vb);
1271 break;
1273 case 253:
1274 /* WAIT */
1275 tcg_gen_st_i32(tcg_constant_i32(1), tcg_env,
1276 -offsetof(AlphaCPU, env) + offsetof(CPUState, halted));
1277 return gen_excp(ctx, EXCP_HALTED, 0);
1279 case 252:
1280 /* HALT */
1281 gen_helper_halt(vb);
1282 return DISAS_PC_STALE;
1284 case 251:
1285 /* ALARM */
1286 if (translator_io_start(&ctx->base)) {
1287 ret = DISAS_PC_STALE;
1289 gen_helper_set_alarm(tcg_env, vb);
1290 break;
1292 case 7:
1293 /* PALBR */
1294 tcg_gen_st_i64(vb, tcg_env, offsetof(CPUAlphaState, palbr));
1295 /* Changing the PAL base register implies un-chaining all of the TBs
1296 that ended with a CALL_PAL. Since the base register usually only
1297 changes during boot, flushing everything works well. */
1298 gen_helper_tb_flush(tcg_env);
1299 return DISAS_PC_STALE;
1301 case 32 ... 39:
1302 /* Accessing the "non-shadow" general registers. */
1303 regno = regno == 39 ? 25 : regno - 32 + 8;
1304 tcg_gen_mov_i64(cpu_std_ir[regno], vb);
1305 break;
1307 case 0: /* PS */
1308 st_flag_byte(vb, ENV_FLAG_PS_SHIFT);
1309 break;
1310 case 1: /* FEN */
1311 st_flag_byte(vb, ENV_FLAG_FEN_SHIFT);
1312 break;
1314 default:
1315 /* The basic registers are data only, and unknown registers
1316 are read-zero, write-ignore. */
1317 data = cpu_pr_data(regno);
1318 if (data != 0) {
1319 if (data & PR_LONG) {
1320 tcg_gen_st32_i64(vb, tcg_env, data & ~PR_LONG);
1321 } else {
1322 tcg_gen_st_i64(vb, tcg_env, data);
1325 break;
1328 return ret;
1330 #endif /* !USER_ONLY*/
1332 #define REQUIRE_NO_LIT \
1333 do { \
1334 if (real_islit) { \
1335 goto invalid_opc; \
1337 } while (0)
1339 #define REQUIRE_AMASK(FLAG) \
1340 do { \
1341 if ((ctx->amask & AMASK_##FLAG) == 0) { \
1342 goto invalid_opc; \
1344 } while (0)
1346 #define REQUIRE_TB_FLAG(FLAG) \
1347 do { \
1348 if ((ctx->tbflags & (FLAG)) == 0) { \
1349 goto invalid_opc; \
1351 } while (0)
1353 #define REQUIRE_REG_31(WHICH) \
1354 do { \
1355 if (WHICH != 31) { \
1356 goto invalid_opc; \
1358 } while (0)
1360 #define REQUIRE_FEN \
1361 do { \
1362 if (!(ctx->tbflags & ENV_FLAG_FEN)) { \
1363 goto raise_fen; \
1365 } while (0)
1367 static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
1369 int32_t disp21, disp16, disp12 __attribute__((unused));
1370 uint16_t fn11;
1371 uint8_t opc, ra, rb, rc, fpfn, fn7, lit;
1372 bool islit, real_islit;
1373 TCGv va, vb, vc, tmp, tmp2;
1374 TCGv_i32 t32;
1375 DisasJumpType ret;
1377 /* Decode all instruction fields */
1378 opc = extract32(insn, 26, 6);
1379 ra = extract32(insn, 21, 5);
1380 rb = extract32(insn, 16, 5);
1381 rc = extract32(insn, 0, 5);
1382 real_islit = islit = extract32(insn, 12, 1);
1383 lit = extract32(insn, 13, 8);
1385 disp21 = sextract32(insn, 0, 21) * 4;
1386 disp16 = sextract32(insn, 0, 16);
1387 disp12 = sextract32(insn, 0, 12);
1389 fn11 = extract32(insn, 5, 11);
1390 fpfn = extract32(insn, 5, 6);
1391 fn7 = extract32(insn, 5, 7);
1393 if (rb == 31 && !islit) {
1394 islit = true;
1395 lit = 0;
1398 ret = DISAS_NEXT;
1399 switch (opc) {
1400 case 0x00:
1401 /* CALL_PAL */
1402 ret = gen_call_pal(ctx, insn & 0x03ffffff);
1403 break;
1404 case 0x01:
1405 /* OPC01 */
1406 goto invalid_opc;
1407 case 0x02:
1408 /* OPC02 */
1409 goto invalid_opc;
1410 case 0x03:
1411 /* OPC03 */
1412 goto invalid_opc;
1413 case 0x04:
1414 /* OPC04 */
1415 goto invalid_opc;
1416 case 0x05:
1417 /* OPC05 */
1418 goto invalid_opc;
1419 case 0x06:
1420 /* OPC06 */
1421 goto invalid_opc;
1422 case 0x07:
1423 /* OPC07 */
1424 goto invalid_opc;
1426 case 0x09:
1427 /* LDAH */
1428 disp16 = (uint32_t)disp16 << 16;
1429 /* fall through */
1430 case 0x08:
1431 /* LDA */
1432 va = dest_gpr(ctx, ra);
1433 /* It's worth special-casing immediate loads. */
1434 if (rb == 31) {
1435 tcg_gen_movi_i64(va, disp16);
1436 } else {
1437 tcg_gen_addi_i64(va, load_gpr(ctx, rb), disp16);
1439 break;
1441 case 0x0A:
1442 /* LDBU */
1443 REQUIRE_AMASK(BWX);
1444 gen_load_int(ctx, ra, rb, disp16, MO_UB, 0, 0);
1445 break;
1446 case 0x0B:
1447 /* LDQ_U */
1448 gen_load_int(ctx, ra, rb, disp16, MO_LEUQ, 1, 0);
1449 break;
1450 case 0x0C:
1451 /* LDWU */
1452 REQUIRE_AMASK(BWX);
1453 gen_load_int(ctx, ra, rb, disp16, MO_LEUW, 0, 0);
1454 break;
1455 case 0x0D:
1456 /* STW */
1457 REQUIRE_AMASK(BWX);
1458 gen_store_int(ctx, ra, rb, disp16, MO_LEUW, 0);
1459 break;
1460 case 0x0E:
1461 /* STB */
1462 REQUIRE_AMASK(BWX);
1463 gen_store_int(ctx, ra, rb, disp16, MO_UB, 0);
1464 break;
1465 case 0x0F:
1466 /* STQ_U */
1467 gen_store_int(ctx, ra, rb, disp16, MO_LEUQ, 1);
1468 break;
1470 case 0x10:
1471 vc = dest_gpr(ctx, rc);
1472 vb = load_gpr_lit(ctx, rb, lit, islit);
1474 if (ra == 31) {
1475 if (fn7 == 0x00) {
1476 /* Special case ADDL as SEXTL. */
1477 tcg_gen_ext32s_i64(vc, vb);
1478 break;
1480 if (fn7 == 0x29) {
1481 /* Special case SUBQ as NEGQ. */
1482 tcg_gen_neg_i64(vc, vb);
1483 break;
1487 va = load_gpr(ctx, ra);
1488 switch (fn7) {
1489 case 0x00:
1490 /* ADDL */
1491 tcg_gen_add_i64(vc, va, vb);
1492 tcg_gen_ext32s_i64(vc, vc);
1493 break;
1494 case 0x02:
1495 /* S4ADDL */
1496 tmp = tcg_temp_new();
1497 tcg_gen_shli_i64(tmp, va, 2);
1498 tcg_gen_add_i64(tmp, tmp, vb);
1499 tcg_gen_ext32s_i64(vc, tmp);
1500 break;
1501 case 0x09:
1502 /* SUBL */
1503 tcg_gen_sub_i64(vc, va, vb);
1504 tcg_gen_ext32s_i64(vc, vc);
1505 break;
1506 case 0x0B:
1507 /* S4SUBL */
1508 tmp = tcg_temp_new();
1509 tcg_gen_shli_i64(tmp, va, 2);
1510 tcg_gen_sub_i64(tmp, tmp, vb);
1511 tcg_gen_ext32s_i64(vc, tmp);
1512 break;
1513 case 0x0F:
1514 /* CMPBGE */
1515 if (ra == 31) {
1516 /* Special case 0 >= X as X == 0. */
1517 gen_helper_cmpbe0(vc, vb);
1518 } else {
1519 gen_helper_cmpbge(vc, va, vb);
1521 break;
1522 case 0x12:
1523 /* S8ADDL */
1524 tmp = tcg_temp_new();
1525 tcg_gen_shli_i64(tmp, va, 3);
1526 tcg_gen_add_i64(tmp, tmp, vb);
1527 tcg_gen_ext32s_i64(vc, tmp);
1528 break;
1529 case 0x1B:
1530 /* S8SUBL */
1531 tmp = tcg_temp_new();
1532 tcg_gen_shli_i64(tmp, va, 3);
1533 tcg_gen_sub_i64(tmp, tmp, vb);
1534 tcg_gen_ext32s_i64(vc, tmp);
1535 break;
1536 case 0x1D:
1537 /* CMPULT */
1538 tcg_gen_setcond_i64(TCG_COND_LTU, vc, va, vb);
1539 break;
1540 case 0x20:
1541 /* ADDQ */
1542 tcg_gen_add_i64(vc, va, vb);
1543 break;
1544 case 0x22:
1545 /* S4ADDQ */
1546 tmp = tcg_temp_new();
1547 tcg_gen_shli_i64(tmp, va, 2);
1548 tcg_gen_add_i64(vc, tmp, vb);
1549 break;
1550 case 0x29:
1551 /* SUBQ */
1552 tcg_gen_sub_i64(vc, va, vb);
1553 break;
1554 case 0x2B:
1555 /* S4SUBQ */
1556 tmp = tcg_temp_new();
1557 tcg_gen_shli_i64(tmp, va, 2);
1558 tcg_gen_sub_i64(vc, tmp, vb);
1559 break;
1560 case 0x2D:
1561 /* CMPEQ */
1562 tcg_gen_setcond_i64(TCG_COND_EQ, vc, va, vb);
1563 break;
1564 case 0x32:
1565 /* S8ADDQ */
1566 tmp = tcg_temp_new();
1567 tcg_gen_shli_i64(tmp, va, 3);
1568 tcg_gen_add_i64(vc, tmp, vb);
1569 break;
1570 case 0x3B:
1571 /* S8SUBQ */
1572 tmp = tcg_temp_new();
1573 tcg_gen_shli_i64(tmp, va, 3);
1574 tcg_gen_sub_i64(vc, tmp, vb);
1575 break;
1576 case 0x3D:
1577 /* CMPULE */
1578 tcg_gen_setcond_i64(TCG_COND_LEU, vc, va, vb);
1579 break;
1580 case 0x40:
1581 /* ADDL/V */
1582 tmp = tcg_temp_new();
1583 tcg_gen_ext32s_i64(tmp, va);
1584 tcg_gen_ext32s_i64(vc, vb);
1585 tcg_gen_add_i64(tmp, tmp, vc);
1586 tcg_gen_ext32s_i64(vc, tmp);
1587 gen_helper_check_overflow(tcg_env, vc, tmp);
1588 break;
1589 case 0x49:
1590 /* SUBL/V */
1591 tmp = tcg_temp_new();
1592 tcg_gen_ext32s_i64(tmp, va);
1593 tcg_gen_ext32s_i64(vc, vb);
1594 tcg_gen_sub_i64(tmp, tmp, vc);
1595 tcg_gen_ext32s_i64(vc, tmp);
1596 gen_helper_check_overflow(tcg_env, vc, tmp);
1597 break;
1598 case 0x4D:
1599 /* CMPLT */
1600 tcg_gen_setcond_i64(TCG_COND_LT, vc, va, vb);
1601 break;
1602 case 0x60:
1603 /* ADDQ/V */
1604 tmp = tcg_temp_new();
1605 tmp2 = tcg_temp_new();
1606 tcg_gen_eqv_i64(tmp, va, vb);
1607 tcg_gen_mov_i64(tmp2, va);
1608 tcg_gen_add_i64(vc, va, vb);
1609 tcg_gen_xor_i64(tmp2, tmp2, vc);
1610 tcg_gen_and_i64(tmp, tmp, tmp2);
1611 tcg_gen_shri_i64(tmp, tmp, 63);
1612 tcg_gen_movi_i64(tmp2, 0);
1613 gen_helper_check_overflow(tcg_env, tmp, tmp2);
1614 break;
1615 case 0x69:
1616 /* SUBQ/V */
1617 tmp = tcg_temp_new();
1618 tmp2 = tcg_temp_new();
1619 tcg_gen_xor_i64(tmp, va, vb);
1620 tcg_gen_mov_i64(tmp2, va);
1621 tcg_gen_sub_i64(vc, va, vb);
1622 tcg_gen_xor_i64(tmp2, tmp2, vc);
1623 tcg_gen_and_i64(tmp, tmp, tmp2);
1624 tcg_gen_shri_i64(tmp, tmp, 63);
1625 tcg_gen_movi_i64(tmp2, 0);
1626 gen_helper_check_overflow(tcg_env, tmp, tmp2);
1627 break;
1628 case 0x6D:
1629 /* CMPLE */
1630 tcg_gen_setcond_i64(TCG_COND_LE, vc, va, vb);
1631 break;
1632 default:
1633 goto invalid_opc;
1635 break;
1637 case 0x11:
1638 if (fn7 == 0x20) {
1639 if (rc == 31) {
1640 /* Special case BIS as NOP. */
1641 break;
1643 if (ra == 31) {
1644 /* Special case BIS as MOV. */
1645 vc = dest_gpr(ctx, rc);
1646 if (islit) {
1647 tcg_gen_movi_i64(vc, lit);
1648 } else {
1649 tcg_gen_mov_i64(vc, load_gpr(ctx, rb));
1651 break;
1655 vc = dest_gpr(ctx, rc);
1656 vb = load_gpr_lit(ctx, rb, lit, islit);
1658 if (fn7 == 0x28 && ra == 31) {
1659 /* Special case ORNOT as NOT. */
1660 tcg_gen_not_i64(vc, vb);
1661 break;
1664 va = load_gpr(ctx, ra);
1665 switch (fn7) {
1666 case 0x00:
1667 /* AND */
1668 tcg_gen_and_i64(vc, va, vb);
1669 break;
1670 case 0x08:
1671 /* BIC */
1672 tcg_gen_andc_i64(vc, va, vb);
1673 break;
1674 case 0x14:
1675 /* CMOVLBS */
1676 tcg_gen_movcond_i64(TCG_COND_TSTNE, vc, va, tcg_constant_i64(1),
1677 vb, load_gpr(ctx, rc));
1678 break;
1679 case 0x16:
1680 /* CMOVLBC */
1681 tcg_gen_movcond_i64(TCG_COND_TSTEQ, vc, va, tcg_constant_i64(1),
1682 vb, load_gpr(ctx, rc));
1683 break;
1684 case 0x20:
1685 /* BIS */
1686 tcg_gen_or_i64(vc, va, vb);
1687 break;
1688 case 0x24:
1689 /* CMOVEQ */
1690 tcg_gen_movcond_i64(TCG_COND_EQ, vc, va, load_zero(ctx),
1691 vb, load_gpr(ctx, rc));
1692 break;
1693 case 0x26:
1694 /* CMOVNE */
1695 tcg_gen_movcond_i64(TCG_COND_NE, vc, va, load_zero(ctx),
1696 vb, load_gpr(ctx, rc));
1697 break;
1698 case 0x28:
1699 /* ORNOT */
1700 tcg_gen_orc_i64(vc, va, vb);
1701 break;
1702 case 0x40:
1703 /* XOR */
1704 tcg_gen_xor_i64(vc, va, vb);
1705 break;
1706 case 0x44:
1707 /* CMOVLT */
1708 tcg_gen_movcond_i64(TCG_COND_LT, vc, va, load_zero(ctx),
1709 vb, load_gpr(ctx, rc));
1710 break;
1711 case 0x46:
1712 /* CMOVGE */
1713 tcg_gen_movcond_i64(TCG_COND_GE, vc, va, load_zero(ctx),
1714 vb, load_gpr(ctx, rc));
1715 break;
1716 case 0x48:
1717 /* EQV */
1718 tcg_gen_eqv_i64(vc, va, vb);
1719 break;
1720 case 0x61:
1721 /* AMASK */
1722 REQUIRE_REG_31(ra);
1723 tcg_gen_andi_i64(vc, vb, ~ctx->amask);
1724 break;
1725 case 0x64:
1726 /* CMOVLE */
1727 tcg_gen_movcond_i64(TCG_COND_LE, vc, va, load_zero(ctx),
1728 vb, load_gpr(ctx, rc));
1729 break;
1730 case 0x66:
1731 /* CMOVGT */
1732 tcg_gen_movcond_i64(TCG_COND_GT, vc, va, load_zero(ctx),
1733 vb, load_gpr(ctx, rc));
1734 break;
1735 case 0x6C:
1736 /* IMPLVER */
1737 REQUIRE_REG_31(ra);
1738 tcg_gen_movi_i64(vc, ctx->implver);
1739 break;
1740 default:
1741 goto invalid_opc;
1743 break;
1745 case 0x12:
1746 vc = dest_gpr(ctx, rc);
1747 va = load_gpr(ctx, ra);
1748 switch (fn7) {
1749 case 0x02:
1750 /* MSKBL */
1751 gen_msk_l(ctx, vc, va, rb, islit, lit, 0x01);
1752 break;
1753 case 0x06:
1754 /* EXTBL */
1755 gen_ext_l(ctx, vc, va, rb, islit, lit, 0x01);
1756 break;
1757 case 0x0B:
1758 /* INSBL */
1759 gen_ins_l(ctx, vc, va, rb, islit, lit, 0x01);
1760 break;
1761 case 0x12:
1762 /* MSKWL */
1763 gen_msk_l(ctx, vc, va, rb, islit, lit, 0x03);
1764 break;
1765 case 0x16:
1766 /* EXTWL */
1767 gen_ext_l(ctx, vc, va, rb, islit, lit, 0x03);
1768 break;
1769 case 0x1B:
1770 /* INSWL */
1771 gen_ins_l(ctx, vc, va, rb, islit, lit, 0x03);
1772 break;
1773 case 0x22:
1774 /* MSKLL */
1775 gen_msk_l(ctx, vc, va, rb, islit, lit, 0x0f);
1776 break;
1777 case 0x26:
1778 /* EXTLL */
1779 gen_ext_l(ctx, vc, va, rb, islit, lit, 0x0f);
1780 break;
1781 case 0x2B:
1782 /* INSLL */
1783 gen_ins_l(ctx, vc, va, rb, islit, lit, 0x0f);
1784 break;
1785 case 0x30:
1786 /* ZAP */
1787 if (islit) {
1788 gen_zapnoti(vc, va, ~lit);
1789 } else {
1790 gen_helper_zap(vc, va, load_gpr(ctx, rb));
1792 break;
1793 case 0x31:
1794 /* ZAPNOT */
1795 if (islit) {
1796 gen_zapnoti(vc, va, lit);
1797 } else {
1798 gen_helper_zapnot(vc, va, load_gpr(ctx, rb));
1800 break;
1801 case 0x32:
1802 /* MSKQL */
1803 gen_msk_l(ctx, vc, va, rb, islit, lit, 0xff);
1804 break;
1805 case 0x34:
1806 /* SRL */
1807 if (islit) {
1808 tcg_gen_shri_i64(vc, va, lit & 0x3f);
1809 } else {
1810 tmp = tcg_temp_new();
1811 vb = load_gpr(ctx, rb);
1812 tcg_gen_andi_i64(tmp, vb, 0x3f);
1813 tcg_gen_shr_i64(vc, va, tmp);
1815 break;
1816 case 0x36:
1817 /* EXTQL */
1818 gen_ext_l(ctx, vc, va, rb, islit, lit, 0xff);
1819 break;
1820 case 0x39:
1821 /* SLL */
1822 if (islit) {
1823 tcg_gen_shli_i64(vc, va, lit & 0x3f);
1824 } else {
1825 tmp = tcg_temp_new();
1826 vb = load_gpr(ctx, rb);
1827 tcg_gen_andi_i64(tmp, vb, 0x3f);
1828 tcg_gen_shl_i64(vc, va, tmp);
1830 break;
1831 case 0x3B:
1832 /* INSQL */
1833 gen_ins_l(ctx, vc, va, rb, islit, lit, 0xff);
1834 break;
1835 case 0x3C:
1836 /* SRA */
1837 if (islit) {
1838 tcg_gen_sari_i64(vc, va, lit & 0x3f);
1839 } else {
1840 tmp = tcg_temp_new();
1841 vb = load_gpr(ctx, rb);
1842 tcg_gen_andi_i64(tmp, vb, 0x3f);
1843 tcg_gen_sar_i64(vc, va, tmp);
1845 break;
1846 case 0x52:
1847 /* MSKWH */
1848 gen_msk_h(ctx, vc, va, rb, islit, lit, 0x03);
1849 break;
1850 case 0x57:
1851 /* INSWH */
1852 gen_ins_h(ctx, vc, va, rb, islit, lit, 0x03);
1853 break;
1854 case 0x5A:
1855 /* EXTWH */
1856 gen_ext_h(ctx, vc, va, rb, islit, lit, 0x03);
1857 break;
1858 case 0x62:
1859 /* MSKLH */
1860 gen_msk_h(ctx, vc, va, rb, islit, lit, 0x0f);
1861 break;
1862 case 0x67:
1863 /* INSLH */
1864 gen_ins_h(ctx, vc, va, rb, islit, lit, 0x0f);
1865 break;
1866 case 0x6A:
1867 /* EXTLH */
1868 gen_ext_h(ctx, vc, va, rb, islit, lit, 0x0f);
1869 break;
1870 case 0x72:
1871 /* MSKQH */
1872 gen_msk_h(ctx, vc, va, rb, islit, lit, 0xff);
1873 break;
1874 case 0x77:
1875 /* INSQH */
1876 gen_ins_h(ctx, vc, va, rb, islit, lit, 0xff);
1877 break;
1878 case 0x7A:
1879 /* EXTQH */
1880 gen_ext_h(ctx, vc, va, rb, islit, lit, 0xff);
1881 break;
1882 default:
1883 goto invalid_opc;
1885 break;
1887 case 0x13:
1888 vc = dest_gpr(ctx, rc);
1889 vb = load_gpr_lit(ctx, rb, lit, islit);
1890 va = load_gpr(ctx, ra);
1891 switch (fn7) {
1892 case 0x00:
1893 /* MULL */
1894 tcg_gen_mul_i64(vc, va, vb);
1895 tcg_gen_ext32s_i64(vc, vc);
1896 break;
1897 case 0x20:
1898 /* MULQ */
1899 tcg_gen_mul_i64(vc, va, vb);
1900 break;
1901 case 0x30:
1902 /* UMULH */
1903 tmp = tcg_temp_new();
1904 tcg_gen_mulu2_i64(tmp, vc, va, vb);
1905 break;
1906 case 0x40:
1907 /* MULL/V */
1908 tmp = tcg_temp_new();
1909 tcg_gen_ext32s_i64(tmp, va);
1910 tcg_gen_ext32s_i64(vc, vb);
1911 tcg_gen_mul_i64(tmp, tmp, vc);
1912 tcg_gen_ext32s_i64(vc, tmp);
1913 gen_helper_check_overflow(tcg_env, vc, tmp);
1914 break;
1915 case 0x60:
1916 /* MULQ/V */
1917 tmp = tcg_temp_new();
1918 tmp2 = tcg_temp_new();
1919 tcg_gen_muls2_i64(vc, tmp, va, vb);
1920 tcg_gen_sari_i64(tmp2, vc, 63);
1921 gen_helper_check_overflow(tcg_env, tmp, tmp2);
1922 break;
1923 default:
1924 goto invalid_opc;
1926 break;
1928 case 0x14:
1929 REQUIRE_AMASK(FIX);
1930 vc = dest_fpr(ctx, rc);
1931 switch (fpfn) { /* fn11 & 0x3F */
1932 case 0x04:
1933 /* ITOFS */
1934 REQUIRE_REG_31(rb);
1935 REQUIRE_FEN;
1936 t32 = tcg_temp_new_i32();
1937 va = load_gpr(ctx, ra);
1938 tcg_gen_extrl_i64_i32(t32, va);
1939 gen_helper_memory_to_s(vc, t32);
1940 break;
1941 case 0x0A:
1942 /* SQRTF */
1943 REQUIRE_REG_31(ra);
1944 REQUIRE_FEN;
1945 vb = load_fpr(ctx, rb);
1946 gen_helper_sqrtf(vc, tcg_env, vb);
1947 break;
1948 case 0x0B:
1949 /* SQRTS */
1950 REQUIRE_REG_31(ra);
1951 REQUIRE_FEN;
1952 gen_sqrts(ctx, rb, rc, fn11);
1953 break;
1954 case 0x14:
1955 /* ITOFF */
1956 REQUIRE_REG_31(rb);
1957 REQUIRE_FEN;
1958 t32 = tcg_temp_new_i32();
1959 va = load_gpr(ctx, ra);
1960 tcg_gen_extrl_i64_i32(t32, va);
1961 gen_helper_memory_to_f(vc, t32);
1962 break;
1963 case 0x24:
1964 /* ITOFT */
1965 REQUIRE_REG_31(rb);
1966 REQUIRE_FEN;
1967 va = load_gpr(ctx, ra);
1968 tcg_gen_mov_i64(vc, va);
1969 break;
1970 case 0x2A:
1971 /* SQRTG */
1972 REQUIRE_REG_31(ra);
1973 REQUIRE_FEN;
1974 vb = load_fpr(ctx, rb);
1975 gen_helper_sqrtg(vc, tcg_env, vb);
1976 break;
1977 case 0x02B:
1978 /* SQRTT */
1979 REQUIRE_REG_31(ra);
1980 REQUIRE_FEN;
1981 gen_sqrtt(ctx, rb, rc, fn11);
1982 break;
1983 default:
1984 goto invalid_opc;
1986 break;
1988 case 0x15:
1989 /* VAX floating point */
1990 /* XXX: rounding mode and trap are ignored (!) */
1991 vc = dest_fpr(ctx, rc);
1992 vb = load_fpr(ctx, rb);
1993 va = load_fpr(ctx, ra);
1994 switch (fpfn) { /* fn11 & 0x3F */
1995 case 0x00:
1996 /* ADDF */
1997 REQUIRE_FEN;
1998 gen_helper_addf(vc, tcg_env, va, vb);
1999 break;
2000 case 0x01:
2001 /* SUBF */
2002 REQUIRE_FEN;
2003 gen_helper_subf(vc, tcg_env, va, vb);
2004 break;
2005 case 0x02:
2006 /* MULF */
2007 REQUIRE_FEN;
2008 gen_helper_mulf(vc, tcg_env, va, vb);
2009 break;
2010 case 0x03:
2011 /* DIVF */
2012 REQUIRE_FEN;
2013 gen_helper_divf(vc, tcg_env, va, vb);
2014 break;
2015 case 0x1E:
2016 /* CVTDG -- TODO */
2017 REQUIRE_REG_31(ra);
2018 goto invalid_opc;
2019 case 0x20:
2020 /* ADDG */
2021 REQUIRE_FEN;
2022 gen_helper_addg(vc, tcg_env, va, vb);
2023 break;
2024 case 0x21:
2025 /* SUBG */
2026 REQUIRE_FEN;
2027 gen_helper_subg(vc, tcg_env, va, vb);
2028 break;
2029 case 0x22:
2030 /* MULG */
2031 REQUIRE_FEN;
2032 gen_helper_mulg(vc, tcg_env, va, vb);
2033 break;
2034 case 0x23:
2035 /* DIVG */
2036 REQUIRE_FEN;
2037 gen_helper_divg(vc, tcg_env, va, vb);
2038 break;
2039 case 0x25:
2040 /* CMPGEQ */
2041 REQUIRE_FEN;
2042 gen_helper_cmpgeq(vc, tcg_env, va, vb);
2043 break;
2044 case 0x26:
2045 /* CMPGLT */
2046 REQUIRE_FEN;
2047 gen_helper_cmpglt(vc, tcg_env, va, vb);
2048 break;
2049 case 0x27:
2050 /* CMPGLE */
2051 REQUIRE_FEN;
2052 gen_helper_cmpgle(vc, tcg_env, va, vb);
2053 break;
2054 case 0x2C:
2055 /* CVTGF */
2056 REQUIRE_REG_31(ra);
2057 REQUIRE_FEN;
2058 gen_helper_cvtgf(vc, tcg_env, vb);
2059 break;
2060 case 0x2D:
2061 /* CVTGD -- TODO */
2062 REQUIRE_REG_31(ra);
2063 goto invalid_opc;
2064 case 0x2F:
2065 /* CVTGQ */
2066 REQUIRE_REG_31(ra);
2067 REQUIRE_FEN;
2068 gen_helper_cvtgq(vc, tcg_env, vb);
2069 break;
2070 case 0x3C:
2071 /* CVTQF */
2072 REQUIRE_REG_31(ra);
2073 REQUIRE_FEN;
2074 gen_helper_cvtqf(vc, tcg_env, vb);
2075 break;
2076 case 0x3E:
2077 /* CVTQG */
2078 REQUIRE_REG_31(ra);
2079 REQUIRE_FEN;
2080 gen_helper_cvtqg(vc, tcg_env, vb);
2081 break;
2082 default:
2083 goto invalid_opc;
2085 break;
2087 case 0x16:
2088 /* IEEE floating-point */
2089 switch (fpfn) { /* fn11 & 0x3F */
2090 case 0x00:
2091 /* ADDS */
2092 REQUIRE_FEN;
2093 gen_adds(ctx, ra, rb, rc, fn11);
2094 break;
2095 case 0x01:
2096 /* SUBS */
2097 REQUIRE_FEN;
2098 gen_subs(ctx, ra, rb, rc, fn11);
2099 break;
2100 case 0x02:
2101 /* MULS */
2102 REQUIRE_FEN;
2103 gen_muls(ctx, ra, rb, rc, fn11);
2104 break;
2105 case 0x03:
2106 /* DIVS */
2107 REQUIRE_FEN;
2108 gen_divs(ctx, ra, rb, rc, fn11);
2109 break;
2110 case 0x20:
2111 /* ADDT */
2112 REQUIRE_FEN;
2113 gen_addt(ctx, ra, rb, rc, fn11);
2114 break;
2115 case 0x21:
2116 /* SUBT */
2117 REQUIRE_FEN;
2118 gen_subt(ctx, ra, rb, rc, fn11);
2119 break;
2120 case 0x22:
2121 /* MULT */
2122 REQUIRE_FEN;
2123 gen_mult(ctx, ra, rb, rc, fn11);
2124 break;
2125 case 0x23:
2126 /* DIVT */
2127 REQUIRE_FEN;
2128 gen_divt(ctx, ra, rb, rc, fn11);
2129 break;
2130 case 0x24:
2131 /* CMPTUN */
2132 REQUIRE_FEN;
2133 gen_cmptun(ctx, ra, rb, rc, fn11);
2134 break;
2135 case 0x25:
2136 /* CMPTEQ */
2137 REQUIRE_FEN;
2138 gen_cmpteq(ctx, ra, rb, rc, fn11);
2139 break;
2140 case 0x26:
2141 /* CMPTLT */
2142 REQUIRE_FEN;
2143 gen_cmptlt(ctx, ra, rb, rc, fn11);
2144 break;
2145 case 0x27:
2146 /* CMPTLE */
2147 REQUIRE_FEN;
2148 gen_cmptle(ctx, ra, rb, rc, fn11);
2149 break;
2150 case 0x2C:
2151 REQUIRE_REG_31(ra);
2152 REQUIRE_FEN;
2153 if (fn11 == 0x2AC || fn11 == 0x6AC) {
2154 /* CVTST */
2155 gen_cvtst(ctx, rb, rc, fn11);
2156 } else {
2157 /* CVTTS */
2158 gen_cvtts(ctx, rb, rc, fn11);
2160 break;
2161 case 0x2F:
2162 /* CVTTQ */
2163 REQUIRE_REG_31(ra);
2164 REQUIRE_FEN;
2165 gen_cvttq(ctx, rb, rc, fn11);
2166 break;
2167 case 0x3C:
2168 /* CVTQS */
2169 REQUIRE_REG_31(ra);
2170 REQUIRE_FEN;
2171 gen_cvtqs(ctx, rb, rc, fn11);
2172 break;
2173 case 0x3E:
2174 /* CVTQT */
2175 REQUIRE_REG_31(ra);
2176 REQUIRE_FEN;
2177 gen_cvtqt(ctx, rb, rc, fn11);
2178 break;
2179 default:
2180 goto invalid_opc;
2182 break;
2184 case 0x17:
2185 switch (fn11) {
2186 case 0x010:
2187 /* CVTLQ */
2188 REQUIRE_REG_31(ra);
2189 REQUIRE_FEN;
2190 vc = dest_fpr(ctx, rc);
2191 vb = load_fpr(ctx, rb);
2192 gen_cvtlq(vc, vb);
2193 break;
2194 case 0x020:
2195 /* CPYS */
2196 REQUIRE_FEN;
2197 if (rc == 31) {
2198 /* Special case CPYS as FNOP. */
2199 } else {
2200 vc = dest_fpr(ctx, rc);
2201 va = load_fpr(ctx, ra);
2202 if (ra == rb) {
2203 /* Special case CPYS as FMOV. */
2204 tcg_gen_mov_i64(vc, va);
2205 } else {
2206 vb = load_fpr(ctx, rb);
2207 gen_cpy_mask(vc, va, vb, 0, 0x8000000000000000ULL);
2210 break;
2211 case 0x021:
2212 /* CPYSN */
2213 REQUIRE_FEN;
2214 vc = dest_fpr(ctx, rc);
2215 vb = load_fpr(ctx, rb);
2216 va = load_fpr(ctx, ra);
2217 gen_cpy_mask(vc, va, vb, 1, 0x8000000000000000ULL);
2218 break;
2219 case 0x022:
2220 /* CPYSE */
2221 REQUIRE_FEN;
2222 vc = dest_fpr(ctx, rc);
2223 vb = load_fpr(ctx, rb);
2224 va = load_fpr(ctx, ra);
2225 gen_cpy_mask(vc, va, vb, 0, 0xFFF0000000000000ULL);
2226 break;
2227 case 0x024:
2228 /* MT_FPCR */
2229 REQUIRE_FEN;
2230 va = load_fpr(ctx, ra);
2231 gen_helper_store_fpcr(tcg_env, va);
2232 if (ctx->tb_rm == QUAL_RM_D) {
2233 /* Re-do the copy of the rounding mode to fp_status
2234 the next time we use dynamic rounding. */
2235 ctx->tb_rm = -1;
2237 break;
2238 case 0x025:
2239 /* MF_FPCR */
2240 REQUIRE_FEN;
2241 va = dest_fpr(ctx, ra);
2242 gen_helper_load_fpcr(va, tcg_env);
2243 break;
2244 case 0x02A:
2245 /* FCMOVEQ */
2246 REQUIRE_FEN;
2247 gen_fcmov(ctx, TCG_COND_EQ, ra, rb, rc);
2248 break;
2249 case 0x02B:
2250 /* FCMOVNE */
2251 REQUIRE_FEN;
2252 gen_fcmov(ctx, TCG_COND_NE, ra, rb, rc);
2253 break;
2254 case 0x02C:
2255 /* FCMOVLT */
2256 REQUIRE_FEN;
2257 gen_fcmov(ctx, TCG_COND_LT, ra, rb, rc);
2258 break;
2259 case 0x02D:
2260 /* FCMOVGE */
2261 REQUIRE_FEN;
2262 gen_fcmov(ctx, TCG_COND_GE, ra, rb, rc);
2263 break;
2264 case 0x02E:
2265 /* FCMOVLE */
2266 REQUIRE_FEN;
2267 gen_fcmov(ctx, TCG_COND_LE, ra, rb, rc);
2268 break;
2269 case 0x02F:
2270 /* FCMOVGT */
2271 REQUIRE_FEN;
2272 gen_fcmov(ctx, TCG_COND_GT, ra, rb, rc);
2273 break;
2274 case 0x030: /* CVTQL */
2275 case 0x130: /* CVTQL/V */
2276 case 0x530: /* CVTQL/SV */
2277 REQUIRE_REG_31(ra);
2278 REQUIRE_FEN;
2279 vc = dest_fpr(ctx, rc);
2280 vb = load_fpr(ctx, rb);
2281 gen_helper_cvtql(vc, tcg_env, vb);
2282 gen_fp_exc_raise(rc, fn11);
2283 break;
2284 default:
2285 goto invalid_opc;
2287 break;
2289 case 0x18:
2290 switch ((uint16_t)disp16) {
2291 case 0x0000:
2292 /* TRAPB */
2293 /* No-op. */
2294 break;
2295 case 0x0400:
2296 /* EXCB */
2297 /* No-op. */
2298 break;
2299 case 0x4000:
2300 /* MB */
2301 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
2302 break;
2303 case 0x4400:
2304 /* WMB */
2305 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
2306 break;
2307 case 0x8000:
2308 /* FETCH */
2309 /* No-op */
2310 break;
2311 case 0xA000:
2312 /* FETCH_M */
2313 /* No-op */
2314 break;
2315 case 0xC000:
2316 /* RPCC */
2317 va = dest_gpr(ctx, ra);
2318 if (translator_io_start(&ctx->base)) {
2319 ret = DISAS_PC_STALE;
2321 gen_helper_load_pcc(va, tcg_env);
2322 break;
2323 case 0xE000:
2324 /* RC */
2325 gen_rx(ctx, ra, 0);
2326 break;
2327 case 0xE800:
2328 /* ECB */
2329 break;
2330 case 0xF000:
2331 /* RS */
2332 gen_rx(ctx, ra, 1);
2333 break;
2334 case 0xF800:
2335 /* WH64 */
2336 /* No-op */
2337 break;
2338 case 0xFC00:
2339 /* WH64EN */
2340 /* No-op */
2341 break;
2342 default:
2343 goto invalid_opc;
2345 break;
2347 case 0x19:
2348 /* HW_MFPR (PALcode) */
2349 #ifndef CONFIG_USER_ONLY
2350 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
2351 va = dest_gpr(ctx, ra);
2352 ret = gen_mfpr(ctx, va, insn & 0xffff);
2353 break;
2354 #else
2355 goto invalid_opc;
2356 #endif
2358 case 0x1A:
2359 /* JMP, JSR, RET, JSR_COROUTINE. These only differ by the branch
2360 prediction stack action, which of course we don't implement. */
2361 vb = load_gpr(ctx, rb);
2362 tcg_gen_andi_i64(cpu_pc, vb, ~3);
2363 if (ra != 31) {
2364 tcg_gen_movi_i64(ctx->ir[ra], ctx->base.pc_next);
2366 ret = DISAS_PC_UPDATED;
2367 break;
2369 case 0x1B:
2370 /* HW_LD (PALcode) */
2371 #ifndef CONFIG_USER_ONLY
2372 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
2374 TCGv addr = tcg_temp_new();
2375 vb = load_gpr(ctx, rb);
2376 va = dest_gpr(ctx, ra);
2378 tcg_gen_addi_i64(addr, vb, disp12);
2379 switch ((insn >> 12) & 0xF) {
2380 case 0x0:
2381 /* Longword physical access (hw_ldl/p) */
2382 tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL | MO_ALIGN);
2383 break;
2384 case 0x1:
2385 /* Quadword physical access (hw_ldq/p) */
2386 tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN);
2387 break;
2388 case 0x2:
2389 /* Longword physical access with lock (hw_ldl_l/p) */
2390 tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL | MO_ALIGN);
2391 tcg_gen_mov_i64(cpu_lock_addr, addr);
2392 tcg_gen_mov_i64(cpu_lock_value, va);
2393 break;
2394 case 0x3:
2395 /* Quadword physical access with lock (hw_ldq_l/p) */
2396 tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN);
2397 tcg_gen_mov_i64(cpu_lock_addr, addr);
2398 tcg_gen_mov_i64(cpu_lock_value, va);
2399 break;
2400 case 0x4:
2401 /* Longword virtual PTE fetch (hw_ldl/v) */
2402 goto invalid_opc;
2403 case 0x5:
2404 /* Quadword virtual PTE fetch (hw_ldq/v) */
2405 goto invalid_opc;
2406 break;
2407 case 0x6:
2408 /* Invalid */
2409 goto invalid_opc;
2410 case 0x7:
2411 /* Invaliid */
2412 goto invalid_opc;
2413 case 0x8:
2414 /* Longword virtual access (hw_ldl) */
2415 goto invalid_opc;
2416 case 0x9:
2417 /* Quadword virtual access (hw_ldq) */
2418 goto invalid_opc;
2419 case 0xA:
2420 /* Longword virtual access with protection check (hw_ldl/w) */
2421 tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX,
2422 MO_LESL | MO_ALIGN);
2423 break;
2424 case 0xB:
2425 /* Quadword virtual access with protection check (hw_ldq/w) */
2426 tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX,
2427 MO_LEUQ | MO_ALIGN);
2428 break;
2429 case 0xC:
2430 /* Longword virtual access with alt access mode (hw_ldl/a)*/
2431 goto invalid_opc;
2432 case 0xD:
2433 /* Quadword virtual access with alt access mode (hw_ldq/a) */
2434 goto invalid_opc;
2435 case 0xE:
2436 /* Longword virtual access with alternate access mode and
2437 protection checks (hw_ldl/wa) */
2438 tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX,
2439 MO_LESL | MO_ALIGN);
2440 break;
2441 case 0xF:
2442 /* Quadword virtual access with alternate access mode and
2443 protection checks (hw_ldq/wa) */
2444 tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX,
2445 MO_LEUQ | MO_ALIGN);
2446 break;
2448 break;
2450 #else
2451 goto invalid_opc;
2452 #endif
2454 case 0x1C:
2455 vc = dest_gpr(ctx, rc);
2456 if (fn7 == 0x70) {
2457 /* FTOIT */
2458 REQUIRE_AMASK(FIX);
2459 REQUIRE_REG_31(rb);
2460 va = load_fpr(ctx, ra);
2461 tcg_gen_mov_i64(vc, va);
2462 break;
2463 } else if (fn7 == 0x78) {
2464 /* FTOIS */
2465 REQUIRE_AMASK(FIX);
2466 REQUIRE_REG_31(rb);
2467 t32 = tcg_temp_new_i32();
2468 va = load_fpr(ctx, ra);
2469 gen_helper_s_to_memory(t32, va);
2470 tcg_gen_ext_i32_i64(vc, t32);
2471 break;
2474 vb = load_gpr_lit(ctx, rb, lit, islit);
2475 switch (fn7) {
2476 case 0x00:
2477 /* SEXTB */
2478 REQUIRE_AMASK(BWX);
2479 REQUIRE_REG_31(ra);
2480 tcg_gen_ext8s_i64(vc, vb);
2481 break;
2482 case 0x01:
2483 /* SEXTW */
2484 REQUIRE_AMASK(BWX);
2485 REQUIRE_REG_31(ra);
2486 tcg_gen_ext16s_i64(vc, vb);
2487 break;
2488 case 0x30:
2489 /* CTPOP */
2490 REQUIRE_AMASK(CIX);
2491 REQUIRE_REG_31(ra);
2492 REQUIRE_NO_LIT;
2493 tcg_gen_ctpop_i64(vc, vb);
2494 break;
2495 case 0x31:
2496 /* PERR */
2497 REQUIRE_AMASK(MVI);
2498 REQUIRE_NO_LIT;
2499 va = load_gpr(ctx, ra);
2500 gen_helper_perr(vc, va, vb);
2501 break;
2502 case 0x32:
2503 /* CTLZ */
2504 REQUIRE_AMASK(CIX);
2505 REQUIRE_REG_31(ra);
2506 REQUIRE_NO_LIT;
2507 tcg_gen_clzi_i64(vc, vb, 64);
2508 break;
2509 case 0x33:
2510 /* CTTZ */
2511 REQUIRE_AMASK(CIX);
2512 REQUIRE_REG_31(ra);
2513 REQUIRE_NO_LIT;
2514 tcg_gen_ctzi_i64(vc, vb, 64);
2515 break;
2516 case 0x34:
2517 /* UNPKBW */
2518 REQUIRE_AMASK(MVI);
2519 REQUIRE_REG_31(ra);
2520 REQUIRE_NO_LIT;
2521 gen_helper_unpkbw(vc, vb);
2522 break;
2523 case 0x35:
2524 /* UNPKBL */
2525 REQUIRE_AMASK(MVI);
2526 REQUIRE_REG_31(ra);
2527 REQUIRE_NO_LIT;
2528 gen_helper_unpkbl(vc, vb);
2529 break;
2530 case 0x36:
2531 /* PKWB */
2532 REQUIRE_AMASK(MVI);
2533 REQUIRE_REG_31(ra);
2534 REQUIRE_NO_LIT;
2535 gen_helper_pkwb(vc, vb);
2536 break;
2537 case 0x37:
2538 /* PKLB */
2539 REQUIRE_AMASK(MVI);
2540 REQUIRE_REG_31(ra);
2541 REQUIRE_NO_LIT;
2542 gen_helper_pklb(vc, vb);
2543 break;
2544 case 0x38:
2545 /* MINSB8 */
2546 REQUIRE_AMASK(MVI);
2547 va = load_gpr(ctx, ra);
2548 gen_helper_minsb8(vc, va, vb);
2549 break;
2550 case 0x39:
2551 /* MINSW4 */
2552 REQUIRE_AMASK(MVI);
2553 va = load_gpr(ctx, ra);
2554 gen_helper_minsw4(vc, va, vb);
2555 break;
2556 case 0x3A:
2557 /* MINUB8 */
2558 REQUIRE_AMASK(MVI);
2559 va = load_gpr(ctx, ra);
2560 gen_helper_minub8(vc, va, vb);
2561 break;
2562 case 0x3B:
2563 /* MINUW4 */
2564 REQUIRE_AMASK(MVI);
2565 va = load_gpr(ctx, ra);
2566 gen_helper_minuw4(vc, va, vb);
2567 break;
2568 case 0x3C:
2569 /* MAXUB8 */
2570 REQUIRE_AMASK(MVI);
2571 va = load_gpr(ctx, ra);
2572 gen_helper_maxub8(vc, va, vb);
2573 break;
2574 case 0x3D:
2575 /* MAXUW4 */
2576 REQUIRE_AMASK(MVI);
2577 va = load_gpr(ctx, ra);
2578 gen_helper_maxuw4(vc, va, vb);
2579 break;
2580 case 0x3E:
2581 /* MAXSB8 */
2582 REQUIRE_AMASK(MVI);
2583 va = load_gpr(ctx, ra);
2584 gen_helper_maxsb8(vc, va, vb);
2585 break;
2586 case 0x3F:
2587 /* MAXSW4 */
2588 REQUIRE_AMASK(MVI);
2589 va = load_gpr(ctx, ra);
2590 gen_helper_maxsw4(vc, va, vb);
2591 break;
2592 default:
2593 goto invalid_opc;
2595 break;
2597 case 0x1D:
2598 /* HW_MTPR (PALcode) */
2599 #ifndef CONFIG_USER_ONLY
2600 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
2601 vb = load_gpr(ctx, rb);
2602 ret = gen_mtpr(ctx, vb, insn & 0xffff);
2603 break;
2604 #else
2605 goto invalid_opc;
2606 #endif
2608 case 0x1E:
2609 /* HW_RET (PALcode) */
2610 #ifndef CONFIG_USER_ONLY
2611 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
2612 if (rb == 31) {
2613 /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
2614 address from EXC_ADDR. This turns out to be useful for our
2615 emulation PALcode, so continue to accept it. */
2616 vb = dest_sink(ctx);
2617 tcg_gen_ld_i64(vb, tcg_env, offsetof(CPUAlphaState, exc_addr));
2618 } else {
2619 vb = load_gpr(ctx, rb);
2621 tcg_gen_movi_i64(cpu_lock_addr, -1);
2622 st_flag_byte(load_zero(ctx), ENV_FLAG_RX_SHIFT);
2623 tmp = tcg_temp_new();
2624 tcg_gen_andi_i64(tmp, vb, 1);
2625 st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT);
2626 tcg_gen_andi_i64(cpu_pc, vb, ~3);
2627 /* Allow interrupts to be recognized right away. */
2628 ret = DISAS_PC_UPDATED_NOCHAIN;
2629 break;
2630 #else
2631 goto invalid_opc;
2632 #endif
2634 case 0x1F:
2635 /* HW_ST (PALcode) */
2636 #ifndef CONFIG_USER_ONLY
2637 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
2639 switch ((insn >> 12) & 0xF) {
2640 case 0x0:
2641 /* Longword physical access */
2642 va = load_gpr(ctx, ra);
2643 vb = load_gpr(ctx, rb);
2644 tmp = tcg_temp_new();
2645 tcg_gen_addi_i64(tmp, vb, disp12);
2646 tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LESL | MO_ALIGN);
2647 break;
2648 case 0x1:
2649 /* Quadword physical access */
2650 va = load_gpr(ctx, ra);
2651 vb = load_gpr(ctx, rb);
2652 tmp = tcg_temp_new();
2653 tcg_gen_addi_i64(tmp, vb, disp12);
2654 tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN);
2655 break;
2656 case 0x2:
2657 /* Longword physical access with lock */
2658 ret = gen_store_conditional(ctx, ra, rb, disp12,
2659 MMU_PHYS_IDX, MO_LESL | MO_ALIGN);
2660 break;
2661 case 0x3:
2662 /* Quadword physical access with lock */
2663 ret = gen_store_conditional(ctx, ra, rb, disp12,
2664 MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN);
2665 break;
2666 case 0x4:
2667 /* Longword virtual access */
2668 goto invalid_opc;
2669 case 0x5:
2670 /* Quadword virtual access */
2671 goto invalid_opc;
2672 case 0x6:
2673 /* Invalid */
2674 goto invalid_opc;
2675 case 0x7:
2676 /* Invalid */
2677 goto invalid_opc;
2678 case 0x8:
2679 /* Invalid */
2680 goto invalid_opc;
2681 case 0x9:
2682 /* Invalid */
2683 goto invalid_opc;
2684 case 0xA:
2685 /* Invalid */
2686 goto invalid_opc;
2687 case 0xB:
2688 /* Invalid */
2689 goto invalid_opc;
2690 case 0xC:
2691 /* Longword virtual access with alternate access mode */
2692 goto invalid_opc;
2693 case 0xD:
2694 /* Quadword virtual access with alternate access mode */
2695 goto invalid_opc;
2696 case 0xE:
2697 /* Invalid */
2698 goto invalid_opc;
2699 case 0xF:
2700 /* Invalid */
2701 goto invalid_opc;
2703 break;
2705 #else
2706 goto invalid_opc;
2707 #endif
2708 case 0x20:
2709 /* LDF */
2710 REQUIRE_FEN;
2711 gen_load_fp(ctx, ra, rb, disp16, gen_ldf);
2712 break;
2713 case 0x21:
2714 /* LDG */
2715 REQUIRE_FEN;
2716 gen_load_fp(ctx, ra, rb, disp16, gen_ldg);
2717 break;
2718 case 0x22:
2719 /* LDS */
2720 REQUIRE_FEN;
2721 gen_load_fp(ctx, ra, rb, disp16, gen_lds);
2722 break;
2723 case 0x23:
2724 /* LDT */
2725 REQUIRE_FEN;
2726 gen_load_fp(ctx, ra, rb, disp16, gen_ldt);
2727 break;
2728 case 0x24:
2729 /* STF */
2730 REQUIRE_FEN;
2731 gen_store_fp(ctx, ra, rb, disp16, gen_stf);
2732 break;
2733 case 0x25:
2734 /* STG */
2735 REQUIRE_FEN;
2736 gen_store_fp(ctx, ra, rb, disp16, gen_stg);
2737 break;
2738 case 0x26:
2739 /* STS */
2740 REQUIRE_FEN;
2741 gen_store_fp(ctx, ra, rb, disp16, gen_sts);
2742 break;
2743 case 0x27:
2744 /* STT */
2745 REQUIRE_FEN;
2746 gen_store_fp(ctx, ra, rb, disp16, gen_stt);
2747 break;
2748 case 0x28:
2749 /* LDL */
2750 gen_load_int(ctx, ra, rb, disp16, MO_LESL, 0, 0);
2751 break;
2752 case 0x29:
2753 /* LDQ */
2754 gen_load_int(ctx, ra, rb, disp16, MO_LEUQ, 0, 0);
2755 break;
2756 case 0x2A:
2757 /* LDL_L */
2758 gen_load_int(ctx, ra, rb, disp16, MO_LESL | MO_ALIGN, 0, 1);
2759 break;
2760 case 0x2B:
2761 /* LDQ_L */
2762 gen_load_int(ctx, ra, rb, disp16, MO_LEUQ | MO_ALIGN, 0, 1);
2763 break;
2764 case 0x2C:
2765 /* STL */
2766 gen_store_int(ctx, ra, rb, disp16, MO_LEUL, 0);
2767 break;
2768 case 0x2D:
2769 /* STQ */
2770 gen_store_int(ctx, ra, rb, disp16, MO_LEUQ, 0);
2771 break;
2772 case 0x2E:
2773 /* STL_C */
2774 ret = gen_store_conditional(ctx, ra, rb, disp16,
2775 ctx->mem_idx, MO_LESL | MO_ALIGN);
2776 break;
2777 case 0x2F:
2778 /* STQ_C */
2779 ret = gen_store_conditional(ctx, ra, rb, disp16,
2780 ctx->mem_idx, MO_LEUQ | MO_ALIGN);
2781 break;
2782 case 0x30:
2783 /* BR */
2784 ret = gen_bdirect(ctx, ra, disp21);
2785 break;
2786 case 0x31: /* FBEQ */
2787 REQUIRE_FEN;
2788 ret = gen_fbcond(ctx, TCG_COND_EQ, ra, disp21);
2789 break;
2790 case 0x32: /* FBLT */
2791 REQUIRE_FEN;
2792 ret = gen_fbcond(ctx, TCG_COND_LT, ra, disp21);
2793 break;
2794 case 0x33: /* FBLE */
2795 REQUIRE_FEN;
2796 ret = gen_fbcond(ctx, TCG_COND_LE, ra, disp21);
2797 break;
2798 case 0x34:
2799 /* BSR */
2800 ret = gen_bdirect(ctx, ra, disp21);
2801 break;
2802 case 0x35: /* FBNE */
2803 REQUIRE_FEN;
2804 ret = gen_fbcond(ctx, TCG_COND_NE, ra, disp21);
2805 break;
2806 case 0x36: /* FBGE */
2807 REQUIRE_FEN;
2808 ret = gen_fbcond(ctx, TCG_COND_GE, ra, disp21);
2809 break;
2810 case 0x37: /* FBGT */
2811 REQUIRE_FEN;
2812 ret = gen_fbcond(ctx, TCG_COND_GT, ra, disp21);
2813 break;
2814 case 0x38:
2815 /* BLBC */
2816 ret = gen_bcond(ctx, TCG_COND_TSTEQ, ra, disp21);
2817 break;
2818 case 0x39:
2819 /* BEQ */
2820 ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21);
2821 break;
2822 case 0x3A:
2823 /* BLT */
2824 ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21);
2825 break;
2826 case 0x3B:
2827 /* BLE */
2828 ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21);
2829 break;
2830 case 0x3C:
2831 /* BLBS */
2832 ret = gen_bcond(ctx, TCG_COND_TSTNE, ra, disp21);
2833 break;
2834 case 0x3D:
2835 /* BNE */
2836 ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21);
2837 break;
2838 case 0x3E:
2839 /* BGE */
2840 ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21);
2841 break;
2842 case 0x3F:
2843 /* BGT */
2844 ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21);
2845 break;
2846 invalid_opc:
2847 ret = gen_invalid(ctx);
2848 break;
2849 raise_fen:
2850 ret = gen_excp(ctx, EXCP_FEN, 0);
2851 break;
2854 return ret;
2857 static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
2859 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2860 CPUAlphaState *env = cpu_env(cpu);
2861 int64_t bound;
2863 ctx->tbflags = ctx->base.tb->flags;
2864 ctx->mem_idx = alpha_env_mmu_index(env);
2865 ctx->implver = env->implver;
2866 ctx->amask = env->amask;
2868 #ifdef CONFIG_USER_ONLY
2869 ctx->ir = cpu_std_ir;
2870 ctx->unalign = (ctx->tbflags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN);
2871 #else
2872 ctx->palbr = env->palbr;
2873 ctx->ir = (ctx->tbflags & ENV_FLAG_PAL_MODE ? cpu_pal_ir : cpu_std_ir);
2874 #endif
2876 /* ??? Every TB begins with unset rounding mode, to be initialized on
2877 the first fp insn of the TB. Alternately we could define a proper
2878 default for every TB (e.g. QUAL_RM_N or QUAL_RM_D) and make sure
2879 to reset the FP_STATUS to that default at the end of any TB that
2880 changes the default. We could even (gasp) dynamically figure out
2881 what default would be most efficient given the running program. */
2882 ctx->tb_rm = -1;
2883 /* Similarly for flush-to-zero. */
2884 ctx->tb_ftz = -1;
2886 ctx->zero = NULL;
2887 ctx->sink = NULL;
2889 /* Bound the number of insns to execute to those left on the page. */
2890 bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
2891 ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
2894 static void alpha_tr_tb_start(DisasContextBase *db, CPUState *cpu)
2898 static void alpha_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
2900 tcg_gen_insn_start(dcbase->pc_next);
2903 static void alpha_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
2905 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2906 uint32_t insn = translator_ldl(cpu_env(cpu), &ctx->base,
2907 ctx->base.pc_next);
2909 ctx->base.pc_next += 4;
2910 ctx->base.is_jmp = translate_one(ctx, insn);
2912 free_context_temps(ctx);
2915 static void alpha_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
2917 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2919 switch (ctx->base.is_jmp) {
2920 case DISAS_NORETURN:
2921 break;
2922 case DISAS_TOO_MANY:
2923 if (use_goto_tb(ctx, ctx->base.pc_next)) {
2924 tcg_gen_goto_tb(0);
2925 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
2926 tcg_gen_exit_tb(ctx->base.tb, 0);
2928 /* FALLTHRU */
2929 case DISAS_PC_STALE:
2930 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
2931 /* FALLTHRU */
2932 case DISAS_PC_UPDATED:
2933 tcg_gen_lookup_and_goto_ptr();
2934 break;
2935 case DISAS_PC_UPDATED_NOCHAIN:
2936 tcg_gen_exit_tb(NULL, 0);
2937 break;
2938 default:
2939 g_assert_not_reached();
2943 static void alpha_tr_disas_log(const DisasContextBase *dcbase,
2944 CPUState *cpu, FILE *logfile)
2946 fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
2947 target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size);
2950 static const TranslatorOps alpha_tr_ops = {
2951 .init_disas_context = alpha_tr_init_disas_context,
2952 .tb_start = alpha_tr_tb_start,
2953 .insn_start = alpha_tr_insn_start,
2954 .translate_insn = alpha_tr_translate_insn,
2955 .tb_stop = alpha_tr_tb_stop,
2956 .disas_log = alpha_tr_disas_log,
2959 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int *max_insns,
2960 vaddr pc, void *host_pc)
2962 DisasContext dc;
2963 translator_loop(cpu, tb, max_insns, pc, host_pc, &alpha_tr_ops, &dc.base);