diff --git a/target-mips/helper.h b/target-mips/helper.h index 7918c9e9937aa825dae9c935aeb6e11f78dac976..246270a59e58def0e35f27ea8215e36c93ca98da 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -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 diff --git a/target-mips/op.c b/target-mips/op.c index 7d7c4732d7d7001286f247c8b39ab387983a9a59..254973f5a6e7e59bd3b765ff906fcfad35a46e87 100644 --- a/target-mips/op.c +++ b/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 diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index f573732e6115fa6fc873231ac6e0c13fc47503df..93cd55e0198aa0a3dc654e7a9ab26e19c8b8877c 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -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; diff --git a/target-mips/translate.c b/target-mips/translate.c index aae8023636919feb90f286d5571e9a7fb59f32e4..82e629e82e61c91f85873ed9da490656a977575c 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -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;