* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-
#include "cpu.h"
-#include "exec-all.h"
#include "disas.h"
#include "tcg-op.h"
-#include "qemu-common.h"
#include "helper.h"
#define GEN_HELPER 1
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 */
TCGv_i32 t2 = tcg_temp_new_i32();
TCGv_ptr addr = tcg_temp_new_ptr();
- tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
+ tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
tcg_gen_andi_i32(t2, t2, 0xf);
tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
TCGv_ptr addr = tcg_temp_new_ptr();
gen_load_gpr(t0, from);
- tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
+ tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
tcg_gen_andi_i32(t2, t2, 0xf);
tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
/* Floating point register moves. */
static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
{
- tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
+ tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
}
static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
{
- tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
+ tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
}
static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
{
- tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
+ tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
}
static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
{
- tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
+ tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
}
static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
{
if (ctx->hflags & MIPS_HFLAG_F64) {
- tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
+ tcg_gen_ld_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
} else {
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32();
static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
{
if (ctx->hflags & MIPS_HFLAG_F64) {
- tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
+ tcg_gen_st_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
} else {
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_i32 t1 = tcg_temp_new_i32();
}
}
-static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
+static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
{
ctx->saved_hflags = ctx->hflags;
switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
/* This code generates a "reserved instruction" exception if the
CPU does not support the instruction set corresponding to flags. */
-static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
+static inline void check_insn(CPUMIPSState *env, DisasContext *ctx, int flags)
{
if (unlikely(!(env->insn_flags & flags)))
generate_exception(ctx, EXCP_RI);
/* 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); \
tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
- tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
- tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval)); \
+ tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
+ tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
tcg_temp_free(t0); \
}
#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(); \
\
tcg_gen_andi_tl(t0, arg2, almask); \
tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
- tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
+ tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
generate_exception(ctx, EXCP_AdES); \
gen_set_label(l1); \
- tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
+ tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
- tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg)); \
- tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval)); \
+ tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
+ tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
gen_helper_0i(raise_exception, EXCP_SC); \
gen_set_label(l2); \
tcg_gen_movi_tl(t0, 0); \
}
#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 (CPUMIPSState *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);
}
-static void gen_cop1_ldst(CPUState *env, DisasContext *ctx,
+static void gen_cop1_ldst(CPUMIPSState *env, DisasContext *ctx,
uint32_t op, int rt, int rs, int16_t imm)
{
if (env->CP0_Config1 & (1 << CP0C1_FP)) {
}
/* Arithmetic with immediate operand */
-static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
+static void gen_arith_imm (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
int rt, int rs, int16_t imm)
{
target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
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 */
-static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
+static void gen_logic_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
{
target_ulong uimm;
const char *opn = "imm logic";
opn = "lui";
break;
}
+ (void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
}
/* Set on less than with immediate operand */
-static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
+static void gen_slt_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
{
target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
const char *opn = "imm arith";
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);
}
/* Shifts with immediate operand */
-static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
+static void gen_shift_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
int rt, int rs, int16_t imm)
{
target_ulong uimm = ((uint16_t)imm) & 0x1f;
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);
}
/* Arithmetic */
-static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
+static void gen_arith (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
int rd, int rs, int rt)
{
const char *opn = "arith";
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 (CPUState *env, uint32_t opc, int rd, int rs, int rt)
+static void gen_cond_move (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
{
const char *opn = "cond move";
int l1;
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]);
}
/* Logic */
-static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
+static void gen_logic (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
{
const char *opn = "logic";
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 (CPUState *env, uint32_t opc, int rd, int rs, int rt)
+static void gen_slt (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
{
const char *opn = "slt";
TCGv 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);
}
/* Shifts */
-static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
+static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
int rd, int rs, int rt)
{
const char *opn = "shifts";
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 */
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);
tcg_gen_st_tl(arg, cpu_env, off);
}
-static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
+static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
{
const char *rn = "invalid";
case 0:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
rn = "Index";
break;
case 1:
break;
case 1:
check_insn(env, ctx, ASE_MT);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
rn = "VPEControl";
break;
case 2:
check_insn(env, ctx, ASE_MT);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
rn = "VPEConf0";
break;
case 3:
check_insn(env, ctx, ASE_MT);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
rn = "VPEConf1";
break;
case 4:
check_insn(env, ctx, ASE_MT);
- gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
+ gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
rn = "YQMask";
break;
case 5:
check_insn(env, ctx, ASE_MT);
- gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
+ gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
rn = "VPESchedule";
break;
case 6:
check_insn(env, ctx, ASE_MT);
- gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
+ gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
rn = "VPEScheFBack";
break;
case 7:
check_insn(env, ctx, ASE_MT);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
rn = "VPEOpt";
break;
default:
case 2:
switch (sel) {
case 0:
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
tcg_gen_ext32s_tl(arg, arg);
rn = "EntryLo0";
break;
case 3:
switch (sel) {
case 0:
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
tcg_gen_ext32s_tl(arg, arg);
rn = "EntryLo1";
break;
case 4:
switch (sel) {
case 0:
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
tcg_gen_ext32s_tl(arg, arg);
rn = "Context";
break;
case 5:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
rn = "PageMask";
break;
case 1:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
rn = "PageGrain";
break;
default:
case 6:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
rn = "Wired";
break;
case 1:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
rn = "SRSConf0";
break;
case 2:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
rn = "SRSConf1";
break;
case 3:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
rn = "SRSConf2";
break;
case 4:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
rn = "SRSConf3";
break;
case 5:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
rn = "SRSConf4";
break;
default:
switch (sel) {
case 0:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
rn = "HWREna";
break;
default:
case 8:
switch (sel) {
case 0:
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
tcg_gen_ext32s_tl(arg, arg);
rn = "BadVAddr";
break;
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 */
case 10:
switch (sel) {
case 0:
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
tcg_gen_ext32s_tl(arg, arg);
rn = "EntryHi";
break;
case 11:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
rn = "Compare";
break;
/* 6,7 are implementation dependent */
case 12:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
rn = "Status";
break;
case 1:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
rn = "IntCtl";
break;
case 2:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
rn = "SRSCtl";
break;
case 3:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
rn = "SRSMap";
break;
default:
case 13:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
rn = "Cause";
break;
default:
case 14:
switch (sel) {
case 0:
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
tcg_gen_ext32s_tl(arg, arg);
rn = "EPC";
break;
case 15:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
rn = "PRid";
break;
case 1:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
rn = "EBase";
break;
default:
case 16:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
rn = "Config";
break;
case 1:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
rn = "Config1";
break;
case 2:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
rn = "Config2";
break;
case 3:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
rn = "Config3";
break;
/* 4,5 are reserved */
/* 6,7 are implementation dependent */
case 6:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
rn = "Config6";
break;
case 7:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
rn = "Config7";
break;
default:
case 0:
#if defined(TARGET_MIPS64)
check_insn(env, ctx, ISA_MIPS3);
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
tcg_gen_ext32s_tl(arg, arg);
rn = "XContext";
break;
/* Officially reserved, but sel 0 is used for R1x000 framemask */
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
rn = "Framemask";
break;
default:
switch (sel) {
case 0:
/* EJTAG support */
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
tcg_gen_ext32s_tl(arg, arg);
rn = "DEPC";
break;
case 25:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
rn = "Performance0";
break;
case 1:
case 2:
case 4:
case 6:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
rn = "TagLo";
break;
case 1:
case 3:
case 5:
case 7:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
rn = "DataLo";
break;
default:
case 2:
case 4:
case 6:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
rn = "TagHi";
break;
case 1:
case 3:
case 5:
case 7:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
rn = "DataHi";
break;
default:
case 30:
switch (sel) {
case 0:
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
tcg_gen_ext32s_tl(arg, arg);
rn = "ErrorEPC";
break;
switch (sel) {
case 0:
/* EJTAG support */
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
rn = "DESAVE";
break;
default:
default:
goto die;
}
+ (void)rn; /* avoid a compiler warning */
LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
return;
generate_exception(ctx, EXCP_RI);
}
-static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
+static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
{
const char *rn = "invalid";
break;
case 5:
check_insn(env, ctx, ASE_MT);
- gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
+ gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
rn = "VPESchedule";
break;
case 6:
check_insn(env, ctx, ASE_MT);
- gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
+ gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
rn = "VPEScheFBack";
break;
case 7:
break;
case 3:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
+ gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
/* Stop translation as we may have switched the execution mode */
ctx->bstate = BS_STOP;
rn = "SRSMap";
case 14:
switch (sel) {
case 0:
- gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
+ gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
rn = "EPC";
break;
default:
switch (sel) {
case 0:
/* EJTAG support */
- gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
+ gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
rn = "DEPC";
break;
default:
case 30:
switch (sel) {
case 0:
- gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
+ gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
rn = "ErrorEPC";
break;
default:
switch (sel) {
case 0:
/* EJTAG support */
- gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
+ gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
rn = "DESAVE";
break;
default:
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) {
}
#if defined(TARGET_MIPS64)
-static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
+static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
{
const char *rn = "invalid";
case 0:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
rn = "Index";
break;
case 1:
break;
case 1:
check_insn(env, ctx, ASE_MT);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
rn = "VPEControl";
break;
case 2:
check_insn(env, ctx, ASE_MT);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
rn = "VPEConf0";
break;
case 3:
check_insn(env, ctx, ASE_MT);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
rn = "VPEConf1";
break;
case 4:
check_insn(env, ctx, ASE_MT);
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
rn = "YQMask";
break;
case 5:
check_insn(env, ctx, ASE_MT);
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
rn = "VPESchedule";
break;
case 6:
check_insn(env, ctx, ASE_MT);
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
rn = "VPEScheFBack";
break;
case 7:
check_insn(env, ctx, ASE_MT);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
rn = "VPEOpt";
break;
default:
case 2:
switch (sel) {
case 0:
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
rn = "EntryLo0";
break;
case 1:
case 3:
switch (sel) {
case 0:
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
rn = "EntryLo1";
break;
default:
case 4:
switch (sel) {
case 0:
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
rn = "Context";
break;
case 1:
case 5:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
rn = "PageMask";
break;
case 1:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
rn = "PageGrain";
break;
default:
case 6:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
rn = "Wired";
break;
case 1:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
rn = "SRSConf0";
break;
case 2:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
rn = "SRSConf1";
break;
case 3:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
rn = "SRSConf2";
break;
case 4:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
rn = "SRSConf3";
break;
case 5:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
rn = "SRSConf4";
break;
default:
switch (sel) {
case 0:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
rn = "HWREna";
break;
default:
case 8:
switch (sel) {
case 0:
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
rn = "BadVAddr";
break;
default:
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 */
case 10:
switch (sel) {
case 0:
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
rn = "EntryHi";
break;
default:
case 11:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
rn = "Compare";
break;
/* 6,7 are implementation dependent */
case 12:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
rn = "Status";
break;
case 1:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
rn = "IntCtl";
break;
case 2:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
rn = "SRSCtl";
break;
case 3:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
rn = "SRSMap";
break;
default:
case 13:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
rn = "Cause";
break;
default:
case 14:
switch (sel) {
case 0:
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
rn = "EPC";
break;
default:
case 15:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
rn = "PRid";
break;
case 1:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
rn = "EBase";
break;
default:
case 16:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
rn = "Config";
break;
case 1:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
rn = "Config1";
break;
case 2:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
rn = "Config2";
break;
case 3:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
rn = "Config3";
break;
/* 6,7 are implementation dependent */
case 6:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
rn = "Config6";
break;
case 7:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
rn = "Config7";
break;
default:
switch (sel) {
case 0:
check_insn(env, ctx, ISA_MIPS3);
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
rn = "XContext";
break;
default:
/* Officially reserved, but sel 0 is used for R1x000 framemask */
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
rn = "Framemask";
break;
default:
switch (sel) {
case 0:
/* EJTAG support */
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
rn = "DEPC";
break;
default:
case 25:
switch (sel) {
case 0:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
rn = "Performance0";
break;
case 1:
case 2:
case 4:
case 6:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
rn = "TagLo";
break;
case 1:
case 3:
case 5:
case 7:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
rn = "DataLo";
break;
default:
case 2:
case 4:
case 6:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
rn = "TagHi";
break;
case 1:
case 3:
case 5:
case 7:
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
rn = "DataHi";
break;
default:
case 30:
switch (sel) {
case 0:
- tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
rn = "ErrorEPC";
break;
default:
switch (sel) {
case 0:
/* EJTAG support */
- gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
rn = "DESAVE";
break;
default:
default:
goto die;
}
+ (void)rn; /* avoid a compiler warning */
LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
return;
generate_exception(ctx, EXCP_RI);
}
-static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
+static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
{
const char *rn = "invalid";
break;
case 5:
check_insn(env, ctx, ASE_MT);
- tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
+ tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
rn = "VPESchedule";
break;
case 6:
check_insn(env, ctx, ASE_MT);
- tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
+ tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
rn = "VPEScheFBack";
break;
case 7:
break;
case 3:
check_insn(env, ctx, ISA_MIPS32R2);
- gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
+ gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
/* Stop translation as we may have switched the execution mode */
ctx->bstate = BS_STOP;
rn = "SRSMap";
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:
case 14:
switch (sel) {
case 0:
- tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
+ tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
rn = "EPC";
break;
default:
switch (sel) {
case 0:
/* EJTAG support */
- tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
+ tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
rn = "DEPC";
break;
default:
case 30:
switch (sel) {
case 0:
- tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
+ tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
rn = "ErrorEPC";
break;
default:
switch (sel) {
case 0:
/* EJTAG support */
- gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
+ gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
rn = "DESAVE";
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) {
}
#endif /* TARGET_MIPS64 */
-static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
+static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
int u, int sel, int h)
{
int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
tcg_gen_movi_tl(t0, -1);
else if (u == 0) {
switch (rt) {
+ case 1:
+ switch (sel) {
+ case 1:
+ gen_helper_mftc0_vpecontrol(t0);
+ break;
+ case 2:
+ gen_helper_mftc0_vpeconf0(t0);
+ break;
+ default:
+ goto die;
+ break;
+ }
+ break;
case 2:
switch (sel) {
case 1:
gen_mfc0(env, ctx, t0, rt, sel);
break;
}
+ case 13:
+ switch (sel) {
+ case 0:
+ gen_helper_mftc0_cause(t0);
+ break;
+ default:
+ goto die;
+ break;
+ }
+ break;
+ case 14:
+ switch (sel) {
+ case 0:
+ gen_helper_mftc0_epc(t0);
+ break;
+ default:
+ goto die;
+ break;
+ }
+ break;
+ case 15:
+ switch (sel) {
+ case 1:
+ gen_helper_mftc0_ebase(t0);
+ break;
+ default:
+ goto die;
+ break;
+ }
+ break;
+ case 16:
+ switch (sel) {
+ case 0 ... 7:
+ gen_helper_mftc0_configx(t0, tcg_const_tl(sel));
+ break;
+ default:
+ goto die;
+ break;
+ }
+ break;
case 23:
switch (sel) {
case 0:
generate_exception(ctx, EXCP_RI);
}
-static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
+static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
int u, int sel, int h)
{
int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
/* NOP */ ;
else if (u == 0) {
switch (rd) {
+ case 1:
+ switch (sel) {
+ case 1:
+ gen_helper_mttc0_vpecontrol(t0);
+ break;
+ case 2:
+ gen_helper_mttc0_vpeconf0(t0);
+ break;
+ default:
+ goto die;
+ break;
+ }
+ break;
case 2:
switch (sel) {
case 1:
gen_mtc0(env, ctx, t0, rd, sel);
break;
}
+ case 13:
+ switch (sel) {
+ case 0:
+ gen_helper_mttc0_cause(t0);
+ break;
+ default:
+ goto die;
+ break;
+ }
+ break;
+ case 15:
+ switch (sel) {
+ case 1:
+ gen_helper_mttc0_ebase(t0);
+ break;
+ default:
+ goto die;
+ break;
+ }
+ break;
case 23:
switch (sel) {
case 0:
generate_exception(ctx, EXCP_RI);
}
-static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
+static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
{
const char *opn = "ldst";
+ check_cp0_enabled(ctx);
switch (opc) {
case OPC_MFC0:
if (rt == 0) {
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 */
/* CP1 Branches (before delay slot) */
-static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
+static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t op,
int32_t cc, int32_t offset)
{
target_ulong btarget;
TCGv_i32 t1 = tcg_temp_new_i32();
tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
- tcg_gen_nor_i32(t0, t0, t1);
+ tcg_gen_nand_i32(t0, t0, t1);
tcg_temp_free_i32(t1);
tcg_gen_andi_i32(t0, t0, 1);
tcg_gen_extu_i32_tl(bcond, t0);
TCGv_i32 t1 = tcg_temp_new_i32();
tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
- tcg_gen_or_i32(t0, t0, t1);
+ tcg_gen_and_i32(t0, t0, t1);
tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
- tcg_gen_or_i32(t0, t0, t1);
+ tcg_gen_and_i32(t0, t0, t1);
tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
- tcg_gen_nor_i32(t0, t0, t1);
+ tcg_gen_nand_i32(t0, t0, t1);
tcg_temp_free_i32(t1);
tcg_gen_andi_i32(t0, t0, 1);
tcg_gen_extu_i32_tl(bcond, t0);
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:
TCGv_i32 fp1 = tcg_temp_new_i32();
gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, fd);
+ gen_load_fpr32(fp1, ft);
gen_helper_float_recip2_s(fp0, fp0, fp1);
tcg_temp_free_i32(fp1);
gen_store_fpr32(fp0, fd);
gen_load_fpr32(fp32_0, fs);
gen_load_fpr32(fp32_1, ft);
- tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
+ tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
tcg_temp_free_i32(fp32_1);
tcg_temp_free_i32(fp32_0);
gen_store_fpr64(ctx, fp64, fd);
TCGv_i64 fp1 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp0, fs);
- gen_load_fpr64(ctx, fp1, fd);
+ gen_load_fpr64(ctx, fp1, ft);
gen_helper_float_recip2_ps(fp0, fp0, fp1);
tcg_temp_free_i64(fp1);
gen_store_fpr64(ctx, fp0, fd);
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]);
} else if (index == 0) {
gen_load_gpr(t0, base);
} else {
- gen_load_gpr(t0, index);
- gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
+ gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
}
/* Don't do NOP if destination is zero: we must perform the actual
memory access. */
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]);
}
static void
-gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
+gen_rdhwr (CPUMIPSState *env, DisasContext *ctx, int rt, int rd)
{
TCGv t0;
+#if !defined(CONFIG_USER_ONLY)
+ /* The Linux kernel will emulate rdhwr if it's not supported natively.
+ Therefore only check the ISA in system mode. */
check_insn(env, ctx, ISA_MIPS32R2);
+#endif
t0 = tcg_temp_new();
switch (rd) {
break;
case 29:
#if defined(CONFIG_USER_ONLY)
- tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
+ tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, tls_value));
gen_store_gpr(t0, rt);
break;
#else
tcg_temp_free(t0);
}
-static void handle_delay_slot (CPUState *env, DisasContext *ctx,
+static void handle_delay_slot (CPUMIPSState *env, DisasContext *ctx,
int insn_bytes)
{
if (ctx->hflags & MIPS_HFLAG_BMASK) {
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)
}
#if defined(TARGET_MIPS64)
-static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
+static void decode_i64_mips16 (CPUMIPSState *env, DisasContext *ctx,
int ry, int funct, int16_t offset,
int extended)
{
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:
}
#endif
-static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
+static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
int *is_branch)
{
int extend = lduw_code(ctx->pc + 2);
#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:
return 4;
}
-static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
+static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
int *is_branch)
{
int rx, ry;
#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:
{
/* Zero-extended immediate */
#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
-static void gen_addiur1sp (CPUState *env, DisasContext *ctx)
+static void gen_addiur1sp (CPUMIPSState *env, DisasContext *ctx)
{
int rd = mmreg(uMIPS_RD(ctx->opcode));
gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
}
-static void gen_addiur2 (CPUState *env, DisasContext *ctx)
+static void gen_addiur2 (CPUMIPSState *env, DisasContext *ctx)
{
static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
int rd = mmreg(uMIPS_RD(ctx->opcode));
gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
}
-static void gen_addiusp (CPUState *env, DisasContext *ctx)
+static void gen_addiusp (CPUMIPSState *env, DisasContext *ctx)
{
int encoded = ZIMM(ctx->opcode, 1, 9);
int decoded;
gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
}
-static void gen_addius5 (CPUState *env, DisasContext *ctx)
+static void gen_addius5 (CPUMIPSState *env, DisasContext *ctx)
{
int imm = SIMM(ctx->opcode, 1, 4);
int rd = (ctx->opcode >> 5) & 0x1f;
gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
}
-static void gen_andi16 (CPUState *env, DisasContext *ctx)
+static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx)
{
static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
31, 32, 63, 64, 255, 32768, 65535 };
}
-static void gen_pool16c_insn (CPUState *env, DisasContext *ctx, int *is_branch)
+static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
{
int rd = mmreg((ctx->opcode >> 3) & 0x7);
int rs = mmreg(ctx->opcode & 0x7);
}
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);
const char *opn = "ldst_pair";
TCGv t0, t1;
- if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) {
+ if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
generate_exception(ctx, EXCP_RI);
return;
}
switch (opc) {
case LWP:
+ if (rd == base) {
+ generate_exception(ctx, EXCP_RI);
+ return;
+ }
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:
+ if (rd == base) {
+ generate_exception(ctx, EXCP_RI);
+ return;
+ }
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);
}
-static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
+static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
int *is_branch)
{
int extension = (ctx->opcode >> 6) & 0x3f;
#ifndef CONFIG_USER_ONLY
case MFC0:
case MFC0 + 32:
+ check_cp0_enabled(ctx);
if (rt == 0) {
/* Treat as NOP. */
break;
break;
case MTC0:
case MTC0 + 32:
+ check_cp0_enabled(ctx);
{
TCGv t0 = tcg_temp_new();
case 0x05:
switch (minor) {
case RDPGPR:
+ check_cp0_enabled(ctx);
check_insn(env, ctx, ISA_MIPS32R2);
gen_load_srsgpr(rt, rs);
break;
case WRPGPR:
+ check_cp0_enabled(ctx);
check_insn(env, ctx, ISA_MIPS32R2);
gen_store_srsgpr(rt, rs);
break;
case 0x1d:
switch (minor) {
case DI:
+ check_cp0_enabled(ctx);
{
TCGv t0 = tcg_temp_new();
}
break;
case EI:
+ check_cp0_enabled(ctx);
{
TCGv t0 = tcg_temp_new();
FMT_DWL_L = 2
};
-static void gen_pool32fxf (CPUState *env, DisasContext *ctx, int rt, int rs)
+static void gen_pool32fxf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
{
int extension = (ctx->opcode >> 6) & 0x3ff;
uint32_t mips32_op;
}
}
-static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
+static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
uint16_t insn_hw1, int *is_branch)
{
int32_t offset;
minor = (ctx->opcode >> 12) & 0xf;
switch (minor) {
case CACHE:
+ check_cp0_enabled(ctx);
/* Treat as no-op. */
break;
case LWC2:
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);
}
}
-static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branch)
+static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
{
uint32_t op;
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:
#endif
-static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
+static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
{
int32_t offset;
int rs, rt, rd, sa;
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);
break;
case OPC_CACHE:
+ check_cp0_enabled(ctx);
check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
/* Treat as NOP. */
break;
/* 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);
}
static inline void
-gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
+gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
int search_pc)
{
DisasContext ctx;
} 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:
#endif
}
-void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
{
gen_intermediate_code_internal(env, tb, 0);
}
-void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
{
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(CPUMIPSState *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]);
#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
static void
-cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
- int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
+ 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 (CPUMIPSState *env, FILE *f, fprintf_function cpu_fprintf,
int flags)
{
int i;
TCGV_UNUSED(cpu_gpr[0]);
for (i = 1; i < 32; i++)
cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUState, active_tc.gpr[i]),
+ offsetof(CPUMIPSState, active_tc.gpr[i]),
regnames[i]);
cpu_PC = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUState, active_tc.PC), "PC");
+ offsetof(CPUMIPSState, active_tc.PC), "PC");
for (i = 0; i < MIPS_DSP_ACC; i++) {
cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUState, active_tc.HI[i]),
+ offsetof(CPUMIPSState, active_tc.HI[i]),
regnames_HI[i]);
cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUState, active_tc.LO[i]),
+ offsetof(CPUMIPSState, active_tc.LO[i]),
regnames_LO[i]);
cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUState, active_tc.ACX[i]),
+ offsetof(CPUMIPSState, active_tc.ACX[i]),
regnames_ACX[i]);
}
cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUState, active_tc.DSPControl),
+ offsetof(CPUMIPSState, active_tc.DSPControl),
"DSPControl");
bcond = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUState, bcond), "bcond");
+ offsetof(CPUMIPSState, bcond), "bcond");
btarget = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUState, btarget), "btarget");
+ offsetof(CPUMIPSState, btarget), "btarget");
hflags = tcg_global_mem_new_i32(TCG_AREG0,
- offsetof(CPUState, hflags), "hflags");
+ offsetof(CPUMIPSState, hflags), "hflags");
fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
- offsetof(CPUState, active_fpu.fcr0),
+ offsetof(CPUMIPSState, active_fpu.fcr0),
"fcr0");
fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
- offsetof(CPUState, active_fpu.fcr31),
+ offsetof(CPUMIPSState, active_fpu.fcr31),
"fcr31");
/* register helpers */
#include "translate_init.c"
-CPUMIPSState *cpu_mips_init (const char *cpu_model)
+MIPSCPU *cpu_mips_init(const char *cpu_model)
{
+ MIPSCPU *cpu;
CPUMIPSState *env;
const mips_def_t *def;
def = cpu_mips_find_by_name(cpu_model);
if (!def)
return NULL;
- env = qemu_mallocz(sizeof(CPUMIPSState));
+ cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
+ env = &cpu->env;
env->cpu_model = def;
env->cpu_model_str = cpu_model;
- cpu_exec_init(env);
#ifndef CONFIG_USER_ONLY
mmu_init(env, def);
#endif
fpu_init(env, def);
mvp_init(env, def);
mips_tcg_init();
- cpu_reset(env);
+ cpu_reset(CPU(cpu));
qemu_init_vcpu(env);
- return env;
+ return cpu;
}
-void cpu_reset (CPUMIPSState *env)
+void cpu_state_reset(CPUMIPSState *env)
{
if (qemu_loglevel_mask(CPU_LOG_RESET)) {
qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
+ env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
env->insn_flags = env->cpu_model->insn_flags;
#if defined(CONFIG_USER_ONLY)
env->hflags = MIPS_HFLAG_UM;
- /* Enable access to the SYNCI_Step register. */
- env->CP0_HWREna |= (1 << 1);
+ /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
+ hardware registers. */
+ env->CP0_HWREna |= 0x0000000F;
if (env->CP0_Config1 & (1 << CP0C1_FP)) {
env->hflags |= MIPS_HFLAG_FPU;
}
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. */
/* Count register increments in debug mode, EJTAG version 1 */
env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
env->hflags = MIPS_HFLAG_CP0;
+
+ if (env->CP0_Config3 & (1 << CP0C3_MT)) {
+ int i;
+
+ /* Only TC0 on VPE 0 starts as active. */
+ for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
+ env->tcs[i].CP0_TCBind = env->cpu_index << CP0TCBd_CurVPE;
+ env->tcs[i].CP0_TCHalt = 1;
+ }
+ env->active_tc.CP0_TCHalt = 1;
+ env->halted = 1;
+
+ if (!env->cpu_index) {
+ /* VPE0 starts up enabled. */
+ env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
+ env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
+
+ /* TC0 starts up unhalted. */
+ env->halted = 0;
+ env->active_tc.CP0_TCHalt = 0;
+ env->tcs[0].CP0_TCHalt = 0;
+ /* With thread 0 active. */
+ env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
+ env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
+ }
+ }
#endif
#if defined(TARGET_MIPS64)
if (env->cpu_model->insn_flags & ISA_MIPS3) {
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(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
{
env->active_tc.PC = gen_opc_pc[pc_pos];
env->hflags &= ~MIPS_HFLAG_BMASK;