diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2023-10-02 14:42:17 -0400 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2023-10-02 14:42:17 -0400 |
commit | a3108b2d92eda76b4dbe0c95051899628e28f6ac (patch) | |
tree | 089cf16d8ad27373444e02332b97c2a157cda548 /target | |
parent | 5b0d1a839513e2aa87965cb6736c8ec355742d5e (diff) | |
parent | ceada000846b0cd81c578b1da9f76d0c59536654 (diff) |
Merge tag 'pull-tricore-20230929' of https://github.com/bkoppelmann/qemu into staging
- Add FTOU, CRCN, FTOHP, and HPTOF insns
# -----BEGIN PGP SIGNATURE-----
#
# iQJTBAABCgA9FiEEbmNqfoPy3Qz6bm43CtLGOWtpyhQFAmUWb2sfHGtiYXN0aWFu
# QG1haWwudW5pLXBhZGVyYm9ybi5kZQAKCRAK0sY5a2nKFPn0D/0S+Zth2okyfe6H
# YdoFB49PWlcafIvZHr1TDswp3LvSDnrjHLJfEW1Gx3mtDkw+/7uid0eMTQ8sDlxJ
# t7spJdZDZ5dkm+9K5MzGkW0zo0jDY6kbS1A3HJRPcpJJJk4zBBL1K4KC1FBUD6IK
# 7n41f5vExgWhIhOgZmT9WTMbBfh73/+Cu8h6M9RAI1VI0O6N5jOETpKTBFsPOx+A
# Kd429cB1c9QeAj0iEXdMn2/Xg2cAII86jrOcYkLYltxir/r6Cia9hfp/F6OXpcZI
# QqKzn11djvbCCL7m9OXhuI3ZP+TIcX7QOabSstfghHlNG1qs/RkXwIRqKHsfRXNG
# nywBTjwIDSiZ4cbZVJ6OjXxbU9OBRkmDgh+SYEVMlFi4E+t3WeTMC8gxUsjfITpK
# JXFoduN2P0yKRjkWQ2OSQ7xX4StFPikXBH1eC8RNnW4IY00wMiJ0tM/0+j+qJLLM
# Ft/bceIZhnGs+axN0jF1EtR03uLZ0kmy3YqsH/KnBnufrag3ytpC/kAtl9Scd6m+
# N4pAT9cfgxqXv/yXAKGupoNPwPGvvSKV6XQTJt2Hn7PBadHWlvlBkgYqGIejpHDM
# x9EghA8o4q5rTu9zTqBv36bOHJEDbJhmq5dYqJTS/q1ORjnWQQsLxv+6XGN3wrbb
# OuexPdD8fH3mWrjeJJ3KDKojOYyGyg==
# =gUyL
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 29 Sep 2023 02:32:11 EDT
# gpg: using RSA key 6E636A7E83F2DD0CFA6E6E370AD2C6396B69CA14
# gpg: issuer "kbastian@mail.uni-paderborn.de"
# gpg: Good signature from "Bastian Koppelmann <kbastian@mail.uni-paderborn.de>" [unknown]
# gpg: WARNING: The key's User ID is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 6E63 6A7E 83F2 DD0C FA6E 6E37 0AD2 C639 6B69 CA14
* tag 'pull-tricore-20230929' of https://github.com/bkoppelmann/qemu:
target/tricore: Change effective address (ea) to target_ulong
target/tricore: Remove CSFRs from cpu.h
tests/tcg: Reset result register after each test
hw/tricore: Log failing test in testdevice
tests/tcg/tricore: Extended and non-extened regs now match
target/tricore: Fix FTOUZ being ISA v1.3.1 up
target/tricore: Replace cpu_*_code with translator_*
target/tricore: Swap src and dst reg for RCRR_INSERT
target/tricore: Fix RCPW/RRPW_INSERT insns for width = 0
target/tricore: Implement hptof insn
target/tricore: Implement ftohp insn
target/tricore: Clarify special case for FTOUZ insn
target/tricore: Implement FTOU insn
target/tricore: Correctly handle FPU RM from PSW
target/tricore: Implement CRCN insn
tests/tcg/tricore: Bump cpu to tc37x
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'target')
-rw-r--r-- | target/tricore/cpu.h | 143 | ||||
-rw-r--r-- | target/tricore/fpu_helper.c | 111 | ||||
-rw-r--r-- | target/tricore/helper.c | 19 | ||||
-rw-r--r-- | target/tricore/helper.h | 4 | ||||
-rw-r--r-- | target/tricore/op_helper.c | 79 | ||||
-rw-r--r-- | target/tricore/translate.c | 56 | ||||
-rw-r--r-- | target/tricore/tricore-opcodes.h | 3 |
7 files changed, 261 insertions, 154 deletions
diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h index 3708405be8..1cace96b01 100644 --- a/target/tricore/cpu.h +++ b/target/tricore/cpu.h @@ -30,150 +30,25 @@ typedef struct CPUArchState { /* GPR Register */ uint32_t gpr_a[16]; uint32_t gpr_d[16]; - /* CSFR Register */ - uint32_t PCXI; /* Frequently accessed PSW_USB bits are stored separately for efficiency. This contains all the other bits. Use psw_{read,write} to access the whole PSW. */ uint32_t PSW; - - /* PSW flag cache for faster execution - */ + /* PSW flag cache for faster execution */ uint32_t PSW_USB_C; uint32_t PSW_USB_V; /* Only if bit 31 set, then flag is set */ uint32_t PSW_USB_SV; /* Only if bit 31 set, then flag is set */ uint32_t PSW_USB_AV; /* Only if bit 31 set, then flag is set. */ uint32_t PSW_USB_SAV; /* Only if bit 31 set, then flag is set. */ - uint32_t PC; - uint32_t SYSCON; - uint32_t CPU_ID; - uint32_t CORE_ID; - uint32_t BIV; - uint32_t BTV; - uint32_t ISP; - uint32_t ICR; - uint32_t FCX; - uint32_t LCX; - uint32_t COMPAT; - - /* Mem Protection Register */ - uint32_t DPR0_0L; - uint32_t DPR0_0U; - uint32_t DPR0_1L; - uint32_t DPR0_1U; - uint32_t DPR0_2L; - uint32_t DPR0_2U; - uint32_t DPR0_3L; - uint32_t DPR0_3U; - - uint32_t DPR1_0L; - uint32_t DPR1_0U; - uint32_t DPR1_1L; - uint32_t DPR1_1U; - uint32_t DPR1_2L; - uint32_t DPR1_2U; - uint32_t DPR1_3L; - uint32_t DPR1_3U; - - uint32_t DPR2_0L; - uint32_t DPR2_0U; - uint32_t DPR2_1L; - uint32_t DPR2_1U; - uint32_t DPR2_2L; - uint32_t DPR2_2U; - uint32_t DPR2_3L; - uint32_t DPR2_3U; - - uint32_t DPR3_0L; - uint32_t DPR3_0U; - uint32_t DPR3_1L; - uint32_t DPR3_1U; - uint32_t DPR3_2L; - uint32_t DPR3_2U; - uint32_t DPR3_3L; - uint32_t DPR3_3U; - - uint32_t CPR0_0L; - uint32_t CPR0_0U; - uint32_t CPR0_1L; - uint32_t CPR0_1U; - uint32_t CPR0_2L; - uint32_t CPR0_2U; - uint32_t CPR0_3L; - uint32_t CPR0_3U; - - uint32_t CPR1_0L; - uint32_t CPR1_0U; - uint32_t CPR1_1L; - uint32_t CPR1_1U; - uint32_t CPR1_2L; - uint32_t CPR1_2U; - uint32_t CPR1_3L; - uint32_t CPR1_3U; - - uint32_t CPR2_0L; - uint32_t CPR2_0U; - uint32_t CPR2_1L; - uint32_t CPR2_1U; - uint32_t CPR2_2L; - uint32_t CPR2_2U; - uint32_t CPR2_3L; - uint32_t CPR2_3U; - - uint32_t CPR3_0L; - uint32_t CPR3_0U; - uint32_t CPR3_1L; - uint32_t CPR3_1U; - uint32_t CPR3_2L; - uint32_t CPR3_2U; - uint32_t CPR3_3L; - uint32_t CPR3_3U; - - uint32_t DPM0; - uint32_t DPM1; - uint32_t DPM2; - uint32_t DPM3; - - uint32_t CPM0; - uint32_t CPM1; - uint32_t CPM2; - uint32_t CPM3; - - /* Memory Management Registers */ - uint32_t MMU_CON; - uint32_t MMU_ASI; - uint32_t MMU_TVA; - uint32_t MMU_TPA; - uint32_t MMU_TPX; - uint32_t MMU_TFA; - /* {1.3.1 only */ - uint32_t BMACON; - uint32_t SMACON; - uint32_t DIEAR; - uint32_t DIETR; - uint32_t CCDIER; - uint32_t MIECON; - uint32_t PIEAR; - uint32_t PIETR; - uint32_t CCPIER; - /*} */ - /* Debug Registers */ - uint32_t DBGSR; - uint32_t EXEVT; - uint32_t CREVT; - uint32_t SWEVT; - uint32_t TR0EVT; - uint32_t TR1EVT; - uint32_t DMS; - uint32_t DCX; - uint32_t DBGTCR; - uint32_t CCTRL; - uint32_t CCNT; - uint32_t ICNT; - uint32_t M1CNT; - uint32_t M2CNT; - uint32_t M3CNT; +#define R(ADDR, NAME, FEATURE) uint32_t NAME; +#define A(ADDR, NAME, FEATURE) uint32_t NAME; +#define E(ADDR, NAME, FEATURE) uint32_t NAME; +#include "csfr.h.inc" +#undef R +#undef A +#undef E + /* Floating Point Registers */ float_status fp_status; diff --git a/target/tricore/fpu_helper.c b/target/tricore/fpu_helper.c index cb7ee7dd35..5d38aea143 100644 --- a/target/tricore/fpu_helper.c +++ b/target/tricore/fpu_helper.c @@ -373,6 +373,80 @@ uint32_t helper_ftoi(CPUTriCoreState *env, uint32_t arg) return (uint32_t)result; } +uint32_t helper_hptof(CPUTriCoreState *env, uint32_t arg) +{ + float16 f_arg = make_float16(arg); + uint32_t result = 0; + int32_t flags = 0; + + /* + * if we have any NAN we need to move the top 2 and lower 8 input mantissa + * bits to the top 2 and lower 8 output mantissa bits respectively. + * Softfloat on the other hand uses the top 10 mantissa bits. + */ + if (float16_is_any_nan(f_arg)) { + if (float16_is_signaling_nan(f_arg, &env->fp_status)) { + flags |= float_flag_invalid; + } + result = 0; + result = float32_set_sign(result, f_arg >> 15); + result = deposit32(result, 23, 8, 0xff); + result = deposit32(result, 21, 2, extract32(f_arg, 8, 2)); + result = deposit32(result, 0, 8, extract32(f_arg, 0, 8)); + } else { + set_flush_inputs_to_zero(0, &env->fp_status); + result = float16_to_float32(f_arg, true, &env->fp_status); + set_flush_inputs_to_zero(1, &env->fp_status); + flags = f_get_excp_flags(env); + } + + if (flags) { + f_update_psw_flags(env, flags); + } else { + env->FPU_FS = 0; + } + + return result; +} + +uint32_t helper_ftohp(CPUTriCoreState *env, uint32_t arg) +{ + float32 f_arg = make_float32(arg); + uint32_t result = 0; + int32_t flags = 0; + + /* + * if we have any NAN we need to move the top 2 and lower 8 input mantissa + * bits to the top 2 and lower 8 output mantissa bits respectively. + * Softfloat on the other hand uses the top 10 mantissa bits. + */ + if (float32_is_any_nan(f_arg)) { + if (float32_is_signaling_nan(f_arg, &env->fp_status)) { + flags |= float_flag_invalid; + } + result = float16_set_sign(result, arg >> 31); + result = deposit32(result, 10, 5, 0x1f); + result = deposit32(result, 8, 2, extract32(arg, 21, 2)); + result = deposit32(result, 0, 8, extract32(arg, 0, 8)); + if (extract32(result, 0, 10) == 0) { + result |= (1 << 8); + } + } else { + set_flush_to_zero(0, &env->fp_status); + result = float32_to_float16(f_arg, true, &env->fp_status); + set_flush_to_zero(1, &env->fp_status); + flags = f_get_excp_flags(env); + } + + if (flags) { + f_update_psw_flags(env, flags); + } else { + env->FPU_FS = 0; + } + + return result; +} + uint32_t helper_itof(CPUTriCoreState *env, uint32_t arg) { float32 f_result; @@ -429,6 +503,38 @@ uint32_t helper_ftoiz(CPUTriCoreState *env, uint32_t arg) return result; } +uint32_t helper_ftou(CPUTriCoreState *env, uint32_t arg) +{ + float32 f_arg = make_float32(arg); + uint32_t result; + int32_t flags = 0; + + result = float32_to_uint32(f_arg, &env->fp_status); + + flags = f_get_excp_flags(env); + if (flags & float_flag_invalid) { + flags &= ~float_flag_inexact; + if (float32_is_any_nan(f_arg)) { + result = 0; + } + /* + * we need to check arg < 0.0 before rounding as TriCore needs to raise + * float_flag_invalid as well. For instance, when we have a negative + * exponent and sign, softfloat would only raise float_flat_inexact. + */ + } else if (float32_lt_quiet(f_arg, 0, &env->fp_status)) { + flags = float_flag_invalid; + result = 0; + } + + if (flags) { + f_update_psw_flags(env, flags); + } else { + env->FPU_FS = 0; + } + return result; +} + uint32_t helper_ftouz(CPUTriCoreState *env, uint32_t arg) { float32 f_arg = make_float32(arg); @@ -443,6 +549,11 @@ uint32_t helper_ftouz(CPUTriCoreState *env, uint32_t arg) if (float32_is_any_nan(f_arg)) { result = 0; } + /* + * we need to check arg < 0.0 before rounding as TriCore needs to raise + * float_flag_invalid as well. For instance, when we have a negative + * exponent and sign, softfloat would only raise float_flat_inexact. + */ } else if (float32_lt_quiet(f_arg, 0, &env->fp_status)) { flags = float_flag_invalid; result = 0; diff --git a/target/tricore/helper.c b/target/tricore/helper.c index 6d076ac36f..7e5da3cb23 100644 --- a/target/tricore/helper.c +++ b/target/tricore/helper.c @@ -120,16 +120,31 @@ void tricore_cpu_list(void) void fpu_set_state(CPUTriCoreState *env) { - set_float_rounding_mode(env->PSW & MASK_PSW_FPU_RM, &env->fp_status); + switch (extract32(env->PSW, 24, 2)) { + case 0: + set_float_rounding_mode(float_round_nearest_even, &env->fp_status); + break; + case 1: + set_float_rounding_mode(float_round_up, &env->fp_status); + break; + case 2: + set_float_rounding_mode(float_round_down, &env->fp_status); + break; + case 3: + set_float_rounding_mode(float_round_to_zero, &env->fp_status); + break; + } + set_flush_inputs_to_zero(1, &env->fp_status); set_flush_to_zero(1, &env->fp_status); + set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status); set_default_nan_mode(1, &env->fp_status); } uint32_t psw_read(CPUTriCoreState *env) { /* clear all USB bits */ - env->PSW &= 0x6ffffff; + env->PSW &= 0x7ffffff; /* now set them from the cache */ env->PSW |= ((env->PSW_USB_C != 0) << 31); env->PSW |= ((env->PSW_USB_V & (1 << 31)) >> 1); diff --git a/target/tricore/helper.h b/target/tricore/helper.h index 31d71eac7a..1d97d078b0 100644 --- a/target/tricore/helper.h +++ b/target/tricore/helper.h @@ -111,9 +111,12 @@ DEF_HELPER_4(fmsub, i32, env, i32, i32, i32) DEF_HELPER_3(fcmp, i32, env, i32, i32) DEF_HELPER_2(qseed, i32, env, i32) DEF_HELPER_2(ftoi, i32, env, i32) +DEF_HELPER_2(ftohp, i32, env, i32) +DEF_HELPER_2(hptof, i32, env, i32) DEF_HELPER_2(itof, i32, env, i32) DEF_HELPER_2(utof, i32, env, i32) DEF_HELPER_2(ftoiz, i32, env, i32) +DEF_HELPER_2(ftou, i32, env, i32) DEF_HELPER_2(ftouz, i32, env, i32) DEF_HELPER_2(updfl, void, env, i32) /* dvinit */ @@ -134,6 +137,7 @@ DEF_HELPER_FLAGS_5(mulr_h, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32, i32, i32) DEF_HELPER_FLAGS_2(crc32b, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_2(crc32_be, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_2(crc32_le, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_3(crcn, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_FLAGS_2(shuffle, TCG_CALL_NO_RWG_SE, i32, i32, i32) /* CSA */ DEF_HELPER_2(call, void, env, i32) diff --git a/target/tricore/op_helper.c b/target/tricore/op_helper.c index 89be1ed648..ba9c4444b3 100644 --- a/target/tricore/op_helper.c +++ b/target/tricore/op_helper.c @@ -2308,6 +2308,69 @@ uint32_t helper_crc32_le(uint32_t arg0, uint32_t arg1) return crc32(arg1, buf, 4); } +static uint32_t crc_div(uint32_t crc_in, uint32_t data, uint32_t gen, + uint32_t n, uint32_t m) +{ + uint32_t i; + + data = data << n; + for (i = 0; i < m; i++) { + if (crc_in & (1u << (n - 1))) { + crc_in <<= 1; + if (data & (1u << (m - 1))) { + crc_in++; + } + crc_in ^= gen; + } else { + crc_in <<= 1; + if (data & (1u << (m - 1))) { + crc_in++; + } + } + data <<= 1; + } + + return crc_in; +} + +uint32_t helper_crcn(uint32_t arg0, uint32_t arg1, uint32_t arg2) +{ + uint32_t crc_out, crc_in; + uint32_t n = extract32(arg0, 12, 4) + 1; + uint32_t gen = extract32(arg0, 16, n); + uint32_t inv = extract32(arg0, 9, 1); + uint32_t le = extract32(arg0, 8, 1); + uint32_t m = extract32(arg0, 0, 3) + 1; + uint32_t data = extract32(arg1, 0, m); + uint32_t seed = extract32(arg2, 0, n); + + if (le == 1) { + if (m == 0) { + data = 0; + } else { + data = revbit32(data) >> (32 - m); + } + } + + if (inv == 1) { + seed = ~seed; + } + + if (m > n) { + crc_in = (data >> (m - n)) ^ seed; + } else { + crc_in = (data << (n - m)) ^ seed; + } + + crc_out = crc_div(crc_in, data, gen, n, m); + + if (inv) { + crc_out = ~crc_out; + } + + return extract32(crc_out, 0, n); +} + uint32_t helper_shuffle(uint32_t arg0, uint32_t arg1) { uint32_t resb; @@ -2395,7 +2458,7 @@ static bool cdc_zero(target_ulong *psw) return count == 0; } -static void save_context_upper(CPUTriCoreState *env, int ea) +static void save_context_upper(CPUTriCoreState *env, target_ulong ea) { cpu_stl_data(env, ea, env->PCXI); cpu_stl_data(env, ea+4, psw_read(env)); @@ -2415,7 +2478,7 @@ static void save_context_upper(CPUTriCoreState *env, int ea) cpu_stl_data(env, ea+60, env->gpr_d[15]); } -static void save_context_lower(CPUTriCoreState *env, int ea) +static void save_context_lower(CPUTriCoreState *env, target_ulong ea) { cpu_stl_data(env, ea, env->PCXI); cpu_stl_data(env, ea+4, env->gpr_a[11]); @@ -2435,7 +2498,7 @@ static void save_context_lower(CPUTriCoreState *env, int ea) cpu_stl_data(env, ea+60, env->gpr_d[7]); } -static void restore_context_upper(CPUTriCoreState *env, int ea, +static void restore_context_upper(CPUTriCoreState *env, target_ulong ea, target_ulong *new_PCXI, target_ulong *new_PSW) { *new_PCXI = cpu_ldl_data(env, ea); @@ -2456,7 +2519,7 @@ static void restore_context_upper(CPUTriCoreState *env, int ea, env->gpr_d[15] = cpu_ldl_data(env, ea+60); } -static void restore_context_lower(CPUTriCoreState *env, int ea, +static void restore_context_lower(CPUTriCoreState *env, target_ulong ea, target_ulong *ra, target_ulong *pcxi) { *pcxi = cpu_ldl_data(env, ea); @@ -2700,26 +2763,26 @@ void helper_rfm(CPUTriCoreState *env) } } -void helper_ldlcx(CPUTriCoreState *env, uint32_t ea) +void helper_ldlcx(CPUTriCoreState *env, target_ulong ea) { uint32_t dummy; /* insn doesn't load PCXI and RA */ restore_context_lower(env, ea, &dummy, &dummy); } -void helper_lducx(CPUTriCoreState *env, uint32_t ea) +void helper_lducx(CPUTriCoreState *env, target_ulong ea) { uint32_t dummy; /* insn doesn't load PCXI and PSW */ restore_context_upper(env, ea, &dummy, &dummy); } -void helper_stlcx(CPUTriCoreState *env, uint32_t ea) +void helper_stlcx(CPUTriCoreState *env, target_ulong ea) { save_context_lower(env, ea); } -void helper_stucx(CPUTriCoreState *env, uint32_t ea) +void helper_stucx(CPUTriCoreState *env, target_ulong ea) { save_context_upper(env, ea); } diff --git a/target/tricore/translate.c b/target/tricore/translate.c index 6ae5ccbf72..7b53307eff 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -5310,8 +5310,11 @@ static void decode_rcpw_insert(DisasContext *ctx) } break; case OPC2_32_RCPW_INSERT: + /* tcg_gen_deposit_tl() does not handle the case of width = 0 */ + if (width == 0) { + tcg_gen_mov_tl(cpu_gpr_d[r2], cpu_gpr_d[r1]); /* if pos + width > 32 undefined result */ - if (pos + width <= 32) { + } else if (pos + width <= 32) { temp = tcg_constant_i32(const4); tcg_gen_deposit_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], temp, pos, width); } @@ -6260,6 +6263,20 @@ static void decode_rr_divide(DisasContext *ctx) case OPC2_32_RR_DIV_F: gen_helper_fdiv(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); break; + case OPC2_32_RR_FTOHP: + if (has_feature(ctx, TRICORE_FEATURE_162)) { + gen_helper_ftohp(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); + } else { + generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); + } + break; + case OPC2_32_RR_HPTOF: + if (has_feature(ctx, TRICORE_FEATURE_162)) { + gen_helper_hptof(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); + } else { + generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); + } + break; case OPC2_32_RR_CMP_F: gen_helper_fcmp(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); break; @@ -6269,8 +6286,15 @@ static void decode_rr_divide(DisasContext *ctx) case OPC2_32_RR_ITOF: gen_helper_itof(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); break; + case OPC2_32_RR_FTOU: + gen_helper_ftou(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); + break; case OPC2_32_RR_FTOUZ: - gen_helper_ftouz(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); + if (has_feature(ctx, TRICORE_FEATURE_131)) { + gen_helper_ftouz(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); + } else { + generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); + } break; case OPC2_32_RR_UPDFL: gen_helper_updfl(cpu_env, cpu_gpr_d[r1]); @@ -6554,7 +6578,10 @@ static void decode_rrpw_extract_insert(DisasContext *ctx) break; case OPC2_32_RRPW_INSERT: - if (pos + width <= 32) { + /* tcg_gen_deposit_tl() does not handle the case of width = 0 */ + if (width == 0) { + tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r1]); + } else if (pos + width <= 32) { tcg_gen_deposit_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], pos, width); } @@ -6669,6 +6696,14 @@ static void decode_rrr_divide(DisasContext *ctx) gen_helper_pack(cpu_gpr_d[r4], cpu_PSW_C, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]); break; + case OPC2_32_RRR_CRCN: + if (has_feature(ctx, TRICORE_FEATURE_162)) { + gen_helper_crcn(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r2], + cpu_gpr_d[r3]); + } else { + generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); + } + break; case OPC2_32_RRR_ADD_F: gen_helper_fadd(cpu_gpr_d[r4], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r3]); break; @@ -8192,12 +8227,12 @@ static void decode_32Bit_opc(DisasContext *ctx) temp2 = tcg_temp_new(); /* width*/ temp3 = tcg_temp_new(); /* pos */ - CHECK_REG_PAIR(r3); + CHECK_REG_PAIR(r2); - tcg_gen_andi_tl(temp2, cpu_gpr_d[r3+1], 0x1f); - tcg_gen_andi_tl(temp3, cpu_gpr_d[r3], 0x1f); + tcg_gen_andi_tl(temp2, cpu_gpr_d[r2 + 1], 0x1f); + tcg_gen_andi_tl(temp3, cpu_gpr_d[r2], 0x1f); - gen_insert(cpu_gpr_d[r2], cpu_gpr_d[r1], temp, temp2, temp3); + gen_insert(cpu_gpr_d[r3], cpu_gpr_d[r1], temp, temp2, temp3); break; /* RCRW Format */ case OPCM_32_RCRW_MASK_INSERT: @@ -8367,7 +8402,7 @@ static bool insn_crosses_page(CPUTriCoreState *env, DisasContext *ctx) * 4 bytes from the page boundary, so we cross the page if the first * 16 bits indicate that this is a 32 bit insn. */ - uint16_t insn = cpu_lduw_code(env, ctx->base.pc_next); + uint16_t insn = translator_lduw(env, &ctx->base, ctx->base.pc_next); return !tricore_insn_is_16bit(insn); } @@ -8380,14 +8415,15 @@ static void tricore_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) uint16_t insn_lo; bool is_16bit; - insn_lo = cpu_lduw_code(env, ctx->base.pc_next); + insn_lo = translator_lduw(env, &ctx->base, ctx->base.pc_next); is_16bit = tricore_insn_is_16bit(insn_lo); if (is_16bit) { ctx->opcode = insn_lo; ctx->pc_succ_insn = ctx->base.pc_next + 2; decode_16Bit_opc(ctx); } else { - uint32_t insn_hi = cpu_lduw_code(env, ctx->base.pc_next + 2); + uint32_t insn_hi = translator_lduw(env, &ctx->base, + ctx->base.pc_next + 2); ctx->opcode = insn_hi << 16 | insn_lo; ctx->pc_succ_insn = ctx->base.pc_next + 4; decode_32Bit_opc(ctx); diff --git a/target/tricore/tricore-opcodes.h b/target/tricore/tricore-opcodes.h index bc62b73173..60d2402b6e 100644 --- a/target/tricore/tricore-opcodes.h +++ b/target/tricore/tricore-opcodes.h @@ -1152,6 +1152,8 @@ enum { OPC2_32_RR_ITOF = 0x14, OPC2_32_RR_CMP_F = 0x00, OPC2_32_RR_FTOIZ = 0x13, + OPC2_32_RR_FTOHP = 0x25, /* 1.6.2 only */ + OPC2_32_RR_HPTOF = 0x24, /* 1.6.2 only */ OPC2_32_RR_FTOQ31 = 0x11, OPC2_32_RR_FTOQ31Z = 0x18, OPC2_32_RR_FTOU = 0x12, @@ -1247,6 +1249,7 @@ enum { OPC2_32_RRR_SUB_F = 0x03, OPC2_32_RRR_MADD_F = 0x06, OPC2_32_RRR_MSUB_F = 0x07, + OPC2_32_RRR_CRCN = 0x01, /* 1.6.2 up */ }; /* * RRR1 Format |