#include <inttypes.h>
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
#include "tcg-op.h"
#include "qemu-common.h"
OPC_MUL = 0x02 | OPC_SPECIAL2,
OPC_MSUB = 0x04 | OPC_SPECIAL2,
OPC_MSUBU = 0x05 | OPC_SPECIAL2,
+ /* Loongson 2F */
+ OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
+ OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
+ OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
+ OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
+ OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
+ OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
+ OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
+ OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
+ OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
+ OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
+ OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
+ OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
/* Misc */
OPC_CLZ = 0x20 | OPC_SPECIAL2,
OPC_CLO = 0x21 | OPC_SPECIAL2,
OPC_BSHFL = 0x20 | OPC_SPECIAL3,
OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
OPC_RDHWR = 0x3B | OPC_SPECIAL3,
+
+ /* Loongson 2E */
+ OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
+ OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
+ OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
+ OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
+ OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
+ OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
+ OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
+ OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
+ OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
+ OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
+ OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
+ OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
};
/* BSHFL opcodes */
/* load/store instructions. */
#define OP_LD(insn,fname) \
-static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
+static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
{ \
tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
}
#undef OP_LD
#define OP_ST(insn,fname) \
-static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
+static inline void op_st_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
{ \
tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
}
#ifdef CONFIG_USER_ONLY
#define OP_LD_ATOMIC(insn,fname) \
-static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
+static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
{ \
TCGv t0 = tcg_temp_new(); \
tcg_gen_mov_tl(t0, arg1); \
}
#else
#define OP_LD_ATOMIC(insn,fname) \
-static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
+static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
{ \
gen_helper_2i(insn, ret, arg1, ctx->mem_idx); \
}
#ifdef CONFIG_USER_ONLY
#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
-static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
+static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
{ \
TCGv t0 = tcg_temp_new(); \
int l1 = gen_new_label(); \
}
#else
#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
-static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
+static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
{ \
TCGv t0 = tcg_temp_new(); \
gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx); \
return pc;
}
-/* Load and store */
-static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
- int base, int16_t offset)
+/* Load */
+static void gen_ld (CPUState *env, DisasContext *ctx, uint32_t opc,
+ int rt, int base, int16_t offset)
{
- const char *opn = "ldst";
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
+ const char *opn = "ld";
+ TCGv t0, t1;
+
+ if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
+ /* Loongson CPU uses a load to zero register for prefetch.
+ We emulate it as a NOP. On other CPU we must perform the
+ actual memory access. */
+ MIPS_DEBUG("NOP");
+ return;
+ }
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
gen_base_offset_addr(ctx, t0, base, offset);
- /* Don't do NOP if destination is zero: we must perform the actual
- memory access. */
+
switch (opc) {
#if defined(TARGET_MIPS64)
case OPC_LWU:
save_cpu_state(ctx, 0);
- op_ldst_lwu(t0, t0, ctx);
+ op_ld_lwu(t0, t0, ctx);
gen_store_gpr(t0, rt);
opn = "lwu";
break;
case OPC_LD:
save_cpu_state(ctx, 0);
- op_ldst_ld(t0, t0, ctx);
+ op_ld_ld(t0, t0, ctx);
gen_store_gpr(t0, rt);
opn = "ld";
break;
case OPC_LLD:
- save_cpu_state(ctx, 0);
- op_ldst_lld(t0, t0, ctx);
+ save_cpu_state(ctx, 1);
+ op_ld_lld(t0, t0, ctx);
gen_store_gpr(t0, rt);
opn = "lld";
break;
- case OPC_SD:
- save_cpu_state(ctx, 0);
- gen_load_gpr(t1, rt);
- op_ldst_sd(t1, t0, ctx);
- opn = "sd";
- break;
case OPC_LDL:
save_cpu_state(ctx, 1);
gen_load_gpr(t1, rt);
gen_store_gpr(t1, rt);
opn = "ldl";
break;
- case OPC_SDL:
- save_cpu_state(ctx, 1);
- gen_load_gpr(t1, rt);
- gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
- opn = "sdl";
- break;
case OPC_LDR:
save_cpu_state(ctx, 1);
gen_load_gpr(t1, rt);
gen_store_gpr(t1, rt);
opn = "ldr";
break;
- case OPC_SDR:
- save_cpu_state(ctx, 1);
- gen_load_gpr(t1, rt);
- gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
- opn = "sdr";
- break;
case OPC_LDPC:
- save_cpu_state(ctx, 1);
+ save_cpu_state(ctx, 0);
tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
gen_op_addr_add(ctx, t0, t0, t1);
- op_ldst_ld(t0, t0, ctx);
+ op_ld_ld(t0, t0, ctx);
gen_store_gpr(t0, rt);
+ opn = "ldpc";
break;
#endif
case OPC_LWPC:
- save_cpu_state(ctx, 1);
+ save_cpu_state(ctx, 0);
tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
gen_op_addr_add(ctx, t0, t0, t1);
- op_ldst_lw(t0, t0, ctx);
+ op_ld_lw(t0, t0, ctx);
gen_store_gpr(t0, rt);
+ opn = "lwpc";
break;
case OPC_LW:
save_cpu_state(ctx, 0);
- op_ldst_lw(t0, t0, ctx);
+ op_ld_lw(t0, t0, ctx);
gen_store_gpr(t0, rt);
opn = "lw";
break;
- case OPC_SW:
- save_cpu_state(ctx, 0);
- gen_load_gpr(t1, rt);
- op_ldst_sw(t1, t0, ctx);
- opn = "sw";
- break;
case OPC_LH:
save_cpu_state(ctx, 0);
- op_ldst_lh(t0, t0, ctx);
+ op_ld_lh(t0, t0, ctx);
gen_store_gpr(t0, rt);
opn = "lh";
break;
- case OPC_SH:
- save_cpu_state(ctx, 0);
- gen_load_gpr(t1, rt);
- op_ldst_sh(t1, t0, ctx);
- opn = "sh";
- break;
case OPC_LHU:
save_cpu_state(ctx, 0);
- op_ldst_lhu(t0, t0, ctx);
+ op_ld_lhu(t0, t0, ctx);
gen_store_gpr(t0, rt);
opn = "lhu";
break;
case OPC_LB:
save_cpu_state(ctx, 0);
- op_ldst_lb(t0, t0, ctx);
+ op_ld_lb(t0, t0, ctx);
gen_store_gpr(t0, rt);
opn = "lb";
break;
- case OPC_SB:
- save_cpu_state(ctx, 0);
- gen_load_gpr(t1, rt);
- op_ldst_sb(t1, t0, ctx);
- opn = "sb";
- break;
case OPC_LBU:
save_cpu_state(ctx, 0);
- op_ldst_lbu(t0, t0, ctx);
+ op_ld_lbu(t0, t0, ctx);
gen_store_gpr(t0, rt);
opn = "lbu";
break;
gen_store_gpr(t1, rt);
opn = "lwl";
break;
- case OPC_SWL:
- save_cpu_state(ctx, 1);
- gen_load_gpr(t1, rt);
- gen_helper_2i(swl, t1, t0, ctx->mem_idx);
- opn = "swr";
- break;
case OPC_LWR:
save_cpu_state(ctx, 1);
gen_load_gpr(t1, rt);
gen_store_gpr(t1, rt);
opn = "lwr";
break;
- case OPC_SWR:
- save_cpu_state(ctx, 1);
- gen_load_gpr(t1, rt);
- gen_helper_2i(swr, t1, t0, ctx->mem_idx);
- opn = "swr";
- break;
case OPC_LL:
save_cpu_state(ctx, 1);
- op_ldst_ll(t0, t0, ctx);
+ op_ld_ll(t0, t0, ctx);
gen_store_gpr(t0, rt);
opn = "ll";
break;
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
tcg_temp_free(t0);
tcg_temp_free(t1);
}
+/* Store */
+static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
+ int base, int16_t offset)
+{
+ const char *opn = "st";
+ TCGv t0 = tcg_temp_new();
+ TCGv t1 = tcg_temp_new();
+
+ gen_base_offset_addr(ctx, t0, base, offset);
+ gen_load_gpr(t1, rt);
+ switch (opc) {
+#if defined(TARGET_MIPS64)
+ case OPC_SD:
+ save_cpu_state(ctx, 0);
+ op_st_sd(t1, t0, ctx);
+ opn = "sd";
+ break;
+ case OPC_SDL:
+ save_cpu_state(ctx, 1);
+ gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
+ opn = "sdl";
+ break;
+ case OPC_SDR:
+ save_cpu_state(ctx, 1);
+ gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
+ opn = "sdr";
+ break;
+#endif
+ case OPC_SW:
+ save_cpu_state(ctx, 0);
+ op_st_sw(t1, t0, ctx);
+ opn = "sw";
+ break;
+ case OPC_SH:
+ save_cpu_state(ctx, 0);
+ op_st_sh(t1, t0, ctx);
+ opn = "sh";
+ break;
+ case OPC_SB:
+ save_cpu_state(ctx, 0);
+ op_st_sb(t1, t0, ctx);
+ opn = "sb";
+ break;
+ case OPC_SWL:
+ save_cpu_state(ctx, 1);
+ gen_helper_2i(swl, t1, t0, ctx->mem_idx);
+ opn = "swl";
+ break;
+ case OPC_SWR:
+ save_cpu_state(ctx, 1);
+ gen_helper_2i(swr, t1, t0, ctx->mem_idx);
+ opn = "swr";
+ break;
+ }
+ (void)opn; /* avoid a compiler warning */
+ MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+}
+
+
/* Store conditional */
static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
int base, int16_t offset)
switch (opc) {
#if defined(TARGET_MIPS64)
case OPC_SCD:
- save_cpu_state(ctx, 0);
- op_ldst_scd(t1, t0, rt, ctx);
+ save_cpu_state(ctx, 1);
+ op_st_scd(t1, t0, rt, ctx);
opn = "scd";
break;
#endif
case OPC_SC:
save_cpu_state(ctx, 1);
- op_ldst_sc(t1, t0, rt, ctx);
+ op_st_sc(t1, t0, rt, ctx);
opn = "sc";
break;
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
tcg_temp_free(t1);
tcg_temp_free(t0);
generate_exception(ctx, EXCP_RI);
goto out;
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
out:
tcg_temp_free(t0);
break;
#endif
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
}
opn = "lui";
break;
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
}
opn = "sltiu";
break;
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
tcg_temp_free(t0);
}
break;
#endif
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
tcg_temp_free(t0);
}
opn = "mul";
break;
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
}
tcg_gen_movi_tl(cpu_gpr[rd], 0);
gen_set_label(l1);
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
}
opn = "xor";
break;
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
}
opn = "sltu";
break;
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
tcg_temp_free(t0);
tcg_temp_free(t1);
break;
#endif
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
tcg_temp_free(t0);
tcg_temp_free(t1);
opn = "mtlo";
break;
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s", opn, regnames[reg]);
}
generate_exception(ctx, EXCP_RI);
goto out;
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
out:
tcg_temp_free(t0);
goto out;
}
gen_store_gpr(t0, rd);
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
out:
break;
#endif
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
tcg_temp_free(t0);
}
+/* Godson integer instructions */
+static void gen_loongson_integer (DisasContext *ctx, uint32_t opc,
+ int rd, int rs, int rt)
+{
+ const char *opn = "loongson";
+ TCGv t0, t1;
+
+ if (rd == 0) {
+ /* Treat as NOP. */
+ MIPS_DEBUG("NOP");
+ return;
+ }
+
+ switch (opc) {
+ case OPC_MULT_G_2E:
+ case OPC_MULT_G_2F:
+ case OPC_MULTU_G_2E:
+ case OPC_MULTU_G_2F:
+#if defined(TARGET_MIPS64)
+ case OPC_DMULT_G_2E:
+ case OPC_DMULT_G_2F:
+ case OPC_DMULTU_G_2E:
+ case OPC_DMULTU_G_2F:
+#endif
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+ break;
+ default:
+ t0 = tcg_temp_local_new();
+ t1 = tcg_temp_local_new();
+ break;
+ }
+
+ gen_load_gpr(t0, rs);
+ gen_load_gpr(t1, rt);
+
+ switch (opc) {
+ case OPC_MULT_G_2E:
+ case OPC_MULT_G_2F:
+ tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ opn = "mult.g";
+ break;
+ case OPC_MULTU_G_2E:
+ case OPC_MULTU_G_2F:
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_ext32u_tl(t1, t1);
+ tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ opn = "multu.g";
+ break;
+ case OPC_DIV_G_2E:
+ case OPC_DIV_G_2F:
+ {
+ int l1 = gen_new_label();
+ int l2 = gen_new_label();
+ int l3 = gen_new_label();
+ tcg_gen_ext32s_tl(t0, t0);
+ tcg_gen_ext32s_tl(t1, t1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l3);
+ gen_set_label(l1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
+ tcg_gen_mov_tl(cpu_gpr[rd], t0);
+ tcg_gen_br(l3);
+ gen_set_label(l2);
+ tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ gen_set_label(l3);
+ }
+ opn = "div.g";
+ break;
+ case OPC_DIVU_G_2E:
+ case OPC_DIVU_G_2F:
+ {
+ int l1 = gen_new_label();
+ int l2 = gen_new_label();
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_ext32u_tl(t1, t1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l2);
+ gen_set_label(l1);
+ tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ gen_set_label(l2);
+ }
+ opn = "divu.g";
+ break;
+ case OPC_MOD_G_2E:
+ case OPC_MOD_G_2F:
+ {
+ int l1 = gen_new_label();
+ int l2 = gen_new_label();
+ int l3 = gen_new_label();
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_ext32u_tl(t1, t1);
+ tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
+ gen_set_label(l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l3);
+ gen_set_label(l2);
+ tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ gen_set_label(l3);
+ }
+ opn = "mod.g";
+ break;
+ case OPC_MODU_G_2E:
+ case OPC_MODU_G_2F:
+ {
+ int l1 = gen_new_label();
+ int l2 = gen_new_label();
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_ext32u_tl(t1, t1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l2);
+ gen_set_label(l1);
+ tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ gen_set_label(l2);
+ }
+ opn = "modu.g";
+ break;
+#if defined(TARGET_MIPS64)
+ case OPC_DMULT_G_2E:
+ case OPC_DMULT_G_2F:
+ tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+ opn = "dmult.g";
+ break;
+ case OPC_DMULTU_G_2E:
+ case OPC_DMULTU_G_2F:
+ tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+ opn = "dmultu.g";
+ break;
+ case OPC_DDIV_G_2E:
+ case OPC_DDIV_G_2F:
+ {
+ int l1 = gen_new_label();
+ int l2 = gen_new_label();
+ int l3 = gen_new_label();
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l3);
+ gen_set_label(l1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
+ tcg_gen_mov_tl(cpu_gpr[rd], t0);
+ tcg_gen_br(l3);
+ gen_set_label(l2);
+ tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
+ gen_set_label(l3);
+ }
+ opn = "ddiv.g";
+ break;
+ case OPC_DDIVU_G_2E:
+ case OPC_DDIVU_G_2F:
+ {
+ int l1 = gen_new_label();
+ int l2 = gen_new_label();
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l2);
+ gen_set_label(l1);
+ tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
+ gen_set_label(l2);
+ }
+ opn = "ddivu.g";
+ break;
+ case OPC_DMOD_G_2E:
+ case OPC_DMOD_G_2F:
+ {
+ int l1 = gen_new_label();
+ int l2 = gen_new_label();
+ int l3 = gen_new_label();
+ tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
+ gen_set_label(l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l3);
+ gen_set_label(l2);
+ tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
+ gen_set_label(l3);
+ }
+ opn = "dmod.g";
+ break;
+ case OPC_DMODU_G_2E:
+ case OPC_DMODU_G_2F:
+ {
+ int l1 = gen_new_label();
+ int l2 = gen_new_label();
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l2);
+ gen_set_label(l1);
+ tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
+ gen_set_label(l2);
+ }
+ opn = "dmodu.g";
+ break;
+#endif
+ }
+
+ (void)opn; /* avoid a compiler warning */
+ MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+}
+
/* Traps */
static void gen_trap (DisasContext *ctx, uint32_t opc,
int rs, int rt, int16_t imm)
likely(!ctx->singlestep_enabled)) {
tcg_gen_goto_tb(n);
gen_save_pc(dest);
- tcg_gen_exit_tb((long)tb + n);
+ tcg_gen_exit_tb((tcg_target_long)tb + n);
} else {
gen_save_pc(dest);
if (ctx->singlestep_enabled) {
case OPC_DINSU:
if (lsb > msb)
goto fail;
- mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
+ mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
gen_load_gpr(t0, rt);
tcg_gen_andi_tl(t0, t0, ~mask);
tcg_gen_shli_tl(t1, t1, lsb + 32);
gen_helper_mfc0_count(arg);
if (use_icount) {
gen_io_end();
- ctx->bstate = BS_STOP;
}
+ /* Break the TB to be able to take timer interrupts immediately
+ after reading count. */
+ ctx->bstate = BS_STOP;
rn = "Count";
break;
/* 6,7 are implementation dependent */
default:
goto die;
}
+ (void)rn; /* avoid a compiler warning */
LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
return;
default:
goto die;
}
+ (void)rn; /* avoid a compiler warning */
LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
/* For simplicity assume that all writes can cause interrupts. */
if (use_icount) {
gen_helper_mfc0_count(arg);
if (use_icount) {
gen_io_end();
- ctx->bstate = BS_STOP;
}
+ /* Break the TB to be able to take timer interrupts immediately
+ after reading count. */
+ ctx->bstate = BS_STOP;
rn = "Count";
break;
/* 6,7 are implementation dependent */
default:
goto die;
}
+ (void)rn; /* avoid a compiler warning */
LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
return;
switch (sel) {
case 0:
save_cpu_state(ctx, 1);
+ /* Mark as an IO operation because we may trigger a software
+ interrupt. */
+ if (use_icount) {
+ gen_io_start();
+ }
gen_helper_mtc0_cause(arg);
+ if (use_icount) {
+ gen_io_end();
+ }
+ /* Stop translation as we may have triggered an intetrupt */
+ ctx->bstate = BS_STOP;
rn = "Cause";
break;
default:
default:
goto die;
}
+ (void)rn; /* avoid a compiler warning */
LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
/* For simplicity assume that all writes can cause interrupts. */
if (use_icount) {
generate_exception(ctx, EXCP_RI);
return;
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
}
#endif /* !CONFIG_USER_ONLY */
generate_exception (ctx, EXCP_RI);
goto out;
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
ctx->hflags, btarget);
ctx->btarget = btarget;
generate_exception (ctx, EXCP_RI);
goto out;
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
out:
generate_exception (ctx, EXCP_RI);
return;
}
+ (void)opn; /* avoid a compiler warning */
switch (optype) {
case BINOP:
MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
break;
}
tcg_temp_free(t0);
+ (void)opn; (void)store; /* avoid compiler warnings */
MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
regnames[index], regnames[base]);
}
generate_exception (ctx, EXCP_RI);
return;
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
fregnames[fs], fregnames[ft]);
}
case 4:
gen_base_offset_addr(ctx, t0, 29, 12);
gen_load_gpr(t1, 7);
- op_ldst_sw(t1, t0, ctx);
+ op_st_sw(t1, t0, ctx);
/* Fall through */
case 3:
gen_base_offset_addr(ctx, t0, 29, 8);
gen_load_gpr(t1, 6);
- op_ldst_sw(t1, t0, ctx);
+ op_st_sw(t1, t0, ctx);
/* Fall through */
case 2:
gen_base_offset_addr(ctx, t0, 29, 4);
gen_load_gpr(t1, 5);
- op_ldst_sw(t1, t0, ctx);
+ op_st_sw(t1, t0, ctx);
/* Fall through */
case 1:
gen_base_offset_addr(ctx, t0, 29, 0);
gen_load_gpr(t1, 4);
- op_ldst_sw(t1, t0, ctx);
+ op_st_sw(t1, t0, ctx);
}
gen_load_gpr(t0, 29);
#define DECR_AND_STORE(reg) do { \
tcg_gen_subi_tl(t0, t0, 4); \
gen_load_gpr(t1, reg); \
- op_ldst_sw(t1, t0, ctx); \
+ op_st_sw(t1, t0, ctx); \
} while (0)
if (do_ra) {
#define DECR_AND_LOAD(reg) do { \
tcg_gen_subi_tl(t0, t0, 4); \
- op_ldst_lw(t1, t0, ctx); \
+ op_ld_lw(t1, t0, ctx); \
gen_store_gpr(t1, reg); \
} while (0)
case I64_LDSP:
check_mips_64(ctx);
offset = extended ? offset : offset << 3;
- gen_ldst(ctx, OPC_LD, ry, 29, offset);
+ gen_ld(env, ctx, OPC_LD, ry, 29, offset);
break;
case I64_SDSP:
check_mips_64(ctx);
offset = extended ? offset : offset << 3;
- gen_ldst(ctx, OPC_SD, ry, 29, offset);
+ gen_st(ctx, OPC_SD, ry, 29, offset);
break;
case I64_SDRASP:
check_mips_64(ctx);
offset = extended ? offset : (ctx->opcode & 0xff) << 3;
- gen_ldst(ctx, OPC_SD, 31, 29, offset);
+ gen_st(ctx, OPC_SD, 31, 29, offset);
break;
case I64_DADJSP:
check_mips_64(ctx);
generate_exception(ctx, EXCP_RI);
} else {
offset = extended ? offset : offset << 3;
- gen_ldst(ctx, OPC_LDPC, ry, 0, offset);
+ gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
}
break;
case I64_DADDIU5:
#if defined(TARGET_MIPS64)
case M16_OPC_LD:
check_mips_64(ctx);
- gen_ldst(ctx, OPC_LD, ry, rx, offset);
+ gen_ld(env, ctx, OPC_LD, ry, rx, offset);
break;
#endif
case M16_OPC_RRIA:
gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
break;
case I8_SWRASP:
- gen_ldst(ctx, OPC_SW, 31, 29, imm);
+ gen_st(ctx, OPC_SW, 31, 29, imm);
break;
case I8_ADJSP:
gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
break;
#if defined(TARGET_MIPS64)
case M16_OPC_SD:
- gen_ldst(ctx, OPC_SD, ry, rx, offset);
+ gen_st(ctx, OPC_SD, ry, rx, offset);
break;
#endif
case M16_OPC_LB:
- gen_ldst(ctx, OPC_LB, ry, rx, offset);
+ gen_ld(env, ctx, OPC_LB, ry, rx, offset);
break;
case M16_OPC_LH:
- gen_ldst(ctx, OPC_LH, ry, rx, offset);
+ gen_ld(env, ctx, OPC_LH, ry, rx, offset);
break;
case M16_OPC_LWSP:
- gen_ldst(ctx, OPC_LW, rx, 29, offset);
+ gen_ld(env, ctx, OPC_LW, rx, 29, offset);
break;
case M16_OPC_LW:
- gen_ldst(ctx, OPC_LW, ry, rx, offset);
+ gen_ld(env, ctx, OPC_LW, ry, rx, offset);
break;
case M16_OPC_LBU:
- gen_ldst(ctx, OPC_LBU, ry, rx, offset);
+ gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
break;
case M16_OPC_LHU:
- gen_ldst(ctx, OPC_LHU, ry, rx, offset);
+ gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
break;
case M16_OPC_LWPC:
- gen_ldst(ctx, OPC_LWPC, rx, 0, offset);
+ gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
break;
#if defined(TARGET_MIPS64)
case M16_OPC_LWU:
- gen_ldst(ctx, OPC_LWU, ry, rx, offset);
+ gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
break;
#endif
case M16_OPC_SB:
- gen_ldst(ctx, OPC_SB, ry, rx, offset);
+ gen_st(ctx, OPC_SB, ry, rx, offset);
break;
case M16_OPC_SH:
- gen_ldst(ctx, OPC_SH, ry, rx, offset);
+ gen_st(ctx, OPC_SH, ry, rx, offset);
break;
case M16_OPC_SWSP:
- gen_ldst(ctx, OPC_SW, rx, 29, offset);
+ gen_st(ctx, OPC_SW, rx, 29, offset);
break;
case M16_OPC_SW:
- gen_ldst(ctx, OPC_SW, ry, rx, offset);
+ gen_st(ctx, OPC_SW, ry, rx, offset);
break;
#if defined(TARGET_MIPS64)
case M16_OPC_I64:
#if defined(TARGET_MIPS64)
case M16_OPC_LD:
check_mips_64(ctx);
- gen_ldst(ctx, OPC_LD, ry, rx, offset << 3);
+ gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
break;
#endif
case M16_OPC_RRIA:
((int8_t)ctx->opcode) << 1);
break;
case I8_SWRASP:
- gen_ldst(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
+ gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
break;
case I8_ADJSP:
gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
#if defined(TARGET_MIPS64)
case M16_OPC_SD:
check_mips_64(ctx);
- gen_ldst(ctx, OPC_SD, ry, rx, offset << 3);
+ gen_st(ctx, OPC_SD, ry, rx, offset << 3);
break;
#endif
case M16_OPC_LB:
- gen_ldst(ctx, OPC_LB, ry, rx, offset);
+ gen_ld(env, ctx, OPC_LB, ry, rx, offset);
break;
case M16_OPC_LH:
- gen_ldst(ctx, OPC_LH, ry, rx, offset << 1);
+ gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
break;
case M16_OPC_LWSP:
- gen_ldst(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
+ gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
break;
case M16_OPC_LW:
- gen_ldst(ctx, OPC_LW, ry, rx, offset << 2);
+ gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
break;
case M16_OPC_LBU:
- gen_ldst(ctx, OPC_LBU, ry, rx, offset);
+ gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
break;
case M16_OPC_LHU:
- gen_ldst(ctx, OPC_LHU, ry, rx, offset << 1);
+ gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
break;
case M16_OPC_LWPC:
- gen_ldst(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
+ gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
break;
#if defined (TARGET_MIPS64)
case M16_OPC_LWU:
check_mips_64(ctx);
- gen_ldst(ctx, OPC_LWU, ry, rx, offset << 2);
+ gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
break;
#endif
case M16_OPC_SB:
- gen_ldst(ctx, OPC_SB, ry, rx, offset);
+ gen_st(ctx, OPC_SB, ry, rx, offset);
break;
case M16_OPC_SH:
- gen_ldst(ctx, OPC_SH, ry, rx, offset << 1);
+ gen_st(ctx, OPC_SH, ry, rx, offset << 1);
break;
case M16_OPC_SWSP:
- gen_ldst(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
+ gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
break;
case M16_OPC_SW:
- gen_ldst(ctx, OPC_SW, ry, rx, offset << 2);
+ gen_st(ctx, OPC_SW, ry, rx, offset << 2);
break;
case M16_OPC_RRR:
{
}
save_cpu_state(ctx, 0);
- op_ldst_lw(t1, t0, ctx);
+ op_ld_lw(t1, t0, ctx);
gen_store_gpr(t1, rd);
tcg_temp_free(t0);
switch (opc) {
case LWP:
save_cpu_state(ctx, 0);
- op_ldst_lw(t1, t0, ctx);
+ op_ld_lw(t1, t0, ctx);
gen_store_gpr(t1, rd);
tcg_gen_movi_tl(t1, 4);
gen_op_addr_add(ctx, t0, t0, t1);
- op_ldst_lw(t1, t0, ctx);
+ op_ld_lw(t1, t0, ctx);
gen_store_gpr(t1, rd+1);
opn = "lwp";
break;
case SWP:
- save_cpu_state(ctx, 1);
+ save_cpu_state(ctx, 0);
gen_load_gpr(t1, rd);
- op_ldst_sw(t1, t0, ctx);
+ op_st_sw(t1, t0, ctx);
tcg_gen_movi_tl(t1, 4);
gen_op_addr_add(ctx, t0, t0, t1);
gen_load_gpr(t1, rd+1);
- op_ldst_sw(t1, t0, ctx);
+ op_st_sw(t1, t0, ctx);
opn = "swp";
break;
#ifdef TARGET_MIPS64
case LDP:
save_cpu_state(ctx, 0);
- op_ldst_ld(t1, t0, ctx);
+ op_ld_ld(t1, t0, ctx);
gen_store_gpr(t1, rd);
tcg_gen_movi_tl(t1, 8);
gen_op_addr_add(ctx, t0, t0, t1);
- op_ldst_ld(t1, t0, ctx);
+ op_ld_ld(t1, t0, ctx);
gen_store_gpr(t1, rd+1);
opn = "ldp";
break;
case SDP:
- save_cpu_state(ctx, 1);
+ save_cpu_state(ctx, 0);
gen_load_gpr(t1, rd);
- op_ldst_sd(t1, t0, ctx);
+ op_st_sd(t1, t0, ctx);
tcg_gen_movi_tl(t1, 8);
gen_op_addr_add(ctx, t0, t0, t1);
gen_load_gpr(t1, rd+1);
- op_ldst_sd(t1, t0, ctx);
+ op_st_sd(t1, t0, ctx);
opn = "sdp";
break;
#endif
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
tcg_temp_free(t0);
tcg_temp_free(t1);
switch (minor) {
case LWL:
mips32_op = OPC_LWL;
- goto do_ldst_lr;
+ goto do_ld_lr;
case SWL:
mips32_op = OPC_SWL;
- goto do_ldst_lr;
+ goto do_st_lr;
case LWR:
mips32_op = OPC_LWR;
- goto do_ldst_lr;
+ goto do_ld_lr;
case SWR:
mips32_op = OPC_SWR;
- goto do_ldst_lr;
+ goto do_st_lr;
#if defined(TARGET_MIPS64)
case LDL:
mips32_op = OPC_LDL;
- goto do_ldst_lr;
+ goto do_ld_lr;
case SDL:
mips32_op = OPC_SDL;
- goto do_ldst_lr;
+ goto do_st_lr;
case LDR:
mips32_op = OPC_LDR;
- goto do_ldst_lr;
+ goto do_ld_lr;
case SDR:
mips32_op = OPC_SDR;
- goto do_ldst_lr;
+ goto do_st_lr;
case LWU:
mips32_op = OPC_LWU;
- goto do_ldst_lr;
+ goto do_ld_lr;
case LLD:
mips32_op = OPC_LLD;
- goto do_ldst_lr;
+ goto do_ld_lr;
#endif
case LL:
mips32_op = OPC_LL;
- do_ldst_lr:
- gen_ldst(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
+ goto do_ld_lr;
+ do_ld_lr:
+ gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
+ break;
+ do_st_lr:
+ gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
break;
case SC:
gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
/* Loads and stores */
case LB32:
mips32_op = OPC_LB;
- goto do_ldst;
+ goto do_ld;
case LBU32:
mips32_op = OPC_LBU;
- goto do_ldst;
+ goto do_ld;
case LH32:
mips32_op = OPC_LH;
- goto do_ldst;
+ goto do_ld;
case LHU32:
mips32_op = OPC_LHU;
- goto do_ldst;
+ goto do_ld;
case LW32:
mips32_op = OPC_LW;
- goto do_ldst;
+ goto do_ld;
#ifdef TARGET_MIPS64
case LD32:
mips32_op = OPC_LD;
- goto do_ldst;
+ goto do_ld;
case SD32:
mips32_op = OPC_SD;
- goto do_ldst;
+ goto do_st;
#endif
case SB32:
mips32_op = OPC_SB;
- goto do_ldst;
+ goto do_st;
case SH32:
mips32_op = OPC_SH;
- goto do_ldst;
+ goto do_st;
case SW32:
mips32_op = OPC_SW;
- do_ldst:
- gen_ldst(ctx, mips32_op, rt, rs, imm);
+ goto do_st;
+ do_ld:
+ gen_ld(env, ctx, mips32_op, rt, rs, imm);
+ break;
+ do_st:
+ gen_st(ctx, mips32_op, rt, rs, imm);
break;
default:
generate_exception(ctx, EXCP_RI);
int rb = 28; /* GP */
int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
- gen_ldst(ctx, OPC_LW, rd, rb, offset);
+ gen_ld(env, ctx, OPC_LW, rd, rb, offset);
}
break;
case POOL16F:
int16_t offset = ZIMM(ctx->opcode, 0, 4);
offset = (offset == 0xf ? -1 : offset);
- gen_ldst(ctx, OPC_LBU, rd, rb, offset);
+ gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
}
break;
case LHU16:
int rb = mmreg(uMIPS_RS(ctx->opcode));
int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
- gen_ldst(ctx, OPC_LHU, rd, rb, offset);
+ gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
}
break;
case LWSP16:
int rb = 29; /* SP */
int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
- gen_ldst(ctx, OPC_LW, rd, rb, offset);
+ gen_ld(env, ctx, OPC_LW, rd, rb, offset);
}
break;
case LW16:
int rb = mmreg(uMIPS_RS(ctx->opcode));
int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
- gen_ldst(ctx, OPC_LW, rd, rb, offset);
+ gen_ld(env, ctx, OPC_LW, rd, rb, offset);
}
break;
case SB16:
int rb = mmreg(uMIPS_RS(ctx->opcode));
int16_t offset = ZIMM(ctx->opcode, 0, 4);
- gen_ldst(ctx, OPC_SB, rd, rb, offset);
+ gen_st(ctx, OPC_SB, rd, rb, offset);
}
break;
case SH16:
int rb = mmreg(uMIPS_RS(ctx->opcode));
int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
- gen_ldst(ctx, OPC_SH, rd, rb, offset);
+ gen_st(ctx, OPC_SH, rd, rb, offset);
}
break;
case SWSP16:
int rb = 29; /* SP */
int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
- gen_ldst(ctx, OPC_SW, rd, rb, offset);
+ gen_st(ctx, OPC_SW, rd, rb, offset);
}
break;
case SW16:
int rb = mmreg(uMIPS_RS(ctx->opcode));
int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
- gen_ldst(ctx, OPC_SW, rd, rb, offset);
+ gen_st(ctx, OPC_SW, rd, rb, offset);
}
break;
case MOVE16:
break;
case OPC_MOVN: /* Conditional move */
case OPC_MOVZ:
- check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
+ check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
+ INSN_LOONGSON2E | INSN_LOONGSON2F);
gen_cond_move(env, op1, rd, rs, rt);
break;
case OPC_ADD ... OPC_SUBU:
}
/* Treat as NOP. */
break;
+ case OPC_DIV_G_2F:
+ case OPC_DIVU_G_2F:
+ case OPC_MULT_G_2F:
+ case OPC_MULTU_G_2F:
+ case OPC_MOD_G_2F:
+ case OPC_MODU_G_2F:
+ check_insn(env, ctx, INSN_LOONGSON2F);
+ gen_loongson_integer(ctx, op1, rd, rs, rt);
+ break;
#if defined(TARGET_MIPS64)
case OPC_DCLO:
case OPC_DCLZ:
check_mips_64(ctx);
gen_cl(ctx, op1, rd, rs);
break;
+ case OPC_DMULT_G_2F:
+ case OPC_DMULTU_G_2F:
+ case OPC_DDIV_G_2F:
+ case OPC_DDIVU_G_2F:
+ case OPC_DMOD_G_2F:
+ case OPC_DMODU_G_2F:
+ check_insn(env, ctx, INSN_LOONGSON2F);
+ gen_loongson_integer(ctx, op1, rd, rs, rt);
+ break;
#endif
default: /* Invalid */
MIPS_INVAL("special2");
tcg_temp_free(t0);
}
break;
+ case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
+ case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
+ case OPC_MOD_G_2E ... OPC_MODU_G_2E:
+ check_insn(env, ctx, INSN_LOONGSON2E);
+ gen_loongson_integer(ctx, op1, rd, rs, rt);
+ break;
#if defined(TARGET_MIPS64)
case OPC_DEXTM ... OPC_DEXT:
case OPC_DINSM ... OPC_DINS:
op2 = MASK_DBSHFL(ctx->opcode);
gen_bshfl(ctx, op2, rt, rd);
break;
+ case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
+ case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
+ case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
+ check_insn(env, ctx, INSN_LOONGSON2E);
+ gen_loongson_integer(ctx, op1, rd, rs, rt);
+ break;
#endif
default: /* Invalid */
MIPS_INVAL("special3");
switch (op2) {
case OPC_DMT:
check_insn(env, ctx, ASE_MT);
- gen_helper_dmt(t0, t0);
+ gen_helper_dmt(t0);
gen_store_gpr(t0, rt);
break;
case OPC_EMT:
check_insn(env, ctx, ASE_MT);
- gen_helper_emt(t0, t0);
+ gen_helper_emt(t0);
gen_store_gpr(t0, rt);
break;
case OPC_DVPE:
check_insn(env, ctx, ASE_MT);
- gen_helper_dvpe(t0, t0);
+ gen_helper_dvpe(t0);
gen_store_gpr(t0, rt);
break;
case OPC_EVPE:
check_insn(env, ctx, ASE_MT);
- gen_helper_evpe(t0, t0);
+ gen_helper_evpe(t0);
gen_store_gpr(t0, rt);
break;
case OPC_DI:
*is_branch = 1;
break;
case OPC_LB ... OPC_LWR: /* Load and stores */
+ case OPC_LL:
+ gen_ld(env, ctx, op, rt, rs, imm);
+ break;
case OPC_SB ... OPC_SW:
case OPC_SWR:
- case OPC_LL:
- gen_ldst(ctx, op, rt, rs, imm);
+ gen_st(ctx, op, rt, rs, imm);
break;
case OPC_SC:
gen_st_cond(ctx, op, rt, rs, imm);
/* MIPS64 opcodes */
case OPC_LWU:
case OPC_LDL ... OPC_LDR:
- case OPC_SDL ... OPC_SDR:
case OPC_LLD:
case OPC_LD:
+ check_insn(env, ctx, ISA_MIPS3);
+ check_mips_64(ctx);
+ gen_ld(env, ctx, op, rt, rs, imm);
+ break;
+ case OPC_SDL ... OPC_SDR:
case OPC_SD:
check_insn(env, ctx, ISA_MIPS3);
check_mips_64(ctx);
- gen_ldst(ctx, op, rt, rs, imm);
+ gen_st(ctx, op, rt, rs, imm);
break;
case OPC_SCD:
check_insn(env, ctx, ISA_MIPS3);
} else {
switch (ctx.bstate) {
case BS_STOP:
- gen_helper_interrupt_restart();
gen_goto_tb(&ctx, 0, ctx.pc);
break;
case BS_NONE:
gen_goto_tb(&ctx, 0, ctx.pc);
break;
case BS_EXCP:
- gen_helper_interrupt_restart();
tcg_gen_exit_tb(0);
break;
case BS_BRANCH:
gen_intermediate_code_internal(env, tb, 1);
}
-static void fpu_dump_state(CPUState *env, FILE *f,
- int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
+static void fpu_dump_state(CPUState *env, FILE *f, fprintf_function fpu_fprintf,
int flags)
{
int i;
} while(0)
- fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
- env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
+ fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
+ env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
get_float_exception_flags(&env->active_fpu.fp_status));
for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
fpu_fprintf(f, "%3s: ", fregnames[i]);
static void
cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
- int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+ fprintf_function cpu_fprintf,
int flags)
{
int i;
}
#endif
-void cpu_dump_state (CPUState *env, FILE *f,
- int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
int flags)
{
int i;
def = cpu_mips_find_by_name(cpu_model);
if (!def)
return NULL;
- env = qemu_mallocz(sizeof(CPUMIPSState));
+ env = g_malloc0(sizeof(CPUMIPSState));
env->cpu_model = def;
env->cpu_model_str = cpu_model;
env->CP0_Random = env->tlb->nb_tlb - 1;
env->tlb->tlb_in_use = env->tlb->nb_tlb;
env->CP0_Wired = 0;
- /* SMP not implemented */
- env->CP0_EBase = 0x80000000;
+ env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
/* vectored interrupts not implemented, timer on int 7,
no performance counters. */
env->exception_index = EXCP_NONE;
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->active_tc.PC = gen_opc_pc[pc_pos];
env->hflags &= ~MIPS_HFLAG_BMASK;