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