"w30.d0", "w30.d1", "w31.d0", "w31.d1",
};
-#define MIPS_DEBUG(fmt, ...) \
+#define LOG_DISAS(...) \
do { \
if (MIPS_DEBUG_DISAS) { \
- qemu_log_mask(CPU_LOG_TB_IN_ASM, \
- TARGET_FMT_lx ": %08x " fmt "\n", \
- ctx->pc, ctx->opcode , ## __VA_ARGS__); \
+ qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
} \
} while (0)
-#define LOG_DISAS(...) \
+#define MIPS_INVAL(op) \
do { \
if (MIPS_DEBUG_DISAS) { \
- qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
+ qemu_log_mask(CPU_LOG_TB_IN_ASM, \
+ TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
+ ctx->pc, ctx->opcode, op, ctx->opcode >> 26, \
+ ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
} \
} while (0)
-#define MIPS_INVAL(op) \
- MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
- ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
-
/* General purpose registers moves. */
static inline void gen_load_gpr (TCGv t, int reg)
{
static void gen_ld(DisasContext *ctx, uint32_t opc,
int rt, int base, int16_t offset)
{
- const char *opn = "ld";
TCGv t0, t1, t2;
if (rt == 0 && ctx->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;
}
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL |
ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rt);
- opn = "lwu";
break;
case OPC_LD:
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rt);
- opn = "ld";
break;
case OPC_LLD:
case R6_OPC_LLD:
save_cpu_state(ctx, 1);
op_ld_lld(t0, t0, ctx);
gen_store_gpr(t0, rt);
- opn = "lld";
break;
case OPC_LDL:
t1 = tcg_temp_new();
tcg_gen_or_tl(t0, t0, t1);
tcg_temp_free(t1);
gen_store_gpr(t0, rt);
- opn = "ldl";
break;
case OPC_LDR:
t1 = tcg_temp_new();
tcg_gen_or_tl(t0, t0, t1);
tcg_temp_free(t1);
gen_store_gpr(t0, rt);
- opn = "ldr";
break;
case OPC_LDPC:
t1 = tcg_const_tl(pc_relative_pc(ctx));
tcg_temp_free(t1);
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
gen_store_gpr(t0, rt);
- opn = "ldpc";
break;
#endif
case OPC_LWPC:
tcg_temp_free(t1);
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
gen_store_gpr(t0, rt);
- opn = "lwpc";
break;
case OPC_LW:
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rt);
- opn = "lw";
break;
case OPC_LH:
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rt);
- opn = "lh";
break;
case OPC_LHU:
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW |
ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rt);
- opn = "lhu";
break;
case OPC_LB:
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
gen_store_gpr(t0, rt);
- opn = "lb";
break;
case OPC_LBU:
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
gen_store_gpr(t0, rt);
- opn = "lbu";
break;
case OPC_LWL:
t1 = tcg_temp_new();
tcg_temp_free(t1);
tcg_gen_ext32s_tl(t0, t0);
gen_store_gpr(t0, rt);
- opn = "lwl";
break;
case OPC_LWR:
t1 = tcg_temp_new();
tcg_temp_free(t1);
tcg_gen_ext32s_tl(t0, t0);
gen_store_gpr(t0, rt);
- opn = "lwr";
break;
case OPC_LL:
case R6_OPC_LL:
save_cpu_state(ctx, 1);
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);
}
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();
case OPC_SD:
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
ctx->default_tcg_memop_mask);
- opn = "sd";
break;
case OPC_SDL:
save_cpu_state(ctx, 1);
gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
- opn = "sdl";
break;
case OPC_SDR:
save_cpu_state(ctx, 1);
gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
- opn = "sdr";
break;
#endif
case OPC_SW:
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
ctx->default_tcg_memop_mask);
- opn = "sw";
break;
case OPC_SH:
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
ctx->default_tcg_memop_mask);
- opn = "sh";
break;
case OPC_SB:
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
- opn = "sb";
break;
case OPC_SWL:
save_cpu_state(ctx, 1);
gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
- opn = "swl";
break;
case OPC_SWR:
save_cpu_state(ctx, 1);
gen_helper_0e2i(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);
}
static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
int base, int16_t offset)
{
- const char *opn = "st_cond";
TCGv t0, t1;
#ifdef CONFIG_USER_ONLY
case R6_OPC_SCD:
save_cpu_state(ctx, 1);
op_st_scd(t1, t0, rt, ctx);
- opn = "scd";
break;
#endif
case OPC_SC:
case R6_OPC_SC:
save_cpu_state(ctx, 1);
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);
}
static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
int base, int16_t offset)
{
- const char *opn = "flt_ldst";
TCGv t0 = tcg_temp_new();
gen_base_offset_addr(ctx, t0, base, offset);
gen_store_fpr32(ctx, fp0, ft);
tcg_temp_free_i32(fp0);
}
- opn = "lwc1";
break;
case OPC_SWC1:
{
ctx->default_tcg_memop_mask);
tcg_temp_free_i32(fp0);
}
- opn = "swc1";
break;
case OPC_LDC1:
{
gen_store_fpr64(ctx, fp0, ft);
tcg_temp_free_i64(fp0);
}
- opn = "ldc1";
break;
case OPC_SDC1:
{
ctx->default_tcg_memop_mask);
tcg_temp_free_i64(fp0);
}
- opn = "sdc1";
break;
default:
- MIPS_INVAL(opn);
+ MIPS_INVAL("flt_ldst");
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);
}
int rt, int rs, int16_t imm)
{
target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
- const char *opn = "imm arith";
if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
/* If no destination, treat it as a NOP.
For addi, we must generate the overflow exception when needed. */
- MIPS_DEBUG("NOP");
return;
}
switch (opc) {
gen_store_gpr(t0, rt);
tcg_temp_free(t0);
}
- opn = "addi";
break;
case OPC_ADDIU:
if (rs != 0) {
} else {
tcg_gen_movi_tl(cpu_gpr[rt], uimm);
}
- opn = "addiu";
break;
#if defined(TARGET_MIPS64)
case OPC_DADDI:
gen_store_gpr(t0, rt);
tcg_temp_free(t0);
}
- opn = "daddi";
break;
case OPC_DADDIU:
if (rs != 0) {
} else {
tcg_gen_movi_tl(cpu_gpr[rt], uimm);
}
- opn = "daddiu";
break;
#endif
}
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
}
/* Logic with immediate operand */
if (rt == 0) {
/* If no destination, treat it as a NOP. */
- MIPS_DEBUG("NOP");
return;
}
uimm = (uint16_t)imm;
tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
else
tcg_gen_movi_tl(cpu_gpr[rt], 0);
- MIPS_DEBUG("andi %s, %s, " TARGET_FMT_lx, regnames[rt],
- regnames[rs], uimm);
break;
case OPC_ORI:
if (rs != 0)
tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
else
tcg_gen_movi_tl(cpu_gpr[rt], uimm);
- MIPS_DEBUG("ori %s, %s, " TARGET_FMT_lx, regnames[rt],
- regnames[rs], uimm);
break;
case OPC_XORI:
if (likely(rs != 0))
tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
else
tcg_gen_movi_tl(cpu_gpr[rt], uimm);
- MIPS_DEBUG("xori %s, %s, " TARGET_FMT_lx, regnames[rt],
- regnames[rs], uimm);
break;
case OPC_LUI:
if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
/* OPC_AUI */
tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
- MIPS_DEBUG("aui %s, %s, %04x", regnames[rt], regnames[rs], imm);
} else {
tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
- MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
}
break;
default:
- MIPS_DEBUG("Unknown logical immediate opcode %08x", opc);
break;
}
}
int rt, int rs, int16_t imm)
{
target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
- const char *opn = "imm arith";
TCGv t0;
if (rt == 0) {
/* If no destination, treat it as a NOP. */
- MIPS_DEBUG("NOP");
return;
}
t0 = tcg_temp_new();
switch (opc) {
case OPC_SLTI:
tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
- opn = "slti";
break;
case OPC_SLTIU:
tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, 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);
}
int rt, int rs, int16_t imm)
{
target_ulong uimm = ((uint16_t)imm) & 0x1f;
- const char *opn = "imm shift";
TCGv t0;
if (rt == 0) {
/* If no destination, treat it as a NOP. */
- MIPS_DEBUG("NOP");
return;
}
case OPC_SLL:
tcg_gen_shli_tl(t0, t0, uimm);
tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
- opn = "sll";
break;
case OPC_SRA:
tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
- opn = "sra";
break;
case OPC_SRL:
if (uimm != 0) {
} else {
tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
}
- opn = "srl";
break;
case OPC_ROTR:
if (uimm != 0) {
} else {
tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
}
- opn = "rotr";
break;
#if defined(TARGET_MIPS64)
case OPC_DSLL:
tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
- opn = "dsll";
break;
case OPC_DSRA:
tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
- opn = "dsra";
break;
case OPC_DSRL:
tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
- opn = "dsrl";
break;
case OPC_DROTR:
if (uimm != 0) {
} else {
tcg_gen_mov_tl(cpu_gpr[rt], t0);
}
- opn = "drotr";
break;
case OPC_DSLL32:
tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
- opn = "dsll32";
break;
case OPC_DSRA32:
tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
- opn = "dsra32";
break;
case OPC_DSRL32:
tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
- opn = "dsrl32";
break;
case OPC_DROTR32:
tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
- opn = "drotr32";
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);
}
static void gen_arith(DisasContext *ctx, uint32_t opc,
int rd, int rs, int rt)
{
- const char *opn = "arith";
-
if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
&& opc != OPC_DADD && opc != OPC_DSUB) {
/* If no destination, treat it as a NOP.
For add & sub, we must generate the overflow exception when needed. */
- MIPS_DEBUG("NOP");
return;
}
gen_store_gpr(t0, rd);
tcg_temp_free(t0);
}
- opn = "add";
break;
case OPC_ADDU:
if (rs != 0 && rt != 0) {
} else {
tcg_gen_movi_tl(cpu_gpr[rd], 0);
}
- opn = "addu";
break;
case OPC_SUB:
{
gen_store_gpr(t0, rd);
tcg_temp_free(t0);
}
- opn = "sub";
break;
case OPC_SUBU:
if (rs != 0 && rt != 0) {
} else {
tcg_gen_movi_tl(cpu_gpr[rd], 0);
}
- opn = "subu";
break;
#if defined(TARGET_MIPS64)
case OPC_DADD:
gen_store_gpr(t0, rd);
tcg_temp_free(t0);
}
- opn = "dadd";
break;
case OPC_DADDU:
if (rs != 0 && rt != 0) {
} else {
tcg_gen_movi_tl(cpu_gpr[rd], 0);
}
- opn = "daddu";
break;
case OPC_DSUB:
{
gen_store_gpr(t0, rd);
tcg_temp_free(t0);
}
- opn = "dsub";
break;
case OPC_DSUBU:
if (rs != 0 && rt != 0) {
} else {
tcg_gen_movi_tl(cpu_gpr[rd], 0);
}
- opn = "dsubu";
break;
#endif
case OPC_MUL:
} else {
tcg_gen_movi_tl(cpu_gpr[rd], 0);
}
- opn = "mul";
break;
}
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
}
/* Conditional move */
static void gen_cond_move(DisasContext *ctx, uint32_t opc,
int rd, int rs, int rt)
{
- const char *opn = "cond move";
TCGv t0, t1, t2;
if (rd == 0) {
/* If no destination, treat it as a NOP. */
- MIPS_DEBUG("NOP");
return;
}
switch (opc) {
case OPC_MOVN:
tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
- opn = "movn";
break;
case OPC_MOVZ:
tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
- opn = "movz";
break;
case OPC_SELNEZ:
tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
- opn = "selnez";
break;
case OPC_SELEQZ:
tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
- opn = "seleqz";
break;
}
tcg_temp_free(t2);
tcg_temp_free(t1);
tcg_temp_free(t0);
-
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
}
/* Logic */
static void gen_logic(DisasContext *ctx, uint32_t opc,
int rd, int rs, int rt)
{
- const char *opn = "logic";
-
if (rd == 0) {
/* If no destination, treat it as a NOP. */
- MIPS_DEBUG("NOP");
return;
}
} else {
tcg_gen_movi_tl(cpu_gpr[rd], 0);
}
- opn = "and";
break;
case OPC_NOR:
if (rs != 0 && rt != 0) {
} else {
tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
}
- opn = "nor";
break;
case OPC_OR:
if (likely(rs != 0 && rt != 0)) {
} else {
tcg_gen_movi_tl(cpu_gpr[rd], 0);
}
- opn = "or";
break;
case OPC_XOR:
if (likely(rs != 0 && rt != 0)) {
} else {
tcg_gen_movi_tl(cpu_gpr[rd], 0);
}
- opn = "xor";
break;
}
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
}
/* Set on lower than */
static void gen_slt(DisasContext *ctx, uint32_t opc,
int rd, int rs, int rt)
{
- const char *opn = "slt";
TCGv t0, t1;
if (rd == 0) {
/* If no destination, treat it as a NOP. */
- MIPS_DEBUG("NOP");
return;
}
switch (opc) {
case OPC_SLT:
tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
- opn = "slt";
break;
case OPC_SLTU:
tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
- 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);
}
static void gen_shift(DisasContext *ctx, uint32_t opc,
int rd, int rs, int rt)
{
- const char *opn = "shifts";
TCGv t0, t1;
if (rd == 0) {
/* If no destination, treat it as a NOP.
For add & sub, we must generate the overflow exception when needed. */
- MIPS_DEBUG("NOP");
return;
}
tcg_gen_andi_tl(t0, t0, 0x1f);
tcg_gen_shl_tl(t0, t1, t0);
tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
- opn = "sllv";
break;
case OPC_SRAV:
tcg_gen_andi_tl(t0, t0, 0x1f);
tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
- opn = "srav";
break;
case OPC_SRLV:
tcg_gen_ext32u_tl(t1, t1);
tcg_gen_andi_tl(t0, t0, 0x1f);
tcg_gen_shr_tl(t0, t1, t0);
tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
- opn = "srlv";
break;
case OPC_ROTRV:
{
tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t3);
- opn = "rotrv";
}
break;
#if defined(TARGET_MIPS64)
case OPC_DSLLV:
tcg_gen_andi_tl(t0, t0, 0x3f);
tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
- opn = "dsllv";
break;
case OPC_DSRAV:
tcg_gen_andi_tl(t0, t0, 0x3f);
tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
- opn = "dsrav";
break;
case OPC_DSRLV:
tcg_gen_andi_tl(t0, t0, 0x3f);
tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
- opn = "dsrlv";
break;
case OPC_DROTRV:
tcg_gen_andi_tl(t0, t0, 0x3f);
tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
- opn = "drotrv";
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);
}
/* Arithmetic on HI/LO registers */
static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
{
- const char *opn = "hilo";
-
if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
/* Treat as NOP. */
- MIPS_DEBUG("NOP");
return;
}
{
tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
}
- opn = "mfhi";
break;
case OPC_MFLO:
#if defined(TARGET_MIPS64)
{
tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
}
- opn = "mflo";
break;
case OPC_MTHI:
if (reg != 0) {
} else {
tcg_gen_movi_tl(cpu_HI[acc], 0);
}
- opn = "mthi";
break;
case OPC_MTLO:
if (reg != 0) {
} else {
tcg_gen_movi_tl(cpu_LO[acc], 0);
}
- opn = "mtlo";
break;
}
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s %s", opn, regnames[reg]);
}
static inline void gen_r6_ld(target_long addr, int reg, int memidx,
static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
{
- const char *opn = "r6 mul/div";
TCGv t0, t1;
if (rd == 0) {
/* Treat as NOP. */
- MIPS_DEBUG("NOP");
return;
}
tcg_temp_free(t3);
tcg_temp_free(t2);
}
- opn = "div";
break;
case R6_OPC_MOD:
{
tcg_temp_free(t3);
tcg_temp_free(t2);
}
- opn = "mod";
break;
case R6_OPC_DIVU:
{
tcg_temp_free(t3);
tcg_temp_free(t2);
}
- opn = "divu";
break;
case R6_OPC_MODU:
{
tcg_temp_free(t3);
tcg_temp_free(t2);
}
- opn = "modu";
break;
case R6_OPC_MUL:
{
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t3);
}
- opn = "mul";
break;
case R6_OPC_MUH:
{
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t3);
}
- opn = "muh";
break;
case R6_OPC_MULU:
{
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t3);
}
- opn = "mulu";
break;
case R6_OPC_MUHU:
{
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t3);
}
- opn = "muhu";
break;
#if defined(TARGET_MIPS64)
case R6_OPC_DDIV:
tcg_temp_free(t3);
tcg_temp_free(t2);
}
- opn = "ddiv";
break;
case R6_OPC_DMOD:
{
tcg_temp_free(t3);
tcg_temp_free(t2);
}
- opn = "dmod";
break;
case R6_OPC_DDIVU:
{
tcg_temp_free(t3);
tcg_temp_free(t2);
}
- opn = "ddivu";
break;
case R6_OPC_DMODU:
{
tcg_temp_free(t3);
tcg_temp_free(t2);
}
- opn = "dmodu";
break;
case R6_OPC_DMUL:
tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
- opn = "dmul";
break;
case R6_OPC_DMUH:
{
tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
tcg_temp_free(t2);
}
- opn = "dmuh";
break;
case R6_OPC_DMULU:
tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
- opn = "dmulu";
break;
case R6_OPC_DMUHU:
{
tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
tcg_temp_free(t2);
}
- opn = "dmuhu";
break;
#endif
default:
- MIPS_INVAL(opn);
+ MIPS_INVAL("r6 mul/div");
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);
tcg_temp_free(t1);
static void gen_muldiv(DisasContext *ctx, uint32_t opc,
int acc, int rs, int rt)
{
- const char *opn = "mul/div";
TCGv t0, t1;
t0 = tcg_temp_new();
tcg_temp_free(t3);
tcg_temp_free(t2);
}
- opn = "div";
break;
case OPC_DIVU:
{
tcg_temp_free(t3);
tcg_temp_free(t2);
}
- opn = "divu";
break;
case OPC_MULT:
{
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t3);
}
- opn = "mult";
break;
case OPC_MULTU:
{
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t3);
}
- opn = "multu";
break;
#if defined(TARGET_MIPS64)
case OPC_DDIV:
tcg_temp_free(t3);
tcg_temp_free(t2);
}
- opn = "ddiv";
break;
case OPC_DDIVU:
{
tcg_temp_free(t3);
tcg_temp_free(t2);
}
- opn = "ddivu";
break;
case OPC_DMULT:
tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
- opn = "dmult";
break;
case OPC_DMULTU:
tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
- opn = "dmultu";
break;
#endif
case OPC_MADD:
gen_move_high32(cpu_HI[acc], t2);
tcg_temp_free_i64(t2);
}
- opn = "madd";
break;
case OPC_MADDU:
{
gen_move_high32(cpu_HI[acc], t2);
tcg_temp_free_i64(t2);
}
- opn = "maddu";
break;
case OPC_MSUB:
{
gen_move_high32(cpu_HI[acc], t2);
tcg_temp_free_i64(t2);
}
- opn = "msub";
break;
case OPC_MSUBU:
{
gen_move_high32(cpu_HI[acc], t2);
tcg_temp_free_i64(t2);
}
- opn = "msubu";
break;
default:
- MIPS_INVAL(opn);
+ MIPS_INVAL("mul/div");
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);
tcg_temp_free(t1);
static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
int rd, int rs, int rt)
{
- const char *opn = "mul vr54xx";
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
switch (opc) {
case OPC_VR54XX_MULS:
gen_helper_muls(t0, cpu_env, t0, t1);
- opn = "muls";
break;
case OPC_VR54XX_MULSU:
gen_helper_mulsu(t0, cpu_env, t0, t1);
- opn = "mulsu";
break;
case OPC_VR54XX_MACC:
gen_helper_macc(t0, cpu_env, t0, t1);
- opn = "macc";
break;
case OPC_VR54XX_MACCU:
gen_helper_maccu(t0, cpu_env, t0, t1);
- opn = "maccu";
break;
case OPC_VR54XX_MSAC:
gen_helper_msac(t0, cpu_env, t0, t1);
- opn = "msac";
break;
case OPC_VR54XX_MSACU:
gen_helper_msacu(t0, cpu_env, t0, t1);
- opn = "msacu";
break;
case OPC_VR54XX_MULHI:
gen_helper_mulhi(t0, cpu_env, t0, t1);
- opn = "mulhi";
break;
case OPC_VR54XX_MULHIU:
gen_helper_mulhiu(t0, cpu_env, t0, t1);
- opn = "mulhiu";
break;
case OPC_VR54XX_MULSHI:
gen_helper_mulshi(t0, cpu_env, t0, t1);
- opn = "mulshi";
break;
case OPC_VR54XX_MULSHIU:
gen_helper_mulshiu(t0, cpu_env, t0, t1);
- opn = "mulshiu";
break;
case OPC_VR54XX_MACCHI:
gen_helper_macchi(t0, cpu_env, t0, t1);
- opn = "macchi";
break;
case OPC_VR54XX_MACCHIU:
gen_helper_macchiu(t0, cpu_env, t0, t1);
- opn = "macchiu";
break;
case OPC_VR54XX_MSACHI:
gen_helper_msachi(t0, cpu_env, t0, t1);
- opn = "msachi";
break;
case OPC_VR54XX_MSACHIU:
gen_helper_msachiu(t0, cpu_env, t0, t1);
- opn = "msachiu";
break;
default:
MIPS_INVAL("mul vr54xx");
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:
tcg_temp_free(t0);
static void gen_cl (DisasContext *ctx, uint32_t opc,
int rd, int rs)
{
- const char *opn = "CLx";
TCGv t0;
if (rd == 0) {
/* Treat as NOP. */
- MIPS_DEBUG("NOP");
return;
}
t0 = tcg_temp_new();
case OPC_CLO:
case R6_OPC_CLO:
gen_helper_clo(cpu_gpr[rd], t0);
- opn = "clo";
break;
case OPC_CLZ:
case R6_OPC_CLZ:
gen_helper_clz(cpu_gpr[rd], t0);
- opn = "clz";
break;
#if defined(TARGET_MIPS64)
case OPC_DCLO:
case R6_OPC_DCLO:
gen_helper_dclo(cpu_gpr[rd], t0);
- opn = "dclo";
break;
case OPC_DCLZ:
case R6_OPC_DCLZ:
gen_helper_dclz(cpu_gpr[rd], t0);
- opn = "dclz";
break;
#endif
}
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
tcg_temp_free(t0);
}
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;
}
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(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:
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:
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:
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:
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:
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:
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:
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:
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);
}
/* Loongson multimedia instructions */
static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
{
- const char *opn = "loongson_cp2";
uint32_t opc, shift_max;
TCGv_i64 t0, t1;
gen_load_fpr64(ctx, t1, rt);
#define LMI_HELPER(UP, LO) \
- case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
+ case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
#define LMI_HELPER_1(UP, LO) \
- case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
+ case OPC_##UP: gen_helper_##LO(t0, t0); break
#define LMI_DIRECT(UP, LO, OP) \
- case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
+ case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
switch (opc) {
LMI_HELPER(PADDSH, paddsh);
case OPC_PINSRH_0:
tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
- opn = "pinsrh_0";
break;
case OPC_PINSRH_1:
tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
- opn = "pinsrh_1";
break;
case OPC_PINSRH_2:
tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
- opn = "pinsrh_2";
break;
case OPC_PINSRH_3:
tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
- opn = "pinsrh_3";
break;
case OPC_PEXTRH:
tcg_gen_shli_i64(t1, t1, 4);
tcg_gen_shr_i64(t0, t0, t1);
tcg_gen_ext16u_i64(t0, t0);
- opn = "pextrh";
break;
case OPC_ADDU_CP2:
tcg_gen_add_i64(t0, t0, t1);
tcg_gen_ext32s_i64(t0, t0);
- opn = "addu";
break;
case OPC_SUBU_CP2:
tcg_gen_sub_i64(t0, t0, t1);
tcg_gen_ext32s_i64(t0, t0);
- opn = "addu";
break;
case OPC_SLL_CP2:
- opn = "sll";
shift_max = 32;
goto do_shift;
case OPC_SRL_CP2:
- opn = "srl";
shift_max = 32;
goto do_shift;
case OPC_SRA_CP2:
- opn = "sra";
shift_max = 32;
goto do_shift;
case OPC_DSLL_CP2:
- opn = "dsll";
shift_max = 64;
goto do_shift;
case OPC_DSRL_CP2:
- opn = "dsrl";
shift_max = 64;
goto do_shift;
case OPC_DSRA_CP2:
- opn = "dsra";
shift_max = 64;
goto do_shift;
do_shift:
tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
generate_exception(ctx, EXCP_OVERFLOW);
gen_set_label(lab);
-
- opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
break;
}
tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
generate_exception(ctx, EXCP_OVERFLOW);
gen_set_label(lab);
-
- opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
break;
}
tcg_gen_ext32u_i64(t0, t0);
tcg_gen_ext32u_i64(t1, t1);
tcg_gen_mul_i64(t0, t0, t1);
- opn = "pmuluw";
break;
case OPC_SEQU_CP2:
/* ??? Document is unclear: Set FCC[CC]. Does that mean the
FD field is the CC field? */
default:
- MIPS_INVAL(opn);
+ MIPS_INVAL("loongson_cp2");
generate_exception(ctx, EXCP_RI);
return;
}
gen_store_fpr64(ctx, t0, rd);
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s %s, %s, %s", opn,
- fregnames[rd], fregnames[rs], fregnames[rt]);
tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1);
}
case OPC_BLEZL: /* 0 <= 0 likely */
/* Always take */
ctx->hflags |= MIPS_HFLAG_B;
- MIPS_DEBUG("balways");
break;
case OPC_BGEZAL: /* 0 >= 0 */
case OPC_BGEZALL: /* 0 >= 0 likely */
/* Always take and link */
blink = 31;
ctx->hflags |= MIPS_HFLAG_B;
- MIPS_DEBUG("balways and link");
break;
case OPC_BNE: /* rx != rx */
case OPC_BGTZ: /* 0 > 0 */
case OPC_BLTZ: /* 0 < 0 */
/* Treat as NOP. */
- MIPS_DEBUG("bnever (NOP)");
goto out;
case OPC_BLTZAL: /* 0 < 0 */
/* Handle as an unconditional branch to get correct delay
blink = 31;
btgt = ctx->pc + insn_bytes + delayslot_size;
ctx->hflags |= MIPS_HFLAG_B;
- MIPS_DEBUG("bnever and link");
break;
case OPC_BLTZALL: /* 0 < 0 likely */
tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
/* Skip the instruction in the delay slot */
- MIPS_DEBUG("bnever, link and skip");
ctx->pc += 4;
goto out;
case OPC_BNEL: /* rx != rx likely */
case OPC_BGTZL: /* 0 > 0 likely */
case OPC_BLTZL: /* 0 < 0 likely */
/* Skip the instruction in the delay slot */
- MIPS_DEBUG("bnever and skip");
ctx->pc += 4;
goto out;
case OPC_J:
ctx->hflags |= MIPS_HFLAG_B;
- MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
break;
case OPC_JALX:
ctx->hflags |= MIPS_HFLAG_BX;
case OPC_JAL:
blink = 31;
ctx->hflags |= MIPS_HFLAG_B;
- MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
break;
case OPC_JR:
ctx->hflags |= MIPS_HFLAG_BR;
- MIPS_DEBUG("jr %s", regnames[rs]);
break;
case OPC_JALR:
blink = rt;
ctx->hflags |= MIPS_HFLAG_BR;
- MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
break;
default:
MIPS_INVAL("branch/jump");
switch (opc) {
case OPC_BEQ:
tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
- MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
- regnames[rs], regnames[rt], btgt);
goto not_likely;
case OPC_BEQL:
tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
- MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
- regnames[rs], regnames[rt], btgt);
goto likely;
case OPC_BNE:
tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
- MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
- regnames[rs], regnames[rt], btgt);
goto not_likely;
case OPC_BNEL:
tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
- MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
- regnames[rs], regnames[rt], btgt);
goto likely;
case OPC_BGEZ:
tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
- MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
goto not_likely;
case OPC_BGEZL:
tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
- MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
goto likely;
case OPC_BGEZAL:
tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
- MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
blink = 31;
goto not_likely;
case OPC_BGEZALL:
tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
blink = 31;
- MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
goto likely;
case OPC_BGTZ:
tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
- MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
goto not_likely;
case OPC_BGTZL:
tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
- MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
goto likely;
case OPC_BLEZ:
tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
- MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
goto not_likely;
case OPC_BLEZL:
tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
- MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
goto likely;
case OPC_BLTZ:
tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
- MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
goto not_likely;
case OPC_BLTZL:
tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
- MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
goto likely;
case OPC_BPOSGE32:
tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
- MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt);
goto not_likely;
#if defined(TARGET_MIPS64)
case OPC_BPOSGE64:
tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
- MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
goto not_likely;
#endif
case OPC_BLTZAL:
tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
blink = 31;
- MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
not_likely:
ctx->hflags |= MIPS_HFLAG_BC;
break;
case OPC_BLTZALL:
tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
blink = 31;
- MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
likely:
ctx->hflags |= MIPS_HFLAG_BL;
break;
goto out;
}
}
- MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
- blink, ctx->hflags, btgt);
ctx->btarget = btgt;
if (rd == 0) {
/* If no destination, treat it as a NOP. */
- MIPS_DEBUG("NOP");
return;
}
case OPC_ERET: /* OPC_ERETNC */
if ((ctx->insn_flags & ISA_MIPS32R6) &&
(ctx->hflags & MIPS_HFLAG_BMASK)) {
- MIPS_DEBUG("CTI in delay / forbidden slot");
goto die;
} else {
int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
check_insn(ctx, ISA_MIPS32);
if ((ctx->insn_flags & ISA_MIPS32R6) &&
(ctx->hflags & MIPS_HFLAG_BMASK)) {
- MIPS_DEBUG("CTI in delay / forbidden slot");
goto die;
}
if (!(ctx->hflags & MIPS_HFLAG_DM)) {
check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
if ((ctx->insn_flags & ISA_MIPS32R6) &&
(ctx->hflags & MIPS_HFLAG_BMASK)) {
- MIPS_DEBUG("CTI in delay / forbidden slot");
goto die;
}
/* If we get an exception, we want to restart at next instruction */
return;
}
(void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
}
#endif /* !CONFIG_USER_ONLY */
int32_t cc, int32_t offset)
{
target_ulong btarget;
- const char *opn = "cp1 cond branch";
TCGv_i32 t0 = tcg_temp_new_i32();
if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
- MIPS_DEBUG("CTI in delay / forbidden slot");
generate_exception(ctx, EXCP_RI);
goto out;
}
tcg_gen_not_i32(t0, t0);
tcg_gen_andi_i32(t0, t0, 1);
tcg_gen_extu_i32_tl(bcond, t0);
- opn = "bc1f";
goto not_likely;
case OPC_BC1FL:
tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
tcg_gen_not_i32(t0, t0);
tcg_gen_andi_i32(t0, t0, 1);
tcg_gen_extu_i32_tl(bcond, t0);
- opn = "bc1fl";
goto likely;
case OPC_BC1T:
tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
tcg_gen_andi_i32(t0, t0, 1);
tcg_gen_extu_i32_tl(bcond, t0);
- opn = "bc1t";
goto not_likely;
case OPC_BC1TL:
tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
tcg_gen_andi_i32(t0, t0, 1);
tcg_gen_extu_i32_tl(bcond, t0);
- opn = "bc1tl";
likely:
ctx->hflags |= MIPS_HFLAG_BL;
break;
tcg_gen_andi_i32(t0, t0, 1);
tcg_gen_extu_i32_tl(bcond, t0);
}
- opn = "bc1any2f";
goto not_likely;
case OPC_BC1TANY2:
{
tcg_gen_andi_i32(t0, t0, 1);
tcg_gen_extu_i32_tl(bcond, t0);
}
- opn = "bc1any2t";
goto not_likely;
case OPC_BC1FANY4:
{
tcg_gen_andi_i32(t0, t0, 1);
tcg_gen_extu_i32_tl(bcond, t0);
}
- opn = "bc1any4f";
goto not_likely;
case OPC_BC1TANY4:
{
tcg_gen_andi_i32(t0, t0, 1);
tcg_gen_extu_i32_tl(bcond, t0);
}
- opn = "bc1any4t";
not_likely:
ctx->hflags |= MIPS_HFLAG_BC;
break;
default:
- MIPS_INVAL(opn);
+ MIPS_INVAL("cp1 cond branch");
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;
ctx->hflags |= MIPS_HFLAG_BDS32;
out:
int delayslot_size)
{
target_ulong btarget;
- const char *opn = "cp1 cond branch";
TCGv_i64 t0 = tcg_temp_new_i64();
if (ctx->hflags & MIPS_HFLAG_BMASK) {
switch (op) {
case OPC_BC1EQZ:
tcg_gen_xori_i64(t0, t0, 1);
- opn = "bc1eqz";
ctx->hflags |= MIPS_HFLAG_BC;
break;
case OPC_BC1NEZ:
/* t0 already set */
- opn = "bc1nez";
ctx->hflags |= MIPS_HFLAG_BC;
break;
default:
- MIPS_INVAL(opn);
+ MIPS_INVAL("cp1 cond branch");
generate_exception(ctx, EXCP_RI);
goto out;
}
tcg_gen_trunc_i64_tl(bcond, t0);
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
- ctx->hflags, btarget);
ctx->btarget = btarget;
switch (delayslot_size) {
};
static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
{
- const char *opn = "cp1 move";
TCGv t0 = tcg_temp_new();
switch (opc) {
tcg_temp_free_i32(fp0);
}
gen_store_gpr(t0, rt);
- opn = "mfc1";
break;
case OPC_MTC1:
gen_load_gpr(t0, rt);
gen_store_fpr32(ctx, fp0, fs);
tcg_temp_free_i32(fp0);
}
- opn = "mtc1";
break;
case OPC_CFC1:
gen_helper_1e0i(cfc1, t0, fs);
gen_store_gpr(t0, rt);
- opn = "cfc1";
break;
case OPC_CTC1:
gen_load_gpr(t0, rt);
}
/* Stop translation as we may have changed hflags */
ctx->bstate = BS_STOP;
- opn = "ctc1";
break;
#if defined(TARGET_MIPS64)
case OPC_DMFC1:
gen_load_fpr64(ctx, t0, fs);
gen_store_gpr(t0, rt);
- opn = "dmfc1";
break;
case OPC_DMTC1:
gen_load_gpr(t0, rt);
gen_store_fpr64(ctx, t0, fs);
- opn = "dmtc1";
break;
#endif
case OPC_MFHC1:
tcg_temp_free_i32(fp0);
}
gen_store_gpr(t0, rt);
- opn = "mfhc1";
break;
case OPC_MTHC1:
gen_load_gpr(t0, rt);
gen_store_fpr32h(ctx, fp0, fs);
tcg_temp_free_i32(fp0);
}
- opn = "mthc1";
break;
default:
- MIPS_INVAL(opn);
+ MIPS_INVAL("cp1 move");
generate_exception (ctx, EXCP_RI);
goto out;
}
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
out:
tcg_temp_free(t0);
static void gen_farith (DisasContext *ctx, enum fopcode op1,
int ft, int fs, int fd, int cc)
{
- const char *opn = "farith";
- const char *condnames[] = {
- "c.f",
- "c.un",
- "c.eq",
- "c.ueq",
- "c.olt",
- "c.ult",
- "c.ole",
- "c.ule",
- "c.sf",
- "c.ngle",
- "c.seq",
- "c.ngl",
- "c.lt",
- "c.nge",
- "c.le",
- "c.ngt",
- };
- const char *condnames_abs[] = {
- "cabs.f",
- "cabs.un",
- "cabs.eq",
- "cabs.ueq",
- "cabs.olt",
- "cabs.ult",
- "cabs.ole",
- "cabs.ule",
- "cabs.sf",
- "cabs.ngle",
- "cabs.seq",
- "cabs.ngl",
- "cabs.lt",
- "cabs.nge",
- "cabs.le",
- "cabs.ngt",
- };
- enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
uint32_t func = ctx->opcode & 0x3f;
switch (op1) {
case OPC_ADD_S:
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "add.s";
- optype = BINOP;
break;
case OPC_SUB_S:
{
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "sub.s";
- optype = BINOP;
break;
case OPC_MUL_S:
{
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "mul.s";
- optype = BINOP;
break;
case OPC_DIV_S:
{
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "div.s";
- optype = BINOP;
break;
case OPC_SQRT_S:
{
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "sqrt.s";
break;
case OPC_ABS_S:
{
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "abs.s";
break;
case OPC_MOV_S:
{
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "mov.s";
break;
case OPC_NEG_S:
{
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "neg.s";
break;
case OPC_ROUND_L_S:
check_cp1_64bitmode(ctx);
gen_store_fpr64(ctx, fp64, fd);
tcg_temp_free_i64(fp64);
}
- opn = "round.l.s";
break;
case OPC_TRUNC_L_S:
check_cp1_64bitmode(ctx);
gen_store_fpr64(ctx, fp64, fd);
tcg_temp_free_i64(fp64);
}
- opn = "trunc.l.s";
break;
case OPC_CEIL_L_S:
check_cp1_64bitmode(ctx);
gen_store_fpr64(ctx, fp64, fd);
tcg_temp_free_i64(fp64);
}
- opn = "ceil.l.s";
break;
case OPC_FLOOR_L_S:
check_cp1_64bitmode(ctx);
gen_store_fpr64(ctx, fp64, fd);
tcg_temp_free_i64(fp64);
}
- opn = "floor.l.s";
break;
case OPC_ROUND_W_S:
{
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "round.w.s";
break;
case OPC_TRUNC_W_S:
{
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "trunc.w.s";
break;
case OPC_CEIL_W_S:
{
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "ceil.w.s";
break;
case OPC_FLOOR_W_S:
{
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "floor.w.s";
break;
case OPC_SEL_S:
check_insn(ctx, ISA_MIPS32R6);
gen_sel_s(ctx, op1, fd, ft, fs);
- opn = "sel.s";
break;
case OPC_SELEQZ_S:
check_insn(ctx, ISA_MIPS32R6);
gen_sel_s(ctx, op1, fd, ft, fs);
- opn = "seleqz.s";
break;
case OPC_SELNEZ_S:
check_insn(ctx, ISA_MIPS32R6);
gen_sel_s(ctx, op1, fd, ft, fs);
- opn = "selnez.s";
break;
case OPC_MOVCF_S:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
- opn = "movcf.s";
break;
case OPC_MOVZ_S:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
tcg_temp_free_i32(fp0);
gen_set_label(l1);
}
- opn = "movz.s";
break;
case OPC_MOVN_S:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
gen_set_label(l1);
}
}
- opn = "movn.s";
break;
case OPC_RECIP_S:
{
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "recip.s";
break;
case OPC_RSQRT_S:
{
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "rsqrt.s";
break;
case OPC_MADDF_S:
check_insn(ctx, ISA_MIPS32R6);
tcg_temp_free_i32(fp2);
tcg_temp_free_i32(fp1);
tcg_temp_free_i32(fp0);
- opn = "maddf.s";
}
break;
case OPC_MSUBF_S:
tcg_temp_free_i32(fp2);
tcg_temp_free_i32(fp1);
tcg_temp_free_i32(fp0);
- opn = "msubf.s";
}
break;
case OPC_RINT_S:
gen_helper_float_rint_s(fp0, cpu_env, fp0);
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
- opn = "rint.s";
}
break;
case OPC_CLASS_S:
gen_helper_float_class_s(fp0, fp0);
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
- opn = "class.s";
}
break;
case OPC_MIN_S: /* OPC_RECIP2_S */
tcg_temp_free_i32(fp2);
tcg_temp_free_i32(fp1);
tcg_temp_free_i32(fp0);
- opn = "min.s";
} else {
/* OPC_RECIP2_S */
check_cp1_64bitmode(ctx);
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "recip2.s";
}
break;
case OPC_MINA_S: /* OPC_RECIP1_S */
tcg_temp_free_i32(fp2);
tcg_temp_free_i32(fp1);
tcg_temp_free_i32(fp0);
- opn = "mina.s";
} else {
/* OPC_RECIP1_S */
check_cp1_64bitmode(ctx);
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "recip1.s";
}
break;
case OPC_MAX_S: /* OPC_RSQRT1_S */
gen_store_fpr32(ctx, fp1, fd);
tcg_temp_free_i32(fp1);
tcg_temp_free_i32(fp0);
- opn = "max.s";
} else {
/* OPC_RSQRT1_S */
check_cp1_64bitmode(ctx);
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "rsqrt1.s";
}
break;
case OPC_MAXA_S: /* OPC_RSQRT2_S */
gen_store_fpr32(ctx, fp1, fd);
tcg_temp_free_i32(fp1);
tcg_temp_free_i32(fp0);
- opn = "maxa.s";
} else {
/* OPC_RSQRT2_S */
check_cp1_64bitmode(ctx);
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "rsqrt2.s";
}
break;
case OPC_CVT_D_S:
gen_store_fpr64(ctx, fp64, fd);
tcg_temp_free_i64(fp64);
}
- opn = "cvt.d.s";
break;
case OPC_CVT_W_S:
{
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "cvt.w.s";
break;
case OPC_CVT_L_S:
check_cp1_64bitmode(ctx);
gen_store_fpr64(ctx, fp64, fd);
tcg_temp_free_i64(fp64);
}
- opn = "cvt.l.s";
break;
case OPC_CVT_PS_S:
check_ps(ctx);
gen_store_fpr64(ctx, fp64, fd);
tcg_temp_free_i64(fp64);
}
- opn = "cvt.ps.s";
break;
case OPC_CMP_F_S:
case OPC_CMP_UN_S:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
if (ctx->opcode & (1 << 6)) {
gen_cmpabs_s(ctx, func-48, ft, fs, cc);
- opn = condnames_abs[func-48];
} else {
gen_cmp_s(ctx, func-48, ft, fs, cc);
- opn = condnames[func-48];
}
- optype = CMPOP;
break;
case OPC_ADD_D:
check_cp1_registers(ctx, fs | ft | fd);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "add.d";
- optype = BINOP;
break;
case OPC_SUB_D:
check_cp1_registers(ctx, fs | ft | fd);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "sub.d";
- optype = BINOP;
break;
case OPC_MUL_D:
check_cp1_registers(ctx, fs | ft | fd);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "mul.d";
- optype = BINOP;
break;
case OPC_DIV_D:
check_cp1_registers(ctx, fs | ft | fd);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "div.d";
- optype = BINOP;
break;
case OPC_SQRT_D:
check_cp1_registers(ctx, fs | fd);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "sqrt.d";
break;
case OPC_ABS_D:
check_cp1_registers(ctx, fs | fd);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "abs.d";
break;
case OPC_MOV_D:
check_cp1_registers(ctx, fs | fd);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "mov.d";
break;
case OPC_NEG_D:
check_cp1_registers(ctx, fs | fd);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "neg.d";
break;
case OPC_ROUND_L_D:
check_cp1_64bitmode(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "round.l.d";
break;
case OPC_TRUNC_L_D:
check_cp1_64bitmode(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "trunc.l.d";
break;
case OPC_CEIL_L_D:
check_cp1_64bitmode(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "ceil.l.d";
break;
case OPC_FLOOR_L_D:
check_cp1_64bitmode(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "floor.l.d";
break;
case OPC_ROUND_W_D:
check_cp1_registers(ctx, fs);
gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
}
- opn = "round.w.d";
break;
case OPC_TRUNC_W_D:
check_cp1_registers(ctx, fs);
gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
}
- opn = "trunc.w.d";
break;
case OPC_CEIL_W_D:
check_cp1_registers(ctx, fs);
gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
}
- opn = "ceil.w.d";
break;
case OPC_FLOOR_W_D:
check_cp1_registers(ctx, fs);
gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
}
- opn = "floor.w.d";
break;
case OPC_SEL_D:
check_insn(ctx, ISA_MIPS32R6);
gen_sel_d(ctx, op1, fd, ft, fs);
- opn = "sel.d";
break;
case OPC_SELEQZ_D:
check_insn(ctx, ISA_MIPS32R6);
gen_sel_d(ctx, op1, fd, ft, fs);
- opn = "seleqz.d";
break;
case OPC_SELNEZ_D:
check_insn(ctx, ISA_MIPS32R6);
gen_sel_d(ctx, op1, fd, ft, fs);
- opn = "selnez.d";
break;
case OPC_MOVCF_D:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
- opn = "movcf.d";
break;
case OPC_MOVZ_D:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
tcg_temp_free_i64(fp0);
gen_set_label(l1);
}
- opn = "movz.d";
break;
case OPC_MOVN_D:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
gen_set_label(l1);
}
}
- opn = "movn.d";
break;
case OPC_RECIP_D:
check_cp1_registers(ctx, fs | fd);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "recip.d";
break;
case OPC_RSQRT_D:
check_cp1_registers(ctx, fs | fd);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "rsqrt.d";
break;
case OPC_MADDF_D:
check_insn(ctx, ISA_MIPS32R6);
tcg_temp_free_i64(fp2);
tcg_temp_free_i64(fp1);
tcg_temp_free_i64(fp0);
- opn = "maddf.d";
}
break;
case OPC_MSUBF_D:
tcg_temp_free_i64(fp2);
tcg_temp_free_i64(fp1);
tcg_temp_free_i64(fp0);
- opn = "msubf.d";
}
break;
case OPC_RINT_D:
gen_helper_float_rint_d(fp0, cpu_env, fp0);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
- opn = "rint.d";
}
break;
case OPC_CLASS_D:
gen_helper_float_class_d(fp0, fp0);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
- opn = "class.d";
}
break;
case OPC_MIN_D: /* OPC_RECIP2_D */
gen_store_fpr64(ctx, fp1, fd);
tcg_temp_free_i64(fp1);
tcg_temp_free_i64(fp0);
- opn = "min.d";
} else {
/* OPC_RECIP2_D */
check_cp1_64bitmode(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "recip2.d";
}
break;
case OPC_MINA_D: /* OPC_RECIP1_D */
gen_store_fpr64(ctx, fp1, fd);
tcg_temp_free_i64(fp1);
tcg_temp_free_i64(fp0);
- opn = "mina.d";
} else {
/* OPC_RECIP1_D */
check_cp1_64bitmode(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "recip1.d";
}
break;
case OPC_MAX_D: /* OPC_RSQRT1_D */
gen_store_fpr64(ctx, fp1, fd);
tcg_temp_free_i64(fp1);
tcg_temp_free_i64(fp0);
- opn = "max.d";
} else {
/* OPC_RSQRT1_D */
check_cp1_64bitmode(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "rsqrt1.d";
}
break;
case OPC_MAXA_D: /* OPC_RSQRT2_D */
gen_store_fpr64(ctx, fp1, fd);
tcg_temp_free_i64(fp1);
tcg_temp_free_i64(fp0);
- opn = "maxa.d";
} else {
/* OPC_RSQRT2_D */
check_cp1_64bitmode(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "rsqrt2.d";
}
break;
case OPC_CMP_F_D:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
if (ctx->opcode & (1 << 6)) {
gen_cmpabs_d(ctx, func-48, ft, fs, cc);
- opn = condnames_abs[func-48];
} else {
gen_cmp_d(ctx, func-48, ft, fs, cc);
- opn = condnames[func-48];
}
- optype = CMPOP;
break;
case OPC_CVT_S_D:
check_cp1_registers(ctx, fs);
gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
}
- opn = "cvt.s.d";
break;
case OPC_CVT_W_D:
check_cp1_registers(ctx, fs);
gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
}
- opn = "cvt.w.d";
break;
case OPC_CVT_L_D:
check_cp1_64bitmode(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "cvt.l.d";
break;
case OPC_CVT_S_W:
{
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "cvt.s.w";
break;
case OPC_CVT_D_W:
check_cp1_registers(ctx, fd);
gen_store_fpr64(ctx, fp64, fd);
tcg_temp_free_i64(fp64);
}
- opn = "cvt.d.w";
break;
case OPC_CVT_S_L:
check_cp1_64bitmode(ctx);
gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
}
- opn = "cvt.s.l";
break;
case OPC_CVT_D_L:
check_cp1_64bitmode(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "cvt.d.l";
break;
case OPC_CVT_PS_PW:
check_ps(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "cvt.ps.pw";
break;
case OPC_ADD_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "add.ps";
break;
case OPC_SUB_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "sub.ps";
break;
case OPC_MUL_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "mul.ps";
break;
case OPC_ABS_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "abs.ps";
break;
case OPC_MOV_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "mov.ps";
break;
case OPC_NEG_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "neg.ps";
break;
case OPC_MOVCF_PS:
check_ps(ctx);
gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
- opn = "movcf.ps";
break;
case OPC_MOVZ_PS:
check_ps(ctx);
tcg_temp_free_i64(fp0);
gen_set_label(l1);
}
- opn = "movz.ps";
break;
case OPC_MOVN_PS:
check_ps(ctx);
gen_set_label(l1);
}
}
- opn = "movn.ps";
break;
case OPC_ADDR_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "addr.ps";
break;
case OPC_MULR_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "mulr.ps";
break;
case OPC_RECIP2_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "recip2.ps";
break;
case OPC_RECIP1_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "recip1.ps";
break;
case OPC_RSQRT1_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "rsqrt1.ps";
break;
case OPC_RSQRT2_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "rsqrt2.ps";
break;
case OPC_CVT_S_PU:
check_cp1_64bitmode(ctx);
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "cvt.s.pu";
break;
case OPC_CVT_PW_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "cvt.pw.ps";
break;
case OPC_CVT_S_PL:
check_cp1_64bitmode(ctx);
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "cvt.s.pl";
break;
case OPC_PLL_PS:
check_ps(ctx);
tcg_temp_free_i32(fp0);
tcg_temp_free_i32(fp1);
}
- opn = "pll.ps";
break;
case OPC_PLU_PS:
check_ps(ctx);
tcg_temp_free_i32(fp0);
tcg_temp_free_i32(fp1);
}
- opn = "plu.ps";
break;
case OPC_PUL_PS:
check_ps(ctx);
tcg_temp_free_i32(fp0);
tcg_temp_free_i32(fp1);
}
- opn = "pul.ps";
break;
case OPC_PUU_PS:
check_ps(ctx);
tcg_temp_free_i32(fp0);
tcg_temp_free_i32(fp1);
}
- opn = "puu.ps";
break;
case OPC_CMP_F_PS:
case OPC_CMP_UN_PS:
case OPC_CMP_NGT_PS:
if (ctx->opcode & (1 << 6)) {
gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
- opn = condnames_abs[func-48];
} else {
gen_cmp_ps(ctx, func-48, ft, fs, cc);
- opn = condnames[func-48];
}
- optype = CMPOP;
break;
default:
- MIPS_INVAL(opn);
+ MIPS_INVAL("farith");
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;
- case CMPOP:
- MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
- break;
- default:
- MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
- break;
- }
}
/* Coprocessor 3 (FPU) */
static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
int fd, int fs, int base, int index)
{
- const char *opn = "extended float load/store";
- int store = 0;
TCGv t0 = tcg_temp_new();
if (base == 0) {
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
- opn = "lwxc1";
break;
case OPC_LDXC1:
check_cop1x(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "ldxc1";
break;
case OPC_LUXC1:
check_cp1_64bitmode(ctx);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
- opn = "luxc1";
break;
case OPC_SWXC1:
check_cop1x(ctx);
tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
tcg_temp_free_i32(fp0);
}
- opn = "swxc1";
- store = 1;
break;
case OPC_SDXC1:
check_cop1x(ctx);
tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
tcg_temp_free_i64(fp0);
}
- opn = "sdxc1";
- store = 1;
break;
case OPC_SUXC1:
check_cp1_64bitmode(ctx);
tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
tcg_temp_free_i64(fp0);
}
- opn = "suxc1";
- store = 1;
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]);
}
static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
int fd, int fr, int fs, int ft)
{
- const char *opn = "flt3_arith";
-
switch (opc) {
case OPC_ALNV_PS:
check_ps(ctx);
tcg_temp_free_i32(fp);
tcg_temp_free_i32(fph);
}
- opn = "alnv.ps";
break;
case OPC_MADD_S:
check_cop1x(ctx);
gen_store_fpr32(ctx, fp2, fd);
tcg_temp_free_i32(fp2);
}
- opn = "madd.s";
break;
case OPC_MADD_D:
check_cop1x(ctx);
gen_store_fpr64(ctx, fp2, fd);
tcg_temp_free_i64(fp2);
}
- opn = "madd.d";
break;
case OPC_MADD_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp2, fd);
tcg_temp_free_i64(fp2);
}
- opn = "madd.ps";
break;
case OPC_MSUB_S:
check_cop1x(ctx);
gen_store_fpr32(ctx, fp2, fd);
tcg_temp_free_i32(fp2);
}
- opn = "msub.s";
break;
case OPC_MSUB_D:
check_cop1x(ctx);
gen_store_fpr64(ctx, fp2, fd);
tcg_temp_free_i64(fp2);
}
- opn = "msub.d";
break;
case OPC_MSUB_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp2, fd);
tcg_temp_free_i64(fp2);
}
- opn = "msub.ps";
break;
case OPC_NMADD_S:
check_cop1x(ctx);
gen_store_fpr32(ctx, fp2, fd);
tcg_temp_free_i32(fp2);
}
- opn = "nmadd.s";
break;
case OPC_NMADD_D:
check_cop1x(ctx);
gen_store_fpr64(ctx, fp2, fd);
tcg_temp_free_i64(fp2);
}
- opn = "nmadd.d";
break;
case OPC_NMADD_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp2, fd);
tcg_temp_free_i64(fp2);
}
- opn = "nmadd.ps";
break;
case OPC_NMSUB_S:
check_cop1x(ctx);
gen_store_fpr32(ctx, fp2, fd);
tcg_temp_free_i32(fp2);
}
- opn = "nmsub.s";
break;
case OPC_NMSUB_D:
check_cop1x(ctx);
gen_store_fpr64(ctx, fp2, fd);
tcg_temp_free_i64(fp2);
}
- opn = "nmsub.d";
break;
case OPC_NMSUB_PS:
check_ps(ctx);
gen_store_fpr64(ctx, fp2, fd);
tcg_temp_free_i64(fp2);
}
- opn = "nmsub.ps";
break;
default:
- MIPS_INVAL(opn);
+ MIPS_INVAL("flt3_arith");
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]);
}
static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
/* FIXME: Need to clear can_do_io. */
switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
case MIPS_HFLAG_FBNSLOT:
- MIPS_DEBUG("forbidden slot");
gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
break;
case MIPS_HFLAG_B:
/* unconditional branch */
- MIPS_DEBUG("unconditional branch");
if (proc_hflags & MIPS_HFLAG_BX) {
tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
}
break;
case MIPS_HFLAG_BL:
/* blikely taken case */
- MIPS_DEBUG("blikely branch taken");
gen_goto_tb(ctx, 0, ctx->btarget);
break;
case MIPS_HFLAG_BC:
/* Conditional branch */
- MIPS_DEBUG("conditional branch");
{
TCGLabel *l1 = gen_new_label();
break;
case MIPS_HFLAG_BR:
/* unconditional branch to register */
- MIPS_DEBUG("branch to register");
if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
TCGv t0 = tcg_temp_new();
TCGv_i32 t1 = tcg_temp_new_i32();
gen_set_label(fs);
ctx->hflags |= MIPS_HFLAG_FBNSLOT;
- MIPS_DEBUG("Compact conditional branch");
}
out:
static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
int base, int16_t offset)
{
- const char *opn = "ldst_multiple";
TCGv t0, t1;
TCGv_i32 t2;
switch (opc) {
case LWM32:
gen_helper_lwm(cpu_env, t0, t1, t2);
- opn = "lwm";
break;
case SWM32:
gen_helper_swm(cpu_env, t0, t1, t2);
- opn = "swm";
break;
#ifdef TARGET_MIPS64
case LDM:
gen_helper_ldm(cpu_env, t0, t1, t2);
- opn = "ldm";
break;
case SDM:
gen_helper_sdm(cpu_env, t0, t1, t2);
- opn = "sdm";
break;
#endif
}
- (void)opn;
- MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
tcg_temp_free(t0);
tcg_temp_free(t1);
tcg_temp_free_i32(t2);
static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
int base, int16_t offset)
{
- const char *opn = "ldst_pair";
TCGv t0, t1;
if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
gen_op_addr_add(ctx, t0, t0, t1);
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
gen_store_gpr(t1, rd+1);
- opn = "lwp";
break;
case SWP:
gen_load_gpr(t1, rd);
gen_op_addr_add(ctx, t0, t0, t1);
gen_load_gpr(t1, rd+1);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
- opn = "swp";
break;
#ifdef TARGET_MIPS64
case LDP:
gen_op_addr_add(ctx, t0, t0, t1);
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
gen_store_gpr(t1, rd+1);
- opn = "ldp";
break;
case SDP:
gen_load_gpr(t1, rd);
gen_op_addr_add(ctx, t0, t0, t1);
gen_load_gpr(t1, rd+1);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
- 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);
}
static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
int rd, int base, int offset)
{
- const char *opn = "ldx";
TCGv t0;
check_dsp(ctx);
case OPC_LBUX:
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
gen_store_gpr(t0, rd);
- opn = "lbux";
break;
case OPC_LHX:
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
gen_store_gpr(t0, rd);
- opn = "lhx";
break;
case OPC_LWX:
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
gen_store_gpr(t0, rd);
- opn = "lwx";
break;
#if defined(TARGET_MIPS64)
case OPC_LDX:
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
gen_store_gpr(t0, rd);
- opn = "ldx";
break;
#endif
}
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s %s, %s(%s)", opn,
- regnames[rd], regnames[offset], regnames[base]);
tcg_temp_free(t0);
}
static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
int ret, int v1, int v2)
{
- const char *opn = "mipsdsp arith";
TCGv v1_t;
TCGv v2_t;
if (ret == 0) {
/* Treat as NOP. */
- MIPS_DEBUG("NOP");
return;
}
tcg_temp_free(v1_t);
tcg_temp_free(v2_t);
-
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s", opn);
}
static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
int ret, int v1, int v2)
{
uint32_t op2;
- const char *opn = "mipsdsp shift";
TCGv t0;
TCGv v1_t;
TCGv v2_t;
if (ret == 0) {
/* Treat as NOP. */
- MIPS_DEBUG("NOP");
return;
}
tcg_temp_free(t0);
tcg_temp_free(v1_t);
tcg_temp_free(v2_t);
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s", opn);
}
static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
int ret, int v1, int v2, int check_ret)
{
- const char *opn = "mipsdsp multiply";
TCGv_i32 t0;
TCGv v1_t;
TCGv v2_t;
if ((ret == 0) && (check_ret == 1)) {
/* Treat as NOP. */
- MIPS_DEBUG("NOP");
return;
}
tcg_temp_free_i32(t0);
tcg_temp_free(v1_t);
tcg_temp_free(v2_t);
-
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s", opn);
-
}
static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
int ret, int val)
{
- const char *opn = "mipsdsp Bit/ Manipulation";
int16_t imm;
TCGv t0;
TCGv val_t;
if (ret == 0) {
/* Treat as NOP. */
- MIPS_DEBUG("NOP");
return;
}
}
tcg_temp_free(t0);
tcg_temp_free(val_t);
-
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s", opn);
}
static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
uint32_t op1, uint32_t op2,
int ret, int v1, int v2, int check_ret)
{
- const char *opn = "mipsdsp add compare pick";
TCGv t1;
TCGv v1_t;
TCGv v2_t;
if ((ret == 0) && (check_ret == 1)) {
/* Treat as NOP. */
- MIPS_DEBUG("NOP");
return;
}
tcg_temp_free(t1);
tcg_temp_free(v1_t);
tcg_temp_free(v2_t);
-
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s", opn);
}
static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
uint32_t op1, int rt, int rs, int sa)
{
- const char *opn = "mipsdsp append/dappend";
TCGv t0;
check_dspr2(ctx);
if (rt == 0) {
/* Treat as NOP. */
- MIPS_DEBUG("NOP");
return;
}
#endif
}
tcg_temp_free(t0);
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s", opn);
}
static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
int ret, int v1, int v2, int check_ret)
{
- const char *opn = "mipsdsp accumulator";
TCGv t0;
TCGv t1;
TCGv v1_t;
if ((ret == 0) && (check_ret == 1)) {
/* Treat as NOP. */
- MIPS_DEBUG("NOP");
return;
}
tcg_temp_free(t1);
tcg_temp_free(v1_t);
tcg_temp_free(v2_t);
-
- (void)opn; /* avoid a compiler warning */
- MIPS_DEBUG("%s", opn);
}
/* End MIPSDSP functions. */
rs == 0 && rt == 0) { /* PAUSE */
if ((ctx->insn_flags & ISA_MIPS32R6) &&
(ctx->hflags & MIPS_HFLAG_BMASK)) {
- MIPS_DEBUG("CTI in delay / forbidden slot");
generate_exception(ctx, EXCP_RI);
break;
}
TCGv t0, t1;
if (rt == 0) {
- MIPS_DEBUG("NOP");
break;
}
TCGv t0, t1;
if (rt == 0) {
- MIPS_DEBUG("NOP");
break;
}
check_dsp(ctx);
check_msa_access(ctx);
if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
- MIPS_DEBUG("CTI in delay / forbidden slot");
generate_exception(ctx, EXCP_RI);
return;
}
if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
TCGLabel *l1 = gen_new_label();
- MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
gen_goto_tb(ctx, 1, ctx->pc + 4);
if (rs != 0) {
tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
}
- MIPS_DEBUG("dahi %s, %04x", regnames[rs], imm);
break;
case OPC_DATI:
check_insn(ctx, ISA_MIPS32R6);
if (rs != 0) {
tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
}
- MIPS_DEBUG("dati %s, %04x", regnames[rs], imm);
break;
#endif
default: /* Invalid */
tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
tcg_temp_free(t0);
}
- MIPS_DEBUG("daui %s, %s, %04x", regnames[rt], regnames[rs], imm);
#else
generate_exception(ctx, EXCP_RI);
MIPS_INVAL("major opcode");