diff options
author | Bastian Koppelmann <kbastian@mail.uni-paderborn.de> | 2015-05-11 14:59:55 +0200 |
---|---|---|
committer | Bastian Koppelmann <kbastian@mail.uni-paderborn.de> | 2015-05-22 17:02:34 +0200 |
commit | 9371557115a734412974f8d4096cbe8a62ca2731 (patch) | |
tree | 7aedb471780d228438883c34b08fdc13084de5ea /target-tricore | |
parent | 0e045f43c45f675711c3f6836118dc7eabcc2411 (diff) | |
download | qemu-9371557115a734412974f8d4096cbe8a62ca2731.zip qemu-9371557115a734412974f8d4096cbe8a62ca2731.tar.gz qemu-9371557115a734412974f8d4096cbe8a62ca2731.tar.bz2 |
target-tricore: add RR_DIV and RR_DIV_U instructions of the v1.6 ISA
Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target-tricore')
-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 842506c..cc221f1 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 7aa1f8e..10ed541 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 d4e4226..5f8eff0 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 22c79f5..1bfed0c 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 { |