ppc queue:
* PNV I2C fixes * VSX instruction fix when converting floating point to integer values -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmVcZ18ACgkQUaNDx8/7 7KG1GBAAopdIWc33pY1kaJlHxXDDtTxShWT384r62unPO0vaDtvmlLBvD0kTRIzk E6OcWeGS/L2D03nI127o5Y677koL20TlOpsR4fZdOwbQUSSVTMsLN5m8Rqvu4Ptx zA8t/Oio+RTxkZ1SHRuEQNC5EWzFklm5R95zyvLEAbMdJ44thlXyo9KgWe8XoBBV tkreEzWvv4F4Nf7nZYnxvOIHsi/8No0bMMjBNGC/v+svpayuaWmsCP4/4vmVRYRP 28R6uMooo9xu0X6oBzqbAV6y6XFSP8pwsvVPd1yAbFhS3w2qw18VpWoMUl2UkVGx ZNNHjt3HPtGAEtnWAdvzVS8sFi929pHf2v5/h8gEhfZ2e4NVS1zJj3K3OqJgWfEB XjiIO4NF4gnbXKIlvZX8m5RqdtxbdKx7BVmJtlzJd7IDERRLe0cNSCZ06s/GcICi AHtxhyA5GGWs2HDQwkOimwDOholjjVbz/sIcHLCpm/jyxcdk9VwE6hBO/9nTcntg IaQ/kWHlbQgTNXNuFDBwiOMuEQ5G4bb6sdqH+CWZU/owFqgXHIlki7oneX6SB09T GUyVwScLWlspCJRpX/y4ubyfGB3ZqAQ9REita4YIMveDvNU83LS344MRrBpzQ+ZI 1yCoHdBsNUkpr9dN/uwkjDSBlDoyWJ2TAgQHsprNUD04ChML7Fs= =qx4p -----END PGP SIGNATURE----- Merge tag 'pull-ppc-20231121' of https://github.com/legoater/qemu into staging ppc queue: * PNV I2C fixes * VSX instruction fix when converting floating point to integer values # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmVcZ18ACgkQUaNDx8/7 # 7KG1GBAAopdIWc33pY1kaJlHxXDDtTxShWT384r62unPO0vaDtvmlLBvD0kTRIzk # E6OcWeGS/L2D03nI127o5Y677koL20TlOpsR4fZdOwbQUSSVTMsLN5m8Rqvu4Ptx # zA8t/Oio+RTxkZ1SHRuEQNC5EWzFklm5R95zyvLEAbMdJ44thlXyo9KgWe8XoBBV # tkreEzWvv4F4Nf7nZYnxvOIHsi/8No0bMMjBNGC/v+svpayuaWmsCP4/4vmVRYRP # 28R6uMooo9xu0X6oBzqbAV6y6XFSP8pwsvVPd1yAbFhS3w2qw18VpWoMUl2UkVGx # ZNNHjt3HPtGAEtnWAdvzVS8sFi929pHf2v5/h8gEhfZ2e4NVS1zJj3K3OqJgWfEB # XjiIO4NF4gnbXKIlvZX8m5RqdtxbdKx7BVmJtlzJd7IDERRLe0cNSCZ06s/GcICi # AHtxhyA5GGWs2HDQwkOimwDOholjjVbz/sIcHLCpm/jyxcdk9VwE6hBO/9nTcntg # IaQ/kWHlbQgTNXNuFDBwiOMuEQ5G4bb6sdqH+CWZU/owFqgXHIlki7oneX6SB09T # GUyVwScLWlspCJRpX/y4ubyfGB3ZqAQ9REita4YIMveDvNU83LS344MRrBpzQ+ZI # 1yCoHdBsNUkpr9dN/uwkjDSBlDoyWJ2TAgQHsprNUD04ChML7Fs= # =qx4p # -----END PGP SIGNATURE----- # gpg: Signature made Tue 21 Nov 2023 03:16:31 EST # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@redhat.com>" [unknown] # gpg: aka "Cédric Le Goater <clg@kaod.org>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * tag 'pull-ppc-20231121' of https://github.com/legoater/qemu: ppc/pnv: Fix PNV I2C invalid status after reset ppc/pnv: PNV I2C engines assigned incorrect XSCOM addresses target/ppc: Fix bugs in VSX_CVT_FP_TO_INT and VSX_CVT_FP_TO_INT2 macros ppc/pnv: Fix potential overflow in I2C model Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
adf798b379
@ -1623,7 +1623,8 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
pnv_xscom_add_subregion(chip, PNV9_XSCOM_I2CM_BASE +
|
||||
chip9->i2c[i].engine * PNV9_XSCOM_I2CM_SIZE,
|
||||
(chip9->i2c[i].engine - 1) *
|
||||
PNV9_XSCOM_I2CM_SIZE,
|
||||
&chip9->i2c[i].xscom_regs);
|
||||
qdev_connect_gpio_out(DEVICE(&chip9->i2c[i]), 0,
|
||||
qdev_get_gpio_in(DEVICE(&chip9->psi),
|
||||
@ -1871,7 +1872,8 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
pnv_xscom_add_subregion(chip, PNV10_XSCOM_I2CM_BASE +
|
||||
chip10->i2c[i].engine * PNV10_XSCOM_I2CM_SIZE,
|
||||
(chip10->i2c[i].engine - 1) *
|
||||
PNV10_XSCOM_I2CM_SIZE,
|
||||
&chip10->i2c[i].xscom_regs);
|
||||
qdev_connect_gpio_out(DEVICE(&chip10->i2c[i]), 0,
|
||||
qdev_get_gpio_in(DEVICE(&chip10->psi),
|
||||
|
@ -151,6 +151,7 @@
|
||||
#define I2C_RESET_S_SDA_REG 0x11
|
||||
|
||||
#define PNV_I2C_FIFO_SIZE 8
|
||||
#define PNV_I2C_MAX_BUSSES 64
|
||||
|
||||
static I2CBus *pnv_i2c_get_bus(PnvI2C *i2c)
|
||||
{
|
||||
@ -437,7 +438,7 @@ static uint64_t pnv_i2c_xscom_read(void *opaque, hwaddr addr,
|
||||
case I2C_PORT_BUSY_REG: /* compute busy bit for each port */
|
||||
val = 0;
|
||||
for (i = 0; i < i2c->num_busses; i++) {
|
||||
val |= i2c_bus_busy(i2c->busses[i]) << i;
|
||||
val |= (uint64_t)i2c_bus_busy(i2c->busses[i]) << i;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -462,6 +463,23 @@ static uint64_t pnv_i2c_xscom_read(void *opaque, hwaddr addr,
|
||||
return val;
|
||||
}
|
||||
|
||||
static void pnv_i2c_reset(void *dev)
|
||||
{
|
||||
PnvI2C *i2c = PNV_I2C(dev);
|
||||
|
||||
memset(i2c->regs, 0, sizeof(i2c->regs));
|
||||
|
||||
i2c->regs[I2C_STAT_REG] =
|
||||
SETFIELD(I2C_STAT_UPPER_THRS, 0ull, i2c->num_busses - 1) |
|
||||
I2C_STAT_CMD_COMP | I2C_STAT_SCL_INPUT_LEVEL |
|
||||
I2C_STAT_SDA_INPUT_LEVEL;
|
||||
i2c->regs[I2C_EXTD_STAT_REG] =
|
||||
SETFIELD(I2C_EXTD_STAT_FIFO_SIZE, 0ull, PNV_I2C_FIFO_SIZE) |
|
||||
SETFIELD(I2C_EXTD_STAT_I2C_VERSION, 0ull, 23); /* last version */
|
||||
|
||||
fifo8_reset(&i2c->fifo);
|
||||
}
|
||||
|
||||
static void pnv_i2c_xscom_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
@ -499,16 +517,7 @@ static void pnv_i2c_xscom_write(void *opaque, hwaddr addr,
|
||||
break;
|
||||
|
||||
case I2C_RESET_I2C_REG:
|
||||
i2c->regs[I2C_MODE_REG] = 0;
|
||||
i2c->regs[I2C_CMD_REG] = 0;
|
||||
i2c->regs[I2C_WATERMARK_REG] = 0;
|
||||
i2c->regs[I2C_INTR_MASK_REG] = 0;
|
||||
i2c->regs[I2C_INTR_COND_REG] = 0;
|
||||
i2c->regs[I2C_INTR_RAW_COND_REG] = 0;
|
||||
i2c->regs[I2C_STAT_REG] = 0;
|
||||
i2c->regs[I2C_RESIDUAL_LEN_REG] = 0;
|
||||
i2c->regs[I2C_EXTD_STAT_REG] &=
|
||||
(I2C_EXTD_STAT_FIFO_SIZE | I2C_EXTD_STAT_I2C_VERSION);
|
||||
pnv_i2c_reset(i2c);
|
||||
break;
|
||||
|
||||
case I2C_RESET_ERRORS:
|
||||
@ -593,7 +602,7 @@ static int pnv_i2c_dt_xscom(PnvXScomInterface *dev, void *fdt,
|
||||
int i2c_offset;
|
||||
const char i2c_compat[] = "ibm,power8-i2cm\0ibm,power9-i2cm";
|
||||
uint32_t i2c_pcba = PNV9_XSCOM_I2CM_BASE +
|
||||
i2c->engine * PNV9_XSCOM_I2CM_SIZE;
|
||||
(i2c->engine - 1) * PNV9_XSCOM_I2CM_SIZE;
|
||||
uint32_t reg[2] = {
|
||||
cpu_to_be32(i2c_pcba),
|
||||
cpu_to_be32(PNV9_XSCOM_I2CM_SIZE)
|
||||
@ -620,20 +629,6 @@ static int pnv_i2c_dt_xscom(PnvXScomInterface *dev, void *fdt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pnv_i2c_reset(void *dev)
|
||||
{
|
||||
PnvI2C *i2c = PNV_I2C(dev);
|
||||
|
||||
memset(i2c->regs, 0, sizeof(i2c->regs));
|
||||
|
||||
i2c->regs[I2C_STAT_REG] = I2C_STAT_CMD_COMP;
|
||||
i2c->regs[I2C_EXTD_STAT_REG] =
|
||||
SETFIELD(I2C_EXTD_STAT_FIFO_SIZE, 0ull, PNV_I2C_FIFO_SIZE) |
|
||||
SETFIELD(I2C_EXTD_STAT_I2C_VERSION, 0ull, 23); /* last version */
|
||||
|
||||
fifo8_reset(&i2c->fifo);
|
||||
}
|
||||
|
||||
static void pnv_i2c_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PnvI2C *i2c = PNV_I2C(dev);
|
||||
@ -641,6 +636,11 @@ static void pnv_i2c_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
assert(i2c->chip);
|
||||
|
||||
if (i2c->num_busses > PNV_I2C_MAX_BUSSES) {
|
||||
error_setg(errp, "Invalid number of busses: %u", i2c->num_busses);
|
||||
return;
|
||||
}
|
||||
|
||||
pnv_xscom_region_init(&i2c->xscom_regs, OBJECT(i2c), &pnv_i2c_xscom_ops,
|
||||
i2c, "xscom-i2c", PNV9_XSCOM_I2CM_SIZE);
|
||||
|
||||
|
@ -2880,20 +2880,22 @@ uint64_t helper_XSCVSPDPN(uint64_t xb)
|
||||
#define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, sfi, rnan) \
|
||||
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
|
||||
{ \
|
||||
int all_flags = 0; \
|
||||
ppc_vsr_t t = { }; \
|
||||
int i, flags; \
|
||||
\
|
||||
helper_reset_fpstatus(env); \
|
||||
\
|
||||
for (i = 0; i < nels; i++) { \
|
||||
helper_reset_fpstatus(env); \
|
||||
t.tfld = stp##_to_##ttp##_round_to_zero(xb->sfld, &env->fp_status); \
|
||||
flags = env->fp_status.float_exception_flags; \
|
||||
all_flags |= flags; \
|
||||
if (unlikely(flags & float_flag_invalid)) { \
|
||||
t.tfld = float_invalid_cvt(env, flags, t.tfld, rnan, 0, GETPC());\
|
||||
} \
|
||||
} \
|
||||
\
|
||||
*xt = t; \
|
||||
env->fp_status.float_exception_flags = all_flags; \
|
||||
do_float_check_status(env, sfi, GETPC()); \
|
||||
}
|
||||
|
||||
@ -2945,15 +2947,16 @@ VSX_CVT_FP_TO_INT128(XSCVQPSQZ, int128, 0x8000000000000000ULL);
|
||||
#define VSX_CVT_FP_TO_INT2(op, nels, stp, ttp, sfi, rnan) \
|
||||
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
|
||||
{ \
|
||||
int all_flags = 0; \
|
||||
ppc_vsr_t t = { }; \
|
||||
int i, flags; \
|
||||
\
|
||||
helper_reset_fpstatus(env); \
|
||||
\
|
||||
for (i = 0; i < nels; i++) { \
|
||||
helper_reset_fpstatus(env); \
|
||||
t.VsrW(2 * i) = stp##_to_##ttp##_round_to_zero(xb->VsrD(i), \
|
||||
&env->fp_status); \
|
||||
flags = env->fp_status.float_exception_flags; \
|
||||
all_flags |= flags; \
|
||||
if (unlikely(flags & float_flag_invalid)) { \
|
||||
t.VsrW(2 * i) = float_invalid_cvt(env, flags, t.VsrW(2 * i), \
|
||||
rnan, 0, GETPC()); \
|
||||
@ -2962,6 +2965,7 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
|
||||
} \
|
||||
\
|
||||
*xt = t; \
|
||||
env->fp_status.float_exception_flags = all_flags; \
|
||||
do_float_check_status(env, sfi, GETPC()); \
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,11 @@ PPC64_TESTS=bcdsub non_signalling_xscv
|
||||
endif
|
||||
$(PPC64_TESTS): CFLAGS += -mpower8-vector
|
||||
|
||||
ifneq ($(CROSS_CC_HAS_POWER8_VECTOR),)
|
||||
PPC64_TESTS += vsx_f2i_nan
|
||||
endif
|
||||
vsx_f2i_nan: CFLAGS += -mpower8-vector -I$(SRC_PATH)/include
|
||||
|
||||
PPC64_TESTS += mtfsf
|
||||
PPC64_TESTS += mffsce
|
||||
|
||||
|
300
tests/tcg/ppc64/vsx_f2i_nan.c
Normal file
300
tests/tcg/ppc64/vsx_f2i_nan.c
Normal file
@ -0,0 +1,300 @@
|
||||
#include <stdio.h>
|
||||
#include "qemu/compiler.h"
|
||||
|
||||
typedef vector float vsx_float32_vec_t;
|
||||
typedef vector double vsx_float64_vec_t;
|
||||
typedef vector signed int vsx_int32_vec_t;
|
||||
typedef vector unsigned int vsx_uint32_vec_t;
|
||||
typedef vector signed long long vsx_int64_vec_t;
|
||||
typedef vector unsigned long long vsx_uint64_vec_t;
|
||||
|
||||
#define DEFINE_VSX_F2I_FUNC(SRC_T, DEST_T, INSN) \
|
||||
static inline vsx_##DEST_T##_vec_t \
|
||||
vsx_convert_##SRC_T##_vec_to_##DEST_T##_vec(vsx_##SRC_T##_vec_t v) \
|
||||
{ \
|
||||
vsx_##DEST_T##_vec_t result; \
|
||||
asm(#INSN " %x0, %x1" : "=wa" (result) : "wa" (v)); \
|
||||
return result; \
|
||||
}
|
||||
|
||||
DEFINE_VSX_F2I_FUNC(float32, int32, xvcvspsxws)
|
||||
DEFINE_VSX_F2I_FUNC(float32, uint32, xvcvspuxws)
|
||||
DEFINE_VSX_F2I_FUNC(float32, int64, xvcvspsxds)
|
||||
DEFINE_VSX_F2I_FUNC(float32, uint64, xvcvspuxds)
|
||||
DEFINE_VSX_F2I_FUNC(float64, int32, xvcvdpsxws)
|
||||
DEFINE_VSX_F2I_FUNC(float64, uint32, xvcvdpuxws)
|
||||
DEFINE_VSX_F2I_FUNC(float64, int64, xvcvdpsxds)
|
||||
DEFINE_VSX_F2I_FUNC(float64, uint64, xvcvdpuxds)
|
||||
|
||||
static inline vsx_float32_vec_t vsx_float32_is_nan(vsx_float32_vec_t v)
|
||||
{
|
||||
vsx_float32_vec_t abs_v;
|
||||
vsx_float32_vec_t result_mask;
|
||||
const vsx_uint32_vec_t f32_pos_inf_bits = {0x7F800000U, 0x7F800000U,
|
||||
0x7F800000U, 0x7F800000U};
|
||||
|
||||
asm("xvabssp %x0, %x1" : "=wa" (abs_v) : "wa" (v));
|
||||
asm("vcmpgtuw %0, %1, %2"
|
||||
: "=v" (result_mask)
|
||||
: "v" (abs_v), "v" (f32_pos_inf_bits));
|
||||
return result_mask;
|
||||
}
|
||||
|
||||
static inline vsx_float64_vec_t vsx_float64_is_nan(vsx_float64_vec_t v)
|
||||
{
|
||||
vsx_float64_vec_t abs_v;
|
||||
vsx_float64_vec_t result_mask;
|
||||
const vsx_uint64_vec_t f64_pos_inf_bits = {0x7FF0000000000000ULL,
|
||||
0x7FF0000000000000ULL};
|
||||
|
||||
asm("xvabsdp %x0, %x1" : "=wa" (abs_v) : "wa" (v));
|
||||
asm("vcmpgtud %0, %1, %2"
|
||||
: "=v" (result_mask)
|
||||
: "v" (abs_v), "v" (f64_pos_inf_bits));
|
||||
return result_mask;
|
||||
}
|
||||
|
||||
#define DEFINE_VSX_BINARY_LOGICAL_OP_INSN(LANE_TYPE, OP_NAME, OP_INSN) \
|
||||
static inline vsx_##LANE_TYPE##_vec_t vsx_##LANE_TYPE##_##OP_NAME( \
|
||||
vsx_##LANE_TYPE##_vec_t a, vsx_##LANE_TYPE##_vec_t b) \
|
||||
{ \
|
||||
vsx_##LANE_TYPE##_vec_t result; \
|
||||
asm(#OP_INSN " %x0, %x1, %x2" : "=wa" (result) : "wa" (a), "wa" (b)); \
|
||||
return result; \
|
||||
}
|
||||
|
||||
DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float32, logical_and, xxland)
|
||||
DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float64, logical_and, xxland)
|
||||
DEFINE_VSX_BINARY_LOGICAL_OP_INSN(int32, logical_and, xxland)
|
||||
DEFINE_VSX_BINARY_LOGICAL_OP_INSN(uint32, logical_and, xxland)
|
||||
DEFINE_VSX_BINARY_LOGICAL_OP_INSN(int64, logical_and, xxland)
|
||||
DEFINE_VSX_BINARY_LOGICAL_OP_INSN(uint64, logical_and, xxland)
|
||||
|
||||
DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float32, logical_andc, xxlandc)
|
||||
DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float64, logical_andc, xxlandc)
|
||||
|
||||
DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float32, logical_or, xxlor)
|
||||
DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float64, logical_or, xxlor)
|
||||
DEFINE_VSX_BINARY_LOGICAL_OP_INSN(int32, logical_or, xxlor)
|
||||
DEFINE_VSX_BINARY_LOGICAL_OP_INSN(uint32, logical_or, xxlor)
|
||||
DEFINE_VSX_BINARY_LOGICAL_OP_INSN(int64, logical_or, xxlor)
|
||||
DEFINE_VSX_BINARY_LOGICAL_OP_INSN(uint64, logical_or, xxlor)
|
||||
|
||||
static inline vsx_int32_vec_t vsx_mask_out_float32_vec_to_int32_vec(
|
||||
vsx_int32_vec_t v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
static inline vsx_uint32_vec_t vsx_mask_out_float32_vec_to_uint32_vec(
|
||||
vsx_uint32_vec_t v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
static inline vsx_int64_vec_t vsx_mask_out_float32_vec_to_int64_vec(
|
||||
vsx_int64_vec_t v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
static inline vsx_uint64_vec_t vsx_mask_out_float32_vec_to_uint64_vec(
|
||||
vsx_uint64_vec_t v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline vsx_int32_vec_t vsx_mask_out_float64_vec_to_int32_vec(
|
||||
vsx_int32_vec_t v)
|
||||
{
|
||||
#if HOST_BIG_ENDIAN
|
||||
const vsx_int32_vec_t valid_lanes_mask = {-1, 0, -1, 0};
|
||||
#else
|
||||
const vsx_int32_vec_t valid_lanes_mask = {0, -1, 0, -1};
|
||||
#endif
|
||||
|
||||
return vsx_int32_logical_and(v, valid_lanes_mask);
|
||||
}
|
||||
|
||||
static inline vsx_uint32_vec_t vsx_mask_out_float64_vec_to_uint32_vec(
|
||||
vsx_uint32_vec_t v)
|
||||
{
|
||||
return (vsx_uint32_vec_t)vsx_mask_out_float64_vec_to_int32_vec(
|
||||
(vsx_int32_vec_t)v);
|
||||
}
|
||||
|
||||
static inline vsx_int64_vec_t vsx_mask_out_float64_vec_to_int64_vec(
|
||||
vsx_int64_vec_t v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
static inline vsx_uint64_vec_t vsx_mask_out_float64_vec_to_uint64_vec(
|
||||
vsx_uint64_vec_t v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline void print_vsx_float32_vec_elements(FILE *stream,
|
||||
vsx_float32_vec_t vec)
|
||||
{
|
||||
fprintf(stream, "%g, %g, %g, %g", (double)vec[0], (double)vec[1],
|
||||
(double)vec[2], (double)vec[3]);
|
||||
}
|
||||
|
||||
static inline void print_vsx_float64_vec_elements(FILE *stream,
|
||||
vsx_float64_vec_t vec)
|
||||
{
|
||||
fprintf(stream, "%.17g, %.17g", vec[0], vec[1]);
|
||||
}
|
||||
|
||||
static inline void print_vsx_int32_vec_elements(FILE *stream,
|
||||
vsx_int32_vec_t vec)
|
||||
{
|
||||
fprintf(stream, "%d, %d, %d, %d", vec[0], vec[1], vec[2], vec[3]);
|
||||
}
|
||||
|
||||
static inline void print_vsx_uint32_vec_elements(FILE *stream,
|
||||
vsx_uint32_vec_t vec)
|
||||
{
|
||||
fprintf(stream, "%u, %u, %u, %u", vec[0], vec[1], vec[2], vec[3]);
|
||||
}
|
||||
|
||||
static inline void print_vsx_int64_vec_elements(FILE *stream,
|
||||
vsx_int64_vec_t vec)
|
||||
{
|
||||
fprintf(stream, "%lld, %lld", vec[0], vec[1]);
|
||||
}
|
||||
|
||||
static inline void print_vsx_uint64_vec_elements(FILE *stream,
|
||||
vsx_uint64_vec_t vec)
|
||||
{
|
||||
fprintf(stream, "%llu, %llu", vec[0], vec[1]);
|
||||
}
|
||||
|
||||
#define DEFINE_VSX_ALL_EQ_FUNC(LANE_TYPE, CMP_INSN) \
|
||||
static inline int vsx_##LANE_TYPE##_all_eq(vsx_##LANE_TYPE##_vec_t a, \
|
||||
vsx_##LANE_TYPE##_vec_t b) \
|
||||
{ \
|
||||
unsigned result; \
|
||||
vsx_##LANE_TYPE##_vec_t is_eq_mask_vec; \
|
||||
asm(#CMP_INSN ". %0, %2, %3\n\t" \
|
||||
"mfocrf %1, 2" \
|
||||
: "=v" (is_eq_mask_vec), "=r" (result) \
|
||||
: "v" (a), "v" (b) \
|
||||
: "cr6"); \
|
||||
return (int)((result >> 7) & 1u); \
|
||||
}
|
||||
|
||||
DEFINE_VSX_ALL_EQ_FUNC(int32, vcmpequw)
|
||||
DEFINE_VSX_ALL_EQ_FUNC(uint32, vcmpequw)
|
||||
DEFINE_VSX_ALL_EQ_FUNC(int64, vcmpequd)
|
||||
DEFINE_VSX_ALL_EQ_FUNC(uint64, vcmpequd)
|
||||
|
||||
#define DEFINE_VSX_F2I_TEST_FUNC(SRC_T, DEST_T) \
|
||||
static inline int test_vsx_conv_##SRC_T##_vec_to_##DEST_T##_vec( \
|
||||
vsx_##SRC_T##_vec_t src_v) \
|
||||
{ \
|
||||
const vsx_##SRC_T##_vec_t is_nan_mask = vsx_##SRC_T##_is_nan(src_v); \
|
||||
const vsx_##SRC_T##_vec_t nan_src_v = \
|
||||
vsx_##SRC_T##_logical_and(src_v, is_nan_mask); \
|
||||
const vsx_##SRC_T##_vec_t non_nan_src_v = \
|
||||
vsx_##SRC_T##_logical_andc(src_v, is_nan_mask); \
|
||||
\
|
||||
const vsx_##DEST_T##_vec_t expected_result = \
|
||||
vsx_mask_out_##SRC_T##_vec_to_##DEST_T##_vec( \
|
||||
vsx_##DEST_T##_logical_or( \
|
||||
vsx_convert_##SRC_T##_vec_to_##DEST_T##_vec(nan_src_v), \
|
||||
vsx_convert_##SRC_T##_vec_to_##DEST_T##_vec( \
|
||||
non_nan_src_v))); \
|
||||
const vsx_##DEST_T##_vec_t actual_result = \
|
||||
vsx_mask_out_##SRC_T##_vec_to_##DEST_T##_vec( \
|
||||
vsx_convert_##SRC_T##_vec_to_##DEST_T##_vec(src_v)); \
|
||||
const int test_result = \
|
||||
vsx_##DEST_T##_all_eq(expected_result, actual_result); \
|
||||
\
|
||||
if (unlikely(test_result == 0)) { \
|
||||
fputs("FAIL: Conversion of " #SRC_T " vector to " #DEST_T \
|
||||
" vector failed\n", stdout); \
|
||||
fputs("Source values: ", stdout); \
|
||||
print_vsx_##SRC_T##_vec_elements(stdout, src_v); \
|
||||
fputs("\nExpected result: ", stdout); \
|
||||
print_vsx_##DEST_T##_vec_elements(stdout, expected_result); \
|
||||
fputs("\nActual result: ", stdout); \
|
||||
print_vsx_##DEST_T##_vec_elements(stdout, actual_result); \
|
||||
fputs("\n\n", stdout); \
|
||||
} \
|
||||
\
|
||||
return test_result; \
|
||||
}
|
||||
|
||||
|
||||
DEFINE_VSX_F2I_TEST_FUNC(float32, int32)
|
||||
DEFINE_VSX_F2I_TEST_FUNC(float32, uint32)
|
||||
DEFINE_VSX_F2I_TEST_FUNC(float32, int64)
|
||||
DEFINE_VSX_F2I_TEST_FUNC(float32, uint64)
|
||||
DEFINE_VSX_F2I_TEST_FUNC(float64, int32)
|
||||
DEFINE_VSX_F2I_TEST_FUNC(float64, uint32)
|
||||
DEFINE_VSX_F2I_TEST_FUNC(float64, int64)
|
||||
DEFINE_VSX_F2I_TEST_FUNC(float64, uint64)
|
||||
|
||||
static inline vsx_int32_vec_t vsx_int32_vec_from_mask(int mask)
|
||||
{
|
||||
const vsx_int32_vec_t bits_to_test = {1, 2, 4, 8};
|
||||
const vsx_int32_vec_t vec_mask = {mask, mask, mask, mask};
|
||||
vsx_int32_vec_t result;
|
||||
|
||||
asm("vcmpequw %0, %1, %2"
|
||||
: "=v" (result)
|
||||
: "v" (vsx_int32_logical_and(vec_mask, bits_to_test)),
|
||||
"v" (bits_to_test));
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline vsx_int64_vec_t vsx_int64_vec_from_mask(int mask)
|
||||
{
|
||||
const vsx_int64_vec_t bits_to_test = {1, 2};
|
||||
const vsx_int64_vec_t vec_mask = {mask, mask};
|
||||
vsx_int64_vec_t result;
|
||||
|
||||
asm("vcmpequd %0, %1, %2"
|
||||
: "=v" (result)
|
||||
: "v" (vsx_int64_logical_and(vec_mask, bits_to_test)),
|
||||
"v" (bits_to_test));
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const vsx_float32_vec_t f32_iota1 = {1.0f, 2.0f, 3.0f, 4.0f};
|
||||
const vsx_float64_vec_t f64_iota1 = {1.0, 2.0};
|
||||
|
||||
int num_of_tests_failed = 0;
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
const vsx_int32_vec_t nan_mask = vsx_int32_vec_from_mask(i);
|
||||
const vsx_float32_vec_t f32_v =
|
||||
vsx_float32_logical_or(f32_iota1, (vsx_float32_vec_t)nan_mask);
|
||||
num_of_tests_failed +=
|
||||
(int)(!test_vsx_conv_float32_vec_to_int32_vec(f32_v));
|
||||
num_of_tests_failed +=
|
||||
(int)(!test_vsx_conv_float32_vec_to_int64_vec(f32_v));
|
||||
num_of_tests_failed +=
|
||||
(int)(!test_vsx_conv_float32_vec_to_uint32_vec(f32_v));
|
||||
num_of_tests_failed +=
|
||||
(int)(!test_vsx_conv_float32_vec_to_uint64_vec(f32_v));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
const vsx_int64_vec_t nan_mask = vsx_int64_vec_from_mask(i);
|
||||
const vsx_float64_vec_t f64_v =
|
||||
vsx_float64_logical_or(f64_iota1, (vsx_float64_vec_t)nan_mask);
|
||||
num_of_tests_failed +=
|
||||
(int)(!test_vsx_conv_float64_vec_to_int32_vec(f64_v));
|
||||
num_of_tests_failed +=
|
||||
(int)(!test_vsx_conv_float64_vec_to_int64_vec(f64_v));
|
||||
num_of_tests_failed +=
|
||||
(int)(!test_vsx_conv_float64_vec_to_uint32_vec(f64_v));
|
||||
num_of_tests_failed +=
|
||||
(int)(!test_vsx_conv_float64_vec_to_uint64_vec(f64_v));
|
||||
}
|
||||
|
||||
printf("%d tests failed\n", num_of_tests_failed);
|
||||
return (int)(num_of_tests_failed != 0);
|
||||
}
|
Loading…
Reference in New Issue
Block a user