diff options
-rw-r--r-- | target-tricore/helper.h | 2 | ||||
-rw-r--r-- | target-tricore/op_helper.c | 49 | ||||
-rw-r--r-- | target-tricore/translate.c | 21 | ||||
-rw-r--r-- | target-tricore/tricore-opcodes.h | 2 |
4 files changed, 74 insertions, 0 deletions
diff --git a/target-tricore/helper.h b/target-tricore/helper.h index 842506c5f9..cc221f1a9b 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -113,6 +113,8 @@ DEF_HELPER_3(dvinit_h_131, i64, env, i32, i32) DEF_HELPER_FLAGS_2(dvadj, TCG_CALL_NO_RWG_SE, i64, i64, i32) DEF_HELPER_FLAGS_2(dvstep, TCG_CALL_NO_RWG_SE, i64, i64, i32) DEF_HELPER_FLAGS_2(dvstep_u, TCG_CALL_NO_RWG_SE, i64, i64, i32) +DEF_HELPER_3(divide, i64, env, i32, i32) +DEF_HELPER_3(divide_u, i64, env, i32, i32) /* mulh */ DEF_HELPER_FLAGS_5(mul_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32) DEF_HELPER_FLAGS_5(mulm_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32) diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index 7aa1f8e40e..10ed541dfd 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -2094,6 +2094,55 @@ uint64_t helper_dvstep_u(uint64_t r1, uint32_t r2) return ((uint64_t)remainder << 32) | (uint32_t)dividend_quotient; } +uint64_t helper_divide(CPUTriCoreState *env, uint32_t r1, uint32_t r2) +{ + int32_t quotient, remainder; + int32_t dividend = (int32_t)r1; + int32_t divisor = (int32_t)r2; + + if (divisor == 0) { + if (dividend >= 0) { + quotient = 0x7fffffff; + remainder = 0; + } else { + quotient = 0x80000000; + remainder = 0; + } + env->PSW_USB_V = (1 << 31); + } else if ((divisor == 0xffffffff) && (dividend == 0x80000000)) { + quotient = 0x7fffffff; + remainder = 0; + env->PSW_USB_V = (1 << 31); + } else { + remainder = dividend % divisor; + quotient = (dividend - remainder)/divisor; + env->PSW_USB_V = 0; + } + env->PSW_USB_SV |= env->PSW_USB_V; + env->PSW_USB_AV = 0; + return ((uint64_t)remainder << 32) | (uint32_t)quotient; +} + +uint64_t helper_divide_u(CPUTriCoreState *env, uint32_t r1, uint32_t r2) +{ + uint32_t quotient, remainder; + uint32_t dividend = r1; + uint32_t divisor = r2; + + if (divisor == 0) { + quotient = 0xffffffff; + remainder = 0; + env->PSW_USB_V = (1 << 31); + } else { + remainder = dividend % divisor; + quotient = (dividend - remainder)/divisor; + env->PSW_USB_V = 0; + } + env->PSW_USB_SV |= env->PSW_USB_V; + env->PSW_USB_AV = 0; + return ((uint64_t)remainder << 32) | quotient; +} + uint64_t helper_mul_h(uint32_t arg00, uint32_t arg01, uint32_t arg10, uint32_t arg11, uint32_t n) { diff --git a/target-tricore/translate.c b/target-tricore/translate.c index d4e4226f69..5f8eff04fa 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -201,6 +201,15 @@ void tricore_cpu_dump_state(CPUState *cs, FILE *f, tcg_temp_free_i64(arg1); \ } while (0) +#define GEN_HELPER_RR(name, rl, rh, arg1, arg2) do { \ + TCGv_i64 ret = tcg_temp_new_i64(); \ + \ + gen_helper_##name(ret, cpu_env, arg1, arg2); \ + tcg_gen_extr_i64_i32(rl, rh, ret); \ + \ + tcg_temp_free_i64(ret); \ +} while (0) + #define EA_ABS_FORMAT(con) (((con & 0x3C000) << 14) + (con & 0x3FFF)) #define EA_B_ABSOLUT(con) (((offset & 0xf00000) << 8) | \ ((offset & 0x0fffff) << 1)) @@ -6494,6 +6503,18 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx) gen_helper_crc32(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); } /* TODO: else raise illegal opcode trap */ break; + case OPC2_32_RR_DIV: + if (tricore_feature(env, TRICORE_FEATURE_16)) { + GEN_HELPER_RR(divide, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1], + cpu_gpr_d[r2]); + } /* TODO: else raise illegal opcode trap */ + break; + case OPC2_32_RR_DIV_U: + if (tricore_feature(env, TRICORE_FEATURE_16)) { + GEN_HELPER_RR(divide_u, cpu_gpr_d[r3], cpu_gpr_d[r3+1], + cpu_gpr_d[r1], cpu_gpr_d[r2]); + } /* TODO: else raise illegal opcode trap */ + break; } } diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index 22c79f570f..1bfed0ce48 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -1124,6 +1124,8 @@ enum { OPC2_32_RR_PARITY = 0x02, OPC2_32_RR_UNPACK = 0x08, OPC2_32_RR_CRC32 = 0x03, + OPC2_32_RR_DIV = 0x20, + OPC2_32_RR_DIV_U = 0x21, }; /* OPCM_32_RR_IDIRECT */ enum { |