Switch bitfield instructions and assorted special ops to TCG.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4739 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
c596defdb9
commit
2b0233abfb
@ -204,5 +204,24 @@ FOP_PROTO(ngt)
|
||||
#undef FOP_PROTO
|
||||
|
||||
/* Special functions */
|
||||
DEF_HELPER(void, do_di, (void))
|
||||
DEF_HELPER(void, do_ei, (void))
|
||||
DEF_HELPER(void, do_eret, (void))
|
||||
DEF_HELPER(void, do_deret, (void))
|
||||
DEF_HELPER(void, do_rdhwr_cpunum, (void))
|
||||
DEF_HELPER(void, do_rdhwr_synci_step, (void))
|
||||
DEF_HELPER(void, do_rdhwr_cc, (void))
|
||||
DEF_HELPER(void, do_rdhwr_ccres, (void))
|
||||
DEF_HELPER(void, do_pmon, (int function))
|
||||
DEF_HELPER(void, do_wait, (void))
|
||||
|
||||
/* Bitfield operations. */
|
||||
DEF_HELPER(void, do_ext, (uint32_t pos, uint32_t size))
|
||||
DEF_HELPER(void, do_ins, (uint32_t pos, uint32_t size))
|
||||
DEF_HELPER(void, do_wsbh, (void))
|
||||
#ifdef TARGET_MIPS64
|
||||
DEF_HELPER(void, do_dext, (uint32_t pos, uint32_t size))
|
||||
DEF_HELPER(void, do_dins, (uint32_t pos, uint32_t size))
|
||||
DEF_HELPER(void, do_dsbh, (void))
|
||||
DEF_HELPER(void, do_dshd, (void))
|
||||
#endif
|
||||
|
150
target-mips/op.c
150
target-mips/op.c
@ -661,153 +661,3 @@ void op_bc1any4t (void)
|
||||
DEBUG_FPU_STATE();
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
/* Specials */
|
||||
void op_di (void)
|
||||
{
|
||||
T0 = env->CP0_Status;
|
||||
env->CP0_Status = T0 & ~(1 << CP0St_IE);
|
||||
CALL_FROM_TB1(cpu_mips_update_irq, env);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_ei (void)
|
||||
{
|
||||
T0 = env->CP0_Status;
|
||||
env->CP0_Status = T0 | (1 << CP0St_IE);
|
||||
CALL_FROM_TB1(cpu_mips_update_irq, env);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void debug_pre_eret (void);
|
||||
void debug_post_eret (void);
|
||||
void op_eret (void)
|
||||
{
|
||||
if (loglevel & CPU_LOG_EXEC)
|
||||
CALL_FROM_TB0(debug_pre_eret);
|
||||
if (env->CP0_Status & (1 << CP0St_ERL)) {
|
||||
env->PC[env->current_tc] = env->CP0_ErrorEPC;
|
||||
env->CP0_Status &= ~(1 << CP0St_ERL);
|
||||
} else {
|
||||
env->PC[env->current_tc] = env->CP0_EPC;
|
||||
env->CP0_Status &= ~(1 << CP0St_EXL);
|
||||
}
|
||||
CALL_FROM_TB1(compute_hflags, env);
|
||||
if (loglevel & CPU_LOG_EXEC)
|
||||
CALL_FROM_TB0(debug_post_eret);
|
||||
env->CP0_LLAddr = 1;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_deret (void)
|
||||
{
|
||||
if (loglevel & CPU_LOG_EXEC)
|
||||
CALL_FROM_TB0(debug_pre_eret);
|
||||
env->PC[env->current_tc] = env->CP0_DEPC;
|
||||
env->hflags &= MIPS_HFLAG_DM;
|
||||
CALL_FROM_TB1(compute_hflags, env);
|
||||
if (loglevel & CPU_LOG_EXEC)
|
||||
CALL_FROM_TB0(debug_post_eret);
|
||||
env->CP0_LLAddr = 1;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_rdhwr_cpunum(void)
|
||||
{
|
||||
if ((env->hflags & MIPS_HFLAG_CP0) ||
|
||||
(env->CP0_HWREna & (1 << 0)))
|
||||
T0 = env->CP0_EBase & 0x3ff;
|
||||
else
|
||||
CALL_FROM_TB1(do_raise_exception, EXCP_RI);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_rdhwr_synci_step(void)
|
||||
{
|
||||
if ((env->hflags & MIPS_HFLAG_CP0) ||
|
||||
(env->CP0_HWREna & (1 << 1)))
|
||||
T0 = env->SYNCI_Step;
|
||||
else
|
||||
CALL_FROM_TB1(do_raise_exception, EXCP_RI);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_rdhwr_cc(void)
|
||||
{
|
||||
if ((env->hflags & MIPS_HFLAG_CP0) ||
|
||||
(env->CP0_HWREna & (1 << 2)))
|
||||
T0 = env->CP0_Count;
|
||||
else
|
||||
CALL_FROM_TB1(do_raise_exception, EXCP_RI);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_rdhwr_ccres(void)
|
||||
{
|
||||
if ((env->hflags & MIPS_HFLAG_CP0) ||
|
||||
(env->CP0_HWREna & (1 << 3)))
|
||||
T0 = env->CCRes;
|
||||
else
|
||||
CALL_FROM_TB1(do_raise_exception, EXCP_RI);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
/* Bitfield operations. */
|
||||
void op_ext(void)
|
||||
{
|
||||
unsigned int pos = PARAM1;
|
||||
unsigned int size = PARAM2;
|
||||
|
||||
T0 = (int32_t)((T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0));
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_ins(void)
|
||||
{
|
||||
unsigned int pos = PARAM1;
|
||||
unsigned int size = PARAM2;
|
||||
target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
|
||||
|
||||
T0 = (int32_t)((T0 & ~mask) | ((T1 << pos) & mask));
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_wsbh(void)
|
||||
{
|
||||
T0 = (int32_t)(((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF));
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
void op_dext(void)
|
||||
{
|
||||
unsigned int pos = PARAM1;
|
||||
unsigned int size = PARAM2;
|
||||
|
||||
T0 = (T1 >> pos) & ((size < 64) ? ((1ULL << size) - 1) : ~0ULL);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_dins(void)
|
||||
{
|
||||
unsigned int pos = PARAM1;
|
||||
unsigned int size = PARAM2;
|
||||
target_ulong mask = ((size < 64) ? ((1ULL << size) - 1) : ~0ULL) << pos;
|
||||
|
||||
T0 = (T0 & ~mask) | ((T1 << pos) & mask);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_dsbh(void)
|
||||
{
|
||||
T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void op_dshd(void)
|
||||
{
|
||||
T1 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
|
||||
T0 = (T1 << 32) | (T1 >> 32);
|
||||
FORCE_RET();
|
||||
}
|
||||
#endif
|
||||
|
@ -1348,6 +1348,21 @@ void dump_sc (void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Specials */
|
||||
void do_di (void)
|
||||
{
|
||||
T0 = env->CP0_Status;
|
||||
env->CP0_Status = T0 & ~(1 << CP0St_IE);
|
||||
cpu_mips_update_irq(env);
|
||||
}
|
||||
|
||||
void do_ei (void)
|
||||
{
|
||||
T0 = env->CP0_Status;
|
||||
env->CP0_Status = T0 | (1 << CP0St_IE);
|
||||
cpu_mips_update_irq(env);
|
||||
}
|
||||
|
||||
void debug_pre_eret (void)
|
||||
{
|
||||
fprintf(logfile, "ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
|
||||
@ -1375,6 +1390,114 @@ void debug_post_eret (void)
|
||||
}
|
||||
}
|
||||
|
||||
void do_eret (void)
|
||||
{
|
||||
if (loglevel & CPU_LOG_EXEC)
|
||||
debug_pre_eret();
|
||||
if (env->CP0_Status & (1 << CP0St_ERL)) {
|
||||
env->PC[env->current_tc] = env->CP0_ErrorEPC;
|
||||
env->CP0_Status &= ~(1 << CP0St_ERL);
|
||||
} else {
|
||||
env->PC[env->current_tc] = env->CP0_EPC;
|
||||
env->CP0_Status &= ~(1 << CP0St_EXL);
|
||||
}
|
||||
compute_hflags(env);
|
||||
if (loglevel & CPU_LOG_EXEC)
|
||||
debug_post_eret();
|
||||
env->CP0_LLAddr = 1;
|
||||
}
|
||||
|
||||
void do_deret (void)
|
||||
{
|
||||
if (loglevel & CPU_LOG_EXEC)
|
||||
debug_pre_eret();
|
||||
env->PC[env->current_tc] = env->CP0_DEPC;
|
||||
env->hflags &= MIPS_HFLAG_DM;
|
||||
compute_hflags(env);
|
||||
if (loglevel & CPU_LOG_EXEC)
|
||||
debug_post_eret();
|
||||
env->CP0_LLAddr = 1;
|
||||
}
|
||||
|
||||
void do_rdhwr_cpunum(void)
|
||||
{
|
||||
if ((env->hflags & MIPS_HFLAG_CP0) ||
|
||||
(env->CP0_HWREna & (1 << 0)))
|
||||
T0 = env->CP0_EBase & 0x3ff;
|
||||
else
|
||||
do_raise_exception(EXCP_RI);
|
||||
}
|
||||
|
||||
void do_rdhwr_synci_step(void)
|
||||
{
|
||||
if ((env->hflags & MIPS_HFLAG_CP0) ||
|
||||
(env->CP0_HWREna & (1 << 1)))
|
||||
T0 = env->SYNCI_Step;
|
||||
else
|
||||
do_raise_exception(EXCP_RI);
|
||||
}
|
||||
|
||||
void do_rdhwr_cc(void)
|
||||
{
|
||||
if ((env->hflags & MIPS_HFLAG_CP0) ||
|
||||
(env->CP0_HWREna & (1 << 2)))
|
||||
T0 = env->CP0_Count;
|
||||
else
|
||||
do_raise_exception(EXCP_RI);
|
||||
}
|
||||
|
||||
void do_rdhwr_ccres(void)
|
||||
{
|
||||
if ((env->hflags & MIPS_HFLAG_CP0) ||
|
||||
(env->CP0_HWREna & (1 << 3)))
|
||||
T0 = env->CCRes;
|
||||
else
|
||||
do_raise_exception(EXCP_RI);
|
||||
}
|
||||
|
||||
/* Bitfield operations. */
|
||||
void do_ext(uint32_t pos, uint32_t size)
|
||||
{
|
||||
T0 = (int32_t)((T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0));
|
||||
}
|
||||
|
||||
void do_ins(uint32_t pos, uint32_t size)
|
||||
{
|
||||
target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
|
||||
|
||||
T0 = (int32_t)((T0 & ~mask) | ((T1 << pos) & mask));
|
||||
}
|
||||
|
||||
void do_wsbh(void)
|
||||
{
|
||||
T0 = (int32_t)(((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF));
|
||||
}
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
void do_dext(uint32_t pos, uint32_t size)
|
||||
{
|
||||
T0 = (T1 >> pos) & ((size < 64) ? ((1ULL << size) - 1) : ~0ULL);
|
||||
}
|
||||
|
||||
void do_dins(uint32_t pos, uint32_t size)
|
||||
{
|
||||
target_ulong mask = ((size < 64) ? ((1ULL << size) - 1) : ~0ULL) << pos;
|
||||
|
||||
T0 = (T0 & ~mask) | ((T1 << pos) & mask);
|
||||
}
|
||||
|
||||
void do_dsbh(void)
|
||||
{
|
||||
T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
|
||||
}
|
||||
|
||||
void do_dshd(void)
|
||||
{
|
||||
T1 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
|
||||
T0 = (T1 << 32) | (T1 >> 32);
|
||||
}
|
||||
#endif
|
||||
|
||||
void do_pmon (int function)
|
||||
{
|
||||
function /= 2;
|
||||
|
@ -2512,49 +2512,49 @@ static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
|
||||
case OPC_EXT:
|
||||
if (lsb + msb > 31)
|
||||
goto fail;
|
||||
gen_op_ext(lsb, msb + 1);
|
||||
tcg_gen_helper_0_2ii(do_ext, lsb, msb + 1);
|
||||
break;
|
||||
#if defined(TARGET_MIPS64)
|
||||
case OPC_DEXTM:
|
||||
if (lsb + msb > 63)
|
||||
goto fail;
|
||||
gen_op_dext(lsb, msb + 1 + 32);
|
||||
tcg_gen_helper_0_2ii(do_dext, lsb, msb + 1 + 32);
|
||||
break;
|
||||
case OPC_DEXTU:
|
||||
if (lsb + msb > 63)
|
||||
goto fail;
|
||||
gen_op_dext(lsb + 32, msb + 1);
|
||||
tcg_gen_helper_0_2ii(do_dext, lsb + 32, msb + 1);
|
||||
break;
|
||||
case OPC_DEXT:
|
||||
if (lsb + msb > 63)
|
||||
goto fail;
|
||||
gen_op_dext(lsb, msb + 1);
|
||||
tcg_gen_helper_0_2ii(do_dext, lsb, msb + 1);
|
||||
break;
|
||||
#endif
|
||||
case OPC_INS:
|
||||
if (lsb > msb)
|
||||
goto fail;
|
||||
gen_load_gpr(cpu_T[0], rt);
|
||||
gen_op_ins(lsb, msb - lsb + 1);
|
||||
tcg_gen_helper_0_2ii(do_ins, lsb, msb - lsb + 1);
|
||||
break;
|
||||
#if defined(TARGET_MIPS64)
|
||||
case OPC_DINSM:
|
||||
if (lsb > msb)
|
||||
goto fail;
|
||||
gen_load_gpr(cpu_T[0], rt);
|
||||
gen_op_dins(lsb, msb - lsb + 1 + 32);
|
||||
tcg_gen_helper_0_2ii(do_dins, lsb, msb - lsb + 1 + 32);
|
||||
break;
|
||||
case OPC_DINSU:
|
||||
if (lsb > msb)
|
||||
goto fail;
|
||||
gen_load_gpr(cpu_T[0], rt);
|
||||
gen_op_dins(lsb + 32, msb - lsb + 1);
|
||||
tcg_gen_helper_0_2ii(do_dins, lsb + 32, msb - lsb + 1);
|
||||
break;
|
||||
case OPC_DINS:
|
||||
if (lsb > msb)
|
||||
goto fail;
|
||||
gen_load_gpr(cpu_T[0], rt);
|
||||
gen_op_dins(lsb, msb - lsb + 1);
|
||||
tcg_gen_helper_0_2ii(do_dins, lsb, msb - lsb + 1);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@ -5348,7 +5348,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
|
||||
opn = "eret";
|
||||
check_insn(env, ctx, ISA_MIPS2);
|
||||
save_cpu_state(ctx, 1);
|
||||
gen_op_eret();
|
||||
tcg_gen_helper_0_0(do_eret);
|
||||
ctx->bstate = BS_EXCP;
|
||||
break;
|
||||
case OPC_DERET:
|
||||
@ -5359,7 +5359,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
} else {
|
||||
save_cpu_state(ctx, 1);
|
||||
gen_op_deret();
|
||||
tcg_gen_helper_0_0(do_deret);
|
||||
ctx->bstate = BS_EXCP;
|
||||
}
|
||||
break;
|
||||
@ -6792,33 +6792,33 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
}
|
||||
break;
|
||||
case OPC_SPECIAL3:
|
||||
op1 = MASK_SPECIAL3(ctx->opcode);
|
||||
switch (op1) {
|
||||
case OPC_EXT:
|
||||
case OPC_INS:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_bitops(ctx, op1, rt, rs, sa, rd);
|
||||
break;
|
||||
case OPC_BSHFL:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
op2 = MASK_BSHFL(ctx->opcode);
|
||||
switch (op2) {
|
||||
case OPC_WSBH:
|
||||
gen_load_gpr(cpu_T[1], rt);
|
||||
gen_op_wsbh();
|
||||
break;
|
||||
case OPC_SEB:
|
||||
gen_load_gpr(cpu_T[1], rt);
|
||||
tcg_gen_ext8s_tl(cpu_T[0], cpu_T[1]);
|
||||
break;
|
||||
case OPC_SEH:
|
||||
gen_load_gpr(cpu_T[1], rt);
|
||||
tcg_gen_ext16s_tl(cpu_T[0], cpu_T[1]);
|
||||
break;
|
||||
default: /* Invalid */
|
||||
MIPS_INVAL("bshfl");
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
break;
|
||||
op1 = MASK_SPECIAL3(ctx->opcode);
|
||||
switch (op1) {
|
||||
case OPC_EXT:
|
||||
case OPC_INS:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_bitops(ctx, op1, rt, rs, sa, rd);
|
||||
break;
|
||||
case OPC_BSHFL:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
op2 = MASK_BSHFL(ctx->opcode);
|
||||
switch (op2) {
|
||||
case OPC_WSBH:
|
||||
gen_load_gpr(cpu_T[1], rt);
|
||||
tcg_gen_helper_0_0(do_wsbh);
|
||||
break;
|
||||
case OPC_SEB:
|
||||
gen_load_gpr(cpu_T[1], rt);
|
||||
tcg_gen_ext8s_tl(cpu_T[0], cpu_T[1]);
|
||||
break;
|
||||
case OPC_SEH:
|
||||
gen_load_gpr(cpu_T[1], rt);
|
||||
tcg_gen_ext16s_tl(cpu_T[0], cpu_T[1]);
|
||||
break;
|
||||
default: /* Invalid */
|
||||
MIPS_INVAL("bshfl");
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
break;
|
||||
}
|
||||
gen_store_gpr(cpu_T[0], rd);
|
||||
break;
|
||||
@ -6827,24 +6827,26 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
switch (rd) {
|
||||
case 0:
|
||||
save_cpu_state(ctx, 1);
|
||||
gen_op_rdhwr_cpunum();
|
||||
tcg_gen_helper_0_0(do_rdhwr_cpunum);
|
||||
break;
|
||||
case 1:
|
||||
save_cpu_state(ctx, 1);
|
||||
gen_op_rdhwr_synci_step();
|
||||
tcg_gen_helper_0_0(do_rdhwr_synci_step);
|
||||
break;
|
||||
case 2:
|
||||
save_cpu_state(ctx, 1);
|
||||
gen_op_rdhwr_cc();
|
||||
tcg_gen_helper_0_0(do_rdhwr_cc);
|
||||
break;
|
||||
case 3:
|
||||
save_cpu_state(ctx, 1);
|
||||
gen_op_rdhwr_ccres();
|
||||
tcg_gen_helper_0_0(do_rdhwr_ccres);
|
||||
break;
|
||||
case 29:
|
||||
#if defined (CONFIG_USER_ONLY)
|
||||
tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, tls_value));
|
||||
break;
|
||||
#else
|
||||
/* XXX: Some CPUs implement this in hardware. Not supported yet. */
|
||||
#endif
|
||||
default: /* Invalid */
|
||||
MIPS_INVAL("rdhwr");
|
||||
@ -6879,11 +6881,11 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
switch (op2) {
|
||||
case OPC_DSBH:
|
||||
gen_load_gpr(cpu_T[1], rt);
|
||||
gen_op_dsbh();
|
||||
tcg_gen_helper_0_0(do_dsbh);
|
||||
break;
|
||||
case OPC_DSHD:
|
||||
gen_load_gpr(cpu_T[1], rt);
|
||||
gen_op_dshd();
|
||||
tcg_gen_helper_0_0(do_dshd);
|
||||
break;
|
||||
default: /* Invalid */
|
||||
MIPS_INVAL("dbshfl");
|
||||
@ -6963,14 +6965,14 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
case OPC_DI:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
save_cpu_state(ctx, 1);
|
||||
gen_op_di();
|
||||
tcg_gen_helper_0_0(do_di);
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
ctx->bstate = BS_STOP;
|
||||
break;
|
||||
case OPC_EI:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
save_cpu_state(ctx, 1);
|
||||
gen_op_ei();
|
||||
tcg_gen_helper_0_0(do_ei);
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
ctx->bstate = BS_STOP;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user