- 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-----

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>
This commit is contained in:
Stefan Hajnoczi 2023-10-02 14:42:17 -04:00
commit a3108b2d92
15 changed files with 375 additions and 174 deletions

View File

@ -16,6 +16,7 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/log.h"
#include "hw/sysbus.h" #include "hw/sysbus.h"
#include "hw/qdev-properties.h" #include "hw/qdev-properties.h"
#include "hw/tricore/tricore_testdevice.h" #include "hw/tricore/tricore_testdevice.h"
@ -23,6 +24,9 @@
static void tricore_testdevice_write(void *opaque, hwaddr offset, static void tricore_testdevice_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size) uint64_t value, unsigned size)
{ {
if (value != 0) {
qemu_log_mask(LOG_GUEST_ERROR, "Test %" PRIu64 " failed!\n", value);
}
exit(value); exit(value);
} }

View File

@ -30,150 +30,25 @@ typedef struct CPUArchState {
/* GPR Register */ /* GPR Register */
uint32_t gpr_a[16]; uint32_t gpr_a[16];
uint32_t gpr_d[16]; uint32_t gpr_d[16];
/* CSFR Register */
uint32_t PCXI;
/* Frequently accessed PSW_USB bits are stored separately for efficiency. /* Frequently accessed PSW_USB bits are stored separately for efficiency.
This contains all the other bits. Use psw_{read,write} to access This contains all the other bits. Use psw_{read,write} to access
the whole PSW. */ the whole PSW. */
uint32_t 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_C;
uint32_t PSW_USB_V; /* Only if bit 31 set, then flag is set */ 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_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_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 PSW_USB_SAV; /* Only if bit 31 set, then flag is set. */
uint32_t PC; #define R(ADDR, NAME, FEATURE) uint32_t NAME;
uint32_t SYSCON; #define A(ADDR, NAME, FEATURE) uint32_t NAME;
uint32_t CPU_ID; #define E(ADDR, NAME, FEATURE) uint32_t NAME;
uint32_t CORE_ID; #include "csfr.h.inc"
uint32_t BIV; #undef R
uint32_t BTV; #undef A
uint32_t ISP; #undef E
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;
/* Floating Point Registers */ /* Floating Point Registers */
float_status fp_status; float_status fp_status;

View File

@ -373,6 +373,80 @@ uint32_t helper_ftoi(CPUTriCoreState *env, uint32_t arg)
return (uint32_t)result; 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) uint32_t helper_itof(CPUTriCoreState *env, uint32_t arg)
{ {
float32 f_result; float32 f_result;
@ -429,6 +503,38 @@ uint32_t helper_ftoiz(CPUTriCoreState *env, uint32_t arg)
return result; 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) uint32_t helper_ftouz(CPUTriCoreState *env, uint32_t arg)
{ {
float32 f_arg = make_float32(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)) { if (float32_is_any_nan(f_arg)) {
result = 0; 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)) { } else if (float32_lt_quiet(f_arg, 0, &env->fp_status)) {
flags = float_flag_invalid; flags = float_flag_invalid;
result = 0; result = 0;

View File

@ -120,16 +120,31 @@ void tricore_cpu_list(void)
void fpu_set_state(CPUTriCoreState *env) 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_inputs_to_zero(1, &env->fp_status);
set_flush_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); set_default_nan_mode(1, &env->fp_status);
} }
uint32_t psw_read(CPUTriCoreState *env) uint32_t psw_read(CPUTriCoreState *env)
{ {
/* clear all USB bits */ /* clear all USB bits */
env->PSW &= 0x6ffffff; env->PSW &= 0x7ffffff;
/* now set them from the cache */ /* now set them from the cache */
env->PSW |= ((env->PSW_USB_C != 0) << 31); env->PSW |= ((env->PSW_USB_C != 0) << 31);
env->PSW |= ((env->PSW_USB_V & (1 << 31)) >> 1); env->PSW |= ((env->PSW_USB_V & (1 << 31)) >> 1);

View File

@ -111,9 +111,12 @@ DEF_HELPER_4(fmsub, i32, env, i32, i32, i32)
DEF_HELPER_3(fcmp, i32, env, i32, i32) DEF_HELPER_3(fcmp, i32, env, i32, i32)
DEF_HELPER_2(qseed, i32, env, i32) DEF_HELPER_2(qseed, i32, env, i32)
DEF_HELPER_2(ftoi, 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(itof, i32, env, i32)
DEF_HELPER_2(utof, i32, env, i32) DEF_HELPER_2(utof, i32, env, i32)
DEF_HELPER_2(ftoiz, 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(ftouz, i32, env, i32)
DEF_HELPER_2(updfl, void, env, i32) DEF_HELPER_2(updfl, void, env, i32)
/* dvinit */ /* 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(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_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_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) DEF_HELPER_FLAGS_2(shuffle, TCG_CALL_NO_RWG_SE, i32, i32, i32)
/* CSA */ /* CSA */
DEF_HELPER_2(call, void, env, i32) DEF_HELPER_2(call, void, env, i32)

View File

@ -2308,6 +2308,69 @@ uint32_t helper_crc32_le(uint32_t arg0, uint32_t arg1)
return crc32(arg1, buf, 4); 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 helper_shuffle(uint32_t arg0, uint32_t arg1)
{ {
uint32_t resb; uint32_t resb;
@ -2395,7 +2458,7 @@ static bool cdc_zero(target_ulong *psw)
return count == 0; 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, env->PCXI);
cpu_stl_data(env, ea+4, psw_read(env)); 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]); 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, env->PCXI);
cpu_stl_data(env, ea+4, env->gpr_a[11]); 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]); 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) target_ulong *new_PCXI, target_ulong *new_PSW)
{ {
*new_PCXI = cpu_ldl_data(env, ea); *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); 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) target_ulong *ra, target_ulong *pcxi)
{ {
*pcxi = cpu_ldl_data(env, ea); *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; uint32_t dummy;
/* insn doesn't load PCXI and RA */ /* insn doesn't load PCXI and RA */
restore_context_lower(env, ea, &dummy, &dummy); 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; uint32_t dummy;
/* insn doesn't load PCXI and PSW */ /* insn doesn't load PCXI and PSW */
restore_context_upper(env, ea, &dummy, &dummy); 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); 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); save_context_upper(env, ea);
} }

View File

@ -5310,8 +5310,11 @@ static void decode_rcpw_insert(DisasContext *ctx)
} }
break; break;
case OPC2_32_RCPW_INSERT: 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 undefined result */
if (pos + width <= 32) { } else if (pos + width <= 32) {
temp = tcg_constant_i32(const4); temp = tcg_constant_i32(const4);
tcg_gen_deposit_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], temp, pos, width); 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: case OPC2_32_RR_DIV_F:
gen_helper_fdiv(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); gen_helper_fdiv(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
break; 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: case OPC2_32_RR_CMP_F:
gen_helper_fcmp(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); gen_helper_fcmp(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
break; break;
@ -6269,8 +6286,15 @@ static void decode_rr_divide(DisasContext *ctx)
case OPC2_32_RR_ITOF: case OPC2_32_RR_ITOF:
gen_helper_itof(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); gen_helper_itof(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]);
break; 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: case OPC2_32_RR_FTOUZ:
if (has_feature(ctx, TRICORE_FEATURE_131)) {
gen_helper_ftouz(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); gen_helper_ftouz(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]);
} else {
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
}
break; break;
case OPC2_32_RR_UPDFL: case OPC2_32_RR_UPDFL:
gen_helper_updfl(cpu_env, cpu_gpr_d[r1]); gen_helper_updfl(cpu_env, cpu_gpr_d[r1]);
@ -6554,7 +6578,10 @@ static void decode_rrpw_extract_insert(DisasContext *ctx)
break; break;
case OPC2_32_RRPW_INSERT: 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], tcg_gen_deposit_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2],
pos, width); 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], gen_helper_pack(cpu_gpr_d[r4], cpu_PSW_C, cpu_gpr_d[r3],
cpu_gpr_d[r3+1], cpu_gpr_d[r1]); cpu_gpr_d[r3+1], cpu_gpr_d[r1]);
break; 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: case OPC2_32_RRR_ADD_F:
gen_helper_fadd(cpu_gpr_d[r4], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r3]); gen_helper_fadd(cpu_gpr_d[r4], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r3]);
break; break;
@ -8192,12 +8227,12 @@ static void decode_32Bit_opc(DisasContext *ctx)
temp2 = tcg_temp_new(); /* width*/ temp2 = tcg_temp_new(); /* width*/
temp3 = tcg_temp_new(); /* pos */ 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(temp2, cpu_gpr_d[r2 + 1], 0x1f);
tcg_gen_andi_tl(temp3, cpu_gpr_d[r3], 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; break;
/* RCRW Format */ /* RCRW Format */
case OPCM_32_RCRW_MASK_INSERT: 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 * 4 bytes from the page boundary, so we cross the page if the first
* 16 bits indicate that this is a 32 bit insn. * 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); return !tricore_insn_is_16bit(insn);
} }
@ -8380,14 +8415,15 @@ static void tricore_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
uint16_t insn_lo; uint16_t insn_lo;
bool is_16bit; 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); is_16bit = tricore_insn_is_16bit(insn_lo);
if (is_16bit) { if (is_16bit) {
ctx->opcode = insn_lo; ctx->opcode = insn_lo;
ctx->pc_succ_insn = ctx->base.pc_next + 2; ctx->pc_succ_insn = ctx->base.pc_next + 2;
decode_16Bit_opc(ctx); decode_16Bit_opc(ctx);
} else { } 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->opcode = insn_hi << 16 | insn_lo;
ctx->pc_succ_insn = ctx->base.pc_next + 4; ctx->pc_succ_insn = ctx->base.pc_next + 4;
decode_32Bit_opc(ctx); decode_32Bit_opc(ctx);

View File

@ -1152,6 +1152,8 @@ enum {
OPC2_32_RR_ITOF = 0x14, OPC2_32_RR_ITOF = 0x14,
OPC2_32_RR_CMP_F = 0x00, OPC2_32_RR_CMP_F = 0x00,
OPC2_32_RR_FTOIZ = 0x13, 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_FTOQ31 = 0x11,
OPC2_32_RR_FTOQ31Z = 0x18, OPC2_32_RR_FTOQ31Z = 0x18,
OPC2_32_RR_FTOU = 0x12, OPC2_32_RR_FTOU = 0x12,
@ -1247,6 +1249,7 @@ enum {
OPC2_32_RRR_SUB_F = 0x03, OPC2_32_RRR_SUB_F = 0x03,
OPC2_32_RRR_MADD_F = 0x06, OPC2_32_RRR_MADD_F = 0x06,
OPC2_32_RRR_MSUB_F = 0x07, OPC2_32_RRR_MSUB_F = 0x07,
OPC2_32_RRR_CRCN = 0x01, /* 1.6.2 up */
}; };
/* /*
* RRR1 Format * RRR1 Format

View File

@ -9,11 +9,15 @@ CFLAGS = -mtc162 -c -I$(TESTS_PATH)
TESTS += test_abs.asm.tst TESTS += test_abs.asm.tst
TESTS += test_bmerge.asm.tst TESTS += test_bmerge.asm.tst
TESTS += test_clz.asm.tst TESTS += test_clz.asm.tst
TESTS += test_crcn.asm.tst
TESTS += test_dextr.asm.tst TESTS += test_dextr.asm.tst
TESTS += test_dvstep.asm.tst TESTS += test_dvstep.asm.tst
TESTS += test_fadd.asm.tst TESTS += test_fadd.asm.tst
TESTS += test_fmul.asm.tst TESTS += test_fmul.asm.tst
TESTS += test_ftohp.asm.tst
TESTS += test_ftoi.asm.tst TESTS += test_ftoi.asm.tst
TESTS += test_ftou.asm.tst
TESTS += test_hptof.asm.tst
TESTS += test_imask.asm.tst TESTS += test_imask.asm.tst
TESTS += test_insert.asm.tst TESTS += test_insert.asm.tst
TESTS += test_ld_bu.asm.tst TESTS += test_ld_bu.asm.tst
@ -25,7 +29,7 @@ TESTS += test_muls.asm.tst
TESTS += test_boot_to_main.c.tst TESTS += test_boot_to_main.c.tst
TESTS += test_context_save_areas.c.tst TESTS += test_context_save_areas.c.tst
QEMU_OPTS += -M tricore_testboard -cpu tc27x -nographic -kernel QEMU_OPTS += -M tricore_testboard -cpu tc37x -nographic -kernel
%.pS: $(ASM_TESTS_PATH)/%.S %.pS: $(ASM_TESTS_PATH)/%.S
$(CC) -E -o $@ $< $(CC) -E -o $@ $<

View File

@ -12,31 +12,31 @@
#define TESTDEV_ADDR 0xf0000000 #define TESTDEV_ADDR 0xf0000000
/* Register definitions */ /* Register definitions */
#define DREG_RS1 %d0 #define DREG_RS1 %d0
#define DREG_RS2 %d1 #define DREG_RS2 %d2
#define DREG_RS3 %d2 #define DREG_RS3 %d4
#define DREG_CALC_RESULT %d3 #define DREG_CALC_RESULT %d5
#define DREG_CALC_PSW %d4 #define DREG_CALC_PSW %d6
#define DREG_CORRECT_PSW %d5 #define DREG_CORRECT_PSW %d7
#define DREG_TEMP_LI %d10 #define DREG_TEMP_LI %d13
#define DREG_TEMP %d11 #define DREG_TEMP %d14
#define DREG_TEST_NUM %d14 #define DREG_TEST_NUM %d8
#define DREG_CORRECT_RESULT %d15 #define DREG_CORRECT_RESULT %d9
#define DREG_CORRECT_RESULT_2 %d13 #define DREG_CORRECT_RESULT_2 %d10
#define AREG_ADDR %a0 #define AREG_ADDR %a0
#define AREG_CORRECT_RESULT %a3 #define AREG_CORRECT_RESULT %a3
#define DREG_DEV_ADDR %a15 #define DREG_DEV_ADDR %a15
#define EREG_RS1 %e6 #define EREG_RS1 %e0
#define EREG_RS1_LO %d6 #define EREG_RS1_LO %d0
#define EREG_RS1_HI %d7 #define EREG_RS1_HI %d1
#define EREG_RS2 %e8 #define EREG_RS2 %e2
#define EREG_RS2_LO %d8 #define EREG_RS2_LO %d2
#define EREG_RS2_HI %d9 #define EREG_RS2_HI %d3
#define EREG_CALC_RESULT %e8 #define EREG_CALC_RESULT %e6
#define EREG_CALC_RESULT_HI %d9 #define EREG_CALC_RESULT_LO %d6
#define EREG_CALC_RESULT_LO %d8 #define EREG_CALC_RESULT_HI %d7
#define EREG_CORRECT_RESULT_LO %d0 #define EREG_CORRECT_RESULT_LO %d0
#define EREG_CORRECT_RESULT_HI %d1 #define EREG_CORRECT_RESULT_HI %d1
@ -46,7 +46,8 @@ test_ ## num: \
code; \ code; \
LI(DREG_CORRECT_RESULT, correct) \ LI(DREG_CORRECT_RESULT, correct) \
mov DREG_TEST_NUM, num; \ mov DREG_TEST_NUM, num; \
jne testreg, DREG_CORRECT_RESULT, fail \ jne testreg, DREG_CORRECT_RESULT, fail; \
mov testreg, 0
#define TEST_CASE_E(num, correct_lo, correct_hi, code...) \ #define TEST_CASE_E(num, correct_lo, correct_hi, code...) \
test_ ## num: \ test_ ## num: \
@ -161,6 +162,30 @@ test_ ## num: \
insn DREG_CALC_RESULT, DREG_RS1, imm1, DREG_RS2, imm2; \ insn DREG_CALC_RESULT, DREG_RS1, imm1, DREG_RS2, imm2; \
) )
#define TEST_D_DDII(insn, num, result, rs1, rs2, imm1, imm2) \
TEST_CASE(num, DREG_CALC_RESULT, result, \
LI(DREG_RS1, rs1); \
LI(DREG_RS2, rs2); \
rstv; \
insn DREG_CALC_RESULT, DREG_RS1, DREG_RS2, imm1, imm2; \
)
#define TEST_D_DIE(insn, num, result, rs1, imm1, rs2_lo, rs2_hi)\
TEST_CASE(num, DREG_CALC_RESULT, result, \
LI(DREG_RS1, rs1); \
LI(EREG_RS2_LO, rs2_lo); \
LI(EREG_RS2_HI, rs2_hi); \
rstv; \
insn DREG_CALC_RESULT, DREG_RS1, imm1, EREG_RS2; \
)
#define TEST_D_DIII(insn, num, result, rs1, imm1, imm2, imm3)\
TEST_CASE(num, DREG_CALC_RESULT, result, \
LI(DREG_RS1, rs1); \
rstv; \
insn DREG_CALC_RESULT, DREG_RS1, imm1, imm2, imm3; \
)
#define TEST_E_ED(insn, num, res_hi, res_lo, rs1_hi, rs1_lo, rs2) \ #define TEST_E_ED(insn, num, res_hi, res_lo, rs1_hi, rs1_lo, rs2) \
TEST_CASE_E(num, res_lo, res_hi, \ TEST_CASE_E(num, res_lo, res_hi, \
LI(EREG_RS1_LO, rs1_lo); \ LI(EREG_RS1_LO, rs1_lo); \

View File

@ -0,0 +1,9 @@
#include "macros.h"
.text
.global _start
_start:
# insn num result rs1 rs2 rs3
# | | | | | |
TEST_D_DDD(crcn, 1, 0x00002bed, 0x0, 0xa10ddeed, 0x0)
TEST_PASSFAIL

View File

@ -0,0 +1,14 @@
#include "macros.h"
.text
.global _start
_start:
TEST_D_D(ftohp, 1, 0xffff, 0xffffffff)
TEST_D_D(ftohp, 2, 0xfc00, 0xff800000)
TEST_D_D(ftohp, 3, 0x7c00, 0x7f800000)
TEST_D_D(ftohp, 4, 0x0, 0x0)
TEST_D_D(ftohp, 5, 0x5, 0x34a43580)
#TEST_D_D_PSW(ftohp, 6, 0x400, 0x8c000b80, 0x387fee74)
TEST_PASSFAIL

View File

@ -0,0 +1,12 @@
#include "macros.h"
.text
.global _start
_start:
TEST_D_D(ftou, 1, 0x00000000, 0x1733f6c2)
TEST_D_D(ftou, 2, 0x00000000, 0x2c9d9cdc)
TEST_D_D(ftou, 3, 0xffffffff, 0x56eb7395)
TEST_D_D(ftou, 4, 0x79900800, 0x4ef32010)
TEST_D_D(ftou, 5, 0x0353f510, 0x4c54fd44)
TEST_PASSFAIL

View File

@ -0,0 +1,12 @@
#include "macros.h"
.text
.global _start
_start:
TEST_D_D(hptof, 1, 0xba190000, 0xcc0e90c8)
TEST_D_D(hptof, 2, 0x3eaea000, 0x8be23575)
TEST_D_D(hptof, 3, 0xc33b8000, 0xcc48d9dc)
TEST_D_D(hptof, 4, 0x43e2a000, 0xaef95f15)
TEST_D_D(hptof, 5, 0x3d55e000, 0x04932aaf)
TEST_PASSFAIL

View File

@ -6,4 +6,18 @@ _start:
# | | | | | | | # | | | | | | |
TEST_D_DIDI(insert, 1, 0x7fffffff, 0xffffffff, 0xa, 0x10, 0x8) TEST_D_DIDI(insert, 1, 0x7fffffff, 0xffffffff, 0xa, 0x10, 0x8)
# insn num result rs1 imm1 imm2 imm3
# | | | | | | |
TEST_D_DIII(insert, 2, 0xd38fe370, 0xd38fe370, 0x4, 0x4 , 0x0)
TEST_D_DIII(insert, 3, 0xd38fe374, 0xd38fe370, 0x4, 0x0 , 0x4)
# insn num result rs1 rs2 pos width
# | | | | | | |
TEST_D_DDII(insert, 4, 0x03c1e53c, 0x03c1e53c, 0x45821385, 0x7 ,0x0)
# insn num result rs1 imm1 rs2_h rs2_l
# | | | | | | |
TEST_D_DIE(insert, 5, 0xe30c308d, 0xe30c308d ,0x3 , 0x00000000 ,0x00000000)
TEST_D_DIE(insert, 6, 0x669b0120, 0x669b2820 ,0x2 , 0x5530a1c7 ,0x3a2b0f67)
TEST_PASSFAIL TEST_PASSFAIL