ppc patch queue for 2022-09-20:

This queue contains a implementation of PowerISA 3.1B hash insns, ppc
 TCG insns cleanups and fixes, and miscellaneus fixes in the spapr and
 pnv_phb models.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQQX6/+ZI9AYAK8oOBk82cqW3gMxZAUCYyoWlAAKCRA82cqW3gMx
 ZDYhAP0eQMeA4NS3hiw7WMcAVg0pei3ZJL9oEh1UE3+MfK7MhQEA0q8qExWnQJAA
 a0hfnFH9pLjI+v0f/FbFK6QJBpu/bg8=
 =qT+H
 -----END PGP SIGNATURE-----

Merge tag 'pull-ppc-20220920' of https://gitlab.com/danielhb/qemu into staging

ppc patch queue for 2022-09-20:

This queue contains a implementation of PowerISA 3.1B hash insns, ppc
TCG insns cleanups and fixes, and miscellaneus fixes in the spapr and
pnv_phb models.

# -----BEGIN PGP SIGNATURE-----
#
# iHUEABYKAB0WIQQX6/+ZI9AYAK8oOBk82cqW3gMxZAUCYyoWlAAKCRA82cqW3gMx
# ZDYhAP0eQMeA4NS3hiw7WMcAVg0pei3ZJL9oEh1UE3+MfK7MhQEA0q8qExWnQJAA
# a0hfnFH9pLjI+v0f/FbFK6QJBpu/bg8=
# =qT+H
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 20 Sep 2022 15:37:56 EDT
# gpg:                using EDDSA key 17EBFF9923D01800AF2838193CD9CA96DE033164
# gpg: Good signature from "Daniel Henrique Barboza <danielhb413@gmail.com>" [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: 17EB FF99 23D0 1800 AF28  3819 3CD9 CA96 DE03 3164

* tag 'pull-ppc-20220920' of https://gitlab.com/danielhb/qemu:
  hw/ppc/spapr: Fix code style problems reported by checkpatch
  hw/pci-host: pnv_phb{3, 4}: Fix heap out-of-bound access failure
  hw/ppc: spapr: Use qemu_vfree() to free spapr->htab
  target/ppc: Clear fpstatus flags on helpers missing it
  target/ppc: Zero second doubleword of VSR registers for FPR insns
  target/ppc: Set OV32 when OV is set
  target/ppc: Zero second doubleword for VSX madd instructions
  target/ppc: Set result to QNaN for DENBCD when VXCVI occurs
  target/ppc: Zero second doubleword in DFP instructions
  target/ppc: Remove unused xer_* macros
  target/ppc: Remove extra space from s128 field in ppc_vsr_t
  target/ppc: Merge fsqrt and fsqrts helpers
  target/ppc: Move fsqrts to decodetree
  target/ppc: Move fsqrt to decodetree
  target/ppc: Implement hashstp and hashchkp
  target/ppc: Implement hashst and hashchk
  target/ppc: Add HASHKEYR and HASHPKEYR SPRs

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2022-09-21 13:11:57 -04:00
commit 6514f1a522
16 changed files with 278 additions and 84 deletions

View File

@ -1169,6 +1169,7 @@ static void pnv_phb3_root_bus_class_init(ObjectClass *klass, void *data)
static const TypeInfo pnv_phb3_root_bus_info = {
.name = TYPE_PNV_PHB3_ROOT_BUS,
.parent = TYPE_PCIE_BUS,
.instance_size = sizeof(PnvPHB3RootBus),
.class_init = pnv_phb3_root_bus_class_init,
};

View File

@ -1773,6 +1773,7 @@ static void pnv_phb4_root_bus_class_init(ObjectClass *klass, void *data)
static const TypeInfo pnv_phb4_root_bus_info = {
.name = TYPE_PNV_PHB4_ROOT_BUS,
.parent = TYPE_PCIE_BUS,
.instance_size = sizeof(PnvPHB4RootBus),
.class_init = pnv_phb4_root_bus_class_init,
};

View File

@ -1522,7 +1522,7 @@ int spapr_hpt_shift_for_ramsize(uint64_t ramsize)
void spapr_free_hpt(SpaprMachineState *spapr)
{
g_free(spapr->htab);
qemu_vfree(spapr->htab);
spapr->htab = NULL;
spapr->htab_shift = 0;
close_htab_fd(spapr);

View File

@ -848,7 +848,8 @@ static inline uint64_t ppc64_phys_to_real(uint64_t addr)
static inline uint32_t rtas_ld(target_ulong phys, int n)
{
return ldl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4*n));
return ldl_be_phys(&address_space_memory,
ppc64_phys_to_real(phys + 4 * n));
}
static inline uint64_t rtas_ldq(target_ulong phys, int n)
@ -858,7 +859,7 @@ static inline uint64_t rtas_ldq(target_ulong phys, int n)
static inline void rtas_st(target_ulong phys, int n, uint32_t val)
{
stl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4*n), val);
stl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4 * n), val);
}
typedef void (*spapr_rtas_fn)(PowerPCCPU *cpu, SpaprMachineState *sm,

View File

@ -246,7 +246,7 @@ typedef union _ppc_vsr_t {
#ifdef CONFIG_INT128
__uint128_t u128;
#endif
Int128 s128;
Int128 s128;
} ppc_vsr_t;
typedef ppc_vsr_t ppc_avr_t;
@ -1506,10 +1506,6 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define XER_CMP 8
#define XER_BC 0
#define xer_so (env->so)
#define xer_ov (env->ov)
#define xer_ca (env->ca)
#define xer_ov32 (env->ov)
#define xer_ca32 (env->ca)
#define xer_cmp ((env->xer >> XER_CMP) & 0xFF)
#define xer_bc ((env->xer >> XER_BC) & 0x7F)
@ -1676,6 +1672,8 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_BOOKE_GIVOR14 (0x1BD)
#define SPR_TIR (0x1BE)
#define SPR_PTCR (0x1D0)
#define SPR_HASHKEYR (0x1D4)
#define SPR_HASHPKEYR (0x1D5)
#define SPR_BOOKE_SPEFSCR (0x200)
#define SPR_Exxx_BBEAR (0x201)
#define SPR_Exxx_BBTAR (0x202)

View File

@ -5700,6 +5700,33 @@ static void register_power9_mmu_sprs(CPUPPCState *env)
#endif
}
static void register_power10_hash_sprs(CPUPPCState *env)
{
/*
* it's the OS responsability to generate a random value for the registers
* in each process' context. So, initialize it with 0 here.
*/
uint64_t hashkeyr_initial_value = 0, hashpkeyr_initial_value = 0;
#if defined(CONFIG_USER_ONLY)
/* in linux-user, setup the hash register with a random value */
GRand *rand = g_rand_new();
hashkeyr_initial_value =
((uint64_t)g_rand_int(rand) << 32) | (uint64_t)g_rand_int(rand);
hashpkeyr_initial_value =
((uint64_t)g_rand_int(rand) << 32) | (uint64_t)g_rand_int(rand);
g_rand_free(rand);
#endif
spr_register(env, SPR_HASHKEYR, "HASHKEYR",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
hashkeyr_initial_value);
spr_register_hv(env, SPR_HASHPKEYR, "HASHPKEYR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
hashpkeyr_initial_value);
}
/*
* Initialize PMU counter overflow timers for Power8 and
* newer Power chips when using TCG.
@ -6518,6 +6545,7 @@ static void init_proc_POWER10(CPUPPCState *env)
register_power8_book4_sprs(env);
register_power8_rpr_sprs(env);
register_power9_mmu_sprs(env);
register_power10_hash_sprs(env);
/* FIXME: Filter fields properly based on privilege level */
spr_register_kvm_hv(env, SPR_PSSCR, "PSSCR", NULL, NULL, NULL, NULL,

View File

@ -42,13 +42,16 @@ static void get_dfp128(ppc_vsr_t *dst, ppc_fprp_t *dfp)
static void set_dfp64(ppc_fprp_t *dfp, ppc_vsr_t *src)
{
dfp->VsrD(0) = src->VsrD(1);
dfp[0].VsrD(0) = src->VsrD(1);
dfp[0].VsrD(1) = 0ULL;
}
static void set_dfp128(ppc_fprp_t *dfp, ppc_vsr_t *src)
{
dfp[0].VsrD(0) = src->VsrD(0);
dfp[1].VsrD(0) = src->VsrD(1);
dfp[0].VsrD(1) = 0ULL;
dfp[1].VsrD(1) = 0ULL;
}
static void set_dfp128_to_avr(ppc_avr_t *dst, ppc_vsr_t *src)
@ -1144,6 +1147,26 @@ static inline uint8_t dfp_get_bcd_digit_128(ppc_vsr_t *t, unsigned n)
return t->VsrD((n & 0x10) ? 0 : 1) >> ((n << 2) & 63) & 15;
}
static inline void dfp_invalid_op_vxcvi_64(struct PPC_DFP *dfp)
{
/* TODO: fpscr is incorrectly not being saved to env */
dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FPSCR_VE);
if ((dfp->env->fpscr & FP_VE) == 0) {
dfp->vt.VsrD(1) = 0x7c00000000000000; /* QNaN */
}
}
static inline void dfp_invalid_op_vxcvi_128(struct PPC_DFP *dfp)
{
/* TODO: fpscr is incorrectly not being saved to env */
dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FPSCR_VE);
if ((dfp->env->fpscr & FP_VE) == 0) {
dfp->vt.VsrD(0) = 0x7c00000000000000; /* QNaN */
dfp->vt.VsrD(1) = 0x0;
}
}
#define DFP_HELPER_ENBCD(op, size) \
void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b, \
uint32_t s) \
@ -1170,7 +1193,8 @@ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b, \
sgn = 0; \
break; \
default: \
dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE); \
dfp_invalid_op_vxcvi_##size(&dfp); \
set_dfp##size(t, &dfp.vt); \
return; \
} \
} \
@ -1180,7 +1204,8 @@ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b, \
digits[(size) / 4 - n] = dfp_get_bcd_digit_##size(&dfp.vb, \
offset++); \
if (digits[(size) / 4 - n] > 10) { \
dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE); \
dfp_invalid_op_vxcvi_##size(&dfp); \
set_dfp##size(t, &dfp.vt); \
return; \
} else { \
nonzero |= (digits[(size) / 4 - n] > 0); \

View File

@ -2173,6 +2173,89 @@ void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
#endif
#endif
static uint32_t helper_SIMON_LIKE_32_64(uint32_t x, uint64_t key, uint32_t lane)
{
const uint16_t c = 0xfffc;
const uint64_t z0 = 0xfa2561cdf44ac398ULL;
uint16_t z = 0, temp;
uint16_t k[32], eff_k[32], xleft[33], xright[33], fxleft[32];
for (int i = 3; i >= 0; i--) {
k[i] = key & 0xffff;
key >>= 16;
}
xleft[0] = x & 0xffff;
xright[0] = (x >> 16) & 0xffff;
for (int i = 0; i < 28; i++) {
z = (z0 >> (63 - i)) & 1;
temp = ror16(k[i + 3], 3) ^ k[i + 1];
k[i + 4] = c ^ z ^ k[i] ^ temp ^ ror16(temp, 1);
}
for (int i = 0; i < 8; i++) {
eff_k[4 * i + 0] = k[4 * i + ((0 + lane) % 4)];
eff_k[4 * i + 1] = k[4 * i + ((1 + lane) % 4)];
eff_k[4 * i + 2] = k[4 * i + ((2 + lane) % 4)];
eff_k[4 * i + 3] = k[4 * i + ((3 + lane) % 4)];
}
for (int i = 0; i < 32; i++) {
fxleft[i] = (rol16(xleft[i], 1) &
rol16(xleft[i], 8)) ^ rol16(xleft[i], 2);
xleft[i + 1] = xright[i] ^ fxleft[i] ^ eff_k[i];
xright[i + 1] = xleft[i];
}
return (((uint32_t)xright[32]) << 16) | xleft[32];
}
static uint64_t hash_digest(uint64_t ra, uint64_t rb, uint64_t key)
{
uint64_t stage0_h = 0ULL, stage0_l = 0ULL;
uint64_t stage1_h, stage1_l;
for (int i = 0; i < 4; i++) {
stage0_h |= ror64(rb & 0xff, 8 * (2 * i + 1));
stage0_h |= ((ra >> 32) & 0xff) << (8 * 2 * i);
stage0_l |= ror64((rb >> 32) & 0xff, 8 * (2 * i + 1));
stage0_l |= (ra & 0xff) << (8 * 2 * i);
rb >>= 8;
ra >>= 8;
}
stage1_h = (uint64_t)helper_SIMON_LIKE_32_64(stage0_h >> 32, key, 0) << 32;
stage1_h |= helper_SIMON_LIKE_32_64(stage0_h, key, 1);
stage1_l = (uint64_t)helper_SIMON_LIKE_32_64(stage0_l >> 32, key, 2) << 32;
stage1_l |= helper_SIMON_LIKE_32_64(stage0_l, key, 3);
return stage1_h ^ stage1_l;
}
#include "qemu/guest-random.h"
#define HELPER_HASH(op, key, store) \
void helper_##op(CPUPPCState *env, target_ulong ea, target_ulong ra, \
target_ulong rb) \
{ \
uint64_t calculated_hash = hash_digest(ra, rb, key), loaded_hash; \
\
if (store) { \
cpu_stq_data_ra(env, ea, calculated_hash, GETPC()); \
} else { \
loaded_hash = cpu_ldq_data_ra(env, ea, GETPC()); \
if (loaded_hash != calculated_hash) { \
raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, \
POWERPC_EXCP_TRAP, GETPC()); \
} \
} \
}
HELPER_HASH(HASHST, env->spr[SPR_HASHKEYR], true)
HELPER_HASH(HASHCHK, env->spr[SPR_HASHKEYR], false)
HELPER_HASH(HASHSTP, env->spr[SPR_HASHPKEYR], true)
HELPER_HASH(HASHCHKP, env->spr[SPR_HASHPKEYR], false)
#if !defined(CONFIG_USER_ONLY)
#ifdef CONFIG_TCG

View File

@ -830,30 +830,21 @@ static void float_invalid_op_sqrt(CPUPPCState *env, int flags,
}
}
/* fsqrt - fsqrt. */
float64 helper_fsqrt(CPUPPCState *env, float64 arg)
{
float64 ret = float64_sqrt(arg, &env->fp_status);
int flags = get_float_exception_flags(&env->fp_status);
if (unlikely(flags & float_flag_invalid)) {
float_invalid_op_sqrt(env, flags, 1, GETPC());
}
return ret;
#define FPU_FSQRT(name, op) \
float64 helper_##name(CPUPPCState *env, float64 arg) \
{ \
float64 ret = op(arg, &env->fp_status); \
int flags = get_float_exception_flags(&env->fp_status); \
\
if (unlikely(flags & float_flag_invalid)) { \
float_invalid_op_sqrt(env, flags, 1, GETPC()); \
} \
\
return ret; \
}
/* fsqrts - fsqrts. */
float64 helper_fsqrts(CPUPPCState *env, float64 arg)
{
float64 ret = float64r32_sqrt(arg, &env->fp_status);
int flags = get_float_exception_flags(&env->fp_status);
if (unlikely(flags & float_flag_invalid)) {
float_invalid_op_sqrt(env, flags, 1, GETPC());
}
return ret;
}
FPU_FSQRT(FSQRT, float64_sqrt)
FPU_FSQRT(FSQRTS, float64r32_sqrt)
/* fre - fre. */
float64 helper_fre(CPUPPCState *env, float64 arg)
@ -2176,7 +2167,7 @@ VSX_TSQRT(xvtsqrtsp, 4, float32, VsrW(i), -126, 23)
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \
ppc_vsr_t *s1, ppc_vsr_t *s2, ppc_vsr_t *s3) \
{ \
ppc_vsr_t t = *xt; \
ppc_vsr_t t = { }; \
int i; \
\
helper_reset_fpstatus(env); \
@ -2637,6 +2628,8 @@ uint32_t helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \
int all_true = 1; \
int all_false = 1; \
\
helper_reset_fpstatus(env); \
\
for (i = 0; i < nels; i++) { \
if (unlikely(tp##_is_any_nan(xa->fld) || \
tp##_is_any_nan(xb->fld))) { \
@ -2690,6 +2683,8 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
ppc_vsr_t t = { }; \
int i; \
\
helper_reset_fpstatus(env); \
\
for (i = 0; i < nels; i++) { \
t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status); \
if (unlikely(stp##_is_signaling_nan(xb->sfld, \
@ -2715,6 +2710,8 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
ppc_vsr_t t = { }; \
int i; \
\
helper_reset_fpstatus(env); \
\
for (i = 0; i < nels; i++) { \
t.VsrW(2 * i) = stp##_to_##ttp(xb->VsrD(i), &env->fp_status); \
if (unlikely(stp##_is_signaling_nan(xb->VsrD(i), \
@ -2752,6 +2749,8 @@ void helper_##op(CPUPPCState *env, uint32_t opcode, \
ppc_vsr_t t = *xt; \
int i; \
\
helper_reset_fpstatus(env); \
\
for (i = 0; i < nels; i++) { \
t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status); \
if (unlikely(stp##_is_signaling_nan(xb->sfld, \
@ -2787,6 +2786,8 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
ppc_vsr_t t = { }; \
int i; \
\
helper_reset_fpstatus(env); \
\
for (i = 0; i < nels; i++) { \
t.tfld = stp##_to_##ttp(xb->sfld, 1, &env->fp_status); \
if (unlikely(stp##_is_signaling_nan(xb->sfld, \
@ -2834,6 +2835,8 @@ void helper_XSCVQPDP(CPUPPCState *env, uint32_t ro, ppc_vsr_t *xt,
ppc_vsr_t t = { };
float_status tstat;
helper_reset_fpstatus(env);
tstat = env->fp_status;
if (ro != 0) {
tstat.float_rounding_mode = float_round_to_odd;
@ -2855,6 +2858,7 @@ uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb)
{
uint64_t result, sign, exp, frac;
helper_reset_fpstatus(env);
float_status tstat = env->fp_status;
set_float_exception_flags(0, &tstat);
@ -2910,22 +2914,20 @@ 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 = env->fp_status.float_exception_flags, flags; \
ppc_vsr_t t = { }; \
int i; \
int i, flags; \
\
helper_reset_fpstatus(env); \
\
for (i = 0; i < nels; i++) { \
env->fp_status.float_exception_flags = 0; \
t.tfld = stp##_to_##ttp##_round_to_zero(xb->sfld, &env->fp_status); \
flags = env->fp_status.float_exception_flags; \
if (unlikely(flags & float_flag_invalid)) { \
t.tfld = float_invalid_cvt(env, flags, t.tfld, rnan, 0, GETPC());\
} \
all_flags |= flags; \
} \
\
*xt = t; \
env->fp_status.float_exception_flags = all_flags; \
do_float_check_status(env, sfi, GETPC()); \
}
@ -2977,12 +2979,12 @@ 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 = env->fp_status.float_exception_flags, flags; \
ppc_vsr_t t = { }; \
int i; \
int i, flags; \
\
helper_reset_fpstatus(env); \
\
for (i = 0; i < nels; i++) { \
env->fp_status.float_exception_flags = 0; \
t.VsrW(2 * i) = stp##_to_##ttp##_round_to_zero(xb->VsrD(i), \
&env->fp_status); \
flags = env->fp_status.float_exception_flags; \
@ -2991,11 +2993,9 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
rnan, 0, GETPC()); \
} \
t.VsrW(2 * i + 1) = t.VsrW(2 * i); \
all_flags |= flags; \
} \
\
*xt = t; \
env->fp_status.float_exception_flags = all_flags; \
do_float_check_status(env, sfi, GETPC()); \
}
@ -3020,6 +3020,8 @@ void helper_##op(CPUPPCState *env, uint32_t opcode, \
ppc_vsr_t t = { }; \
int flags; \
\
helper_reset_fpstatus(env); \
\
t.tfld = stp##_to_##ttp##_round_to_zero(xb->sfld, &env->fp_status); \
flags = get_float_exception_flags(&env->fp_status); \
if (flags & float_flag_invalid) { \
@ -3032,7 +3034,6 @@ void helper_##op(CPUPPCState *env, uint32_t opcode, \
VSX_CVT_FP_TO_INT_VECTOR(xscvqpsdz, float128, int64, f128, VsrD(0), \
0x8000000000000000ULL)
VSX_CVT_FP_TO_INT_VECTOR(xscvqpswz, float128, int32, f128, VsrD(0), \
0xffffffff80000000ULL)
VSX_CVT_FP_TO_INT_VECTOR(xscvqpudz, float128, uint64, f128, VsrD(0), 0x0ULL)
@ -3055,6 +3056,8 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
ppc_vsr_t t = { }; \
int i; \
\
helper_reset_fpstatus(env); \
\
for (i = 0; i < nels; i++) { \
t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status); \
if (r2sp) { \
@ -3124,6 +3127,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode, \
{ \
ppc_vsr_t t = *xt; \
\
helper_reset_fpstatus(env); \
t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status); \
helper_compute_fprf_##ttp(env, t.tfld); \
\
@ -3157,6 +3161,8 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
int i; \
FloatRoundMode curr_rounding_mode; \
\
helper_reset_fpstatus(env); \
\
if (rmode != FLOAT_ROUND_CURRENT) { \
curr_rounding_mode = get_float_rounding_mode(&env->fp_status); \
set_float_rounding_mode(rmode, &env->fp_status); \

View File

@ -4,6 +4,10 @@ DEF_HELPER_FLAGS_4(tw, TCG_CALL_NO_WG, void, env, tl, tl, i32)
#if defined(TARGET_PPC64)
DEF_HELPER_FLAGS_4(td, TCG_CALL_NO_WG, void, env, tl, tl, i32)
#endif
DEF_HELPER_4(HASHST, void, env, tl, tl, tl)
DEF_HELPER_4(HASHCHK, void, env, tl, tl, tl)
DEF_HELPER_4(HASHSTP, void, env, tl, tl, tl)
DEF_HELPER_4(HASHCHKP, void, env, tl, tl, tl)
#if !defined(CONFIG_USER_ONLY)
DEF_HELPER_2(store_msr, void, env, tl)
DEF_HELPER_1(rfi, void, env)
@ -116,8 +120,8 @@ DEF_HELPER_4(fmadds, i64, env, i64, i64, i64)
DEF_HELPER_4(fmsubs, i64, env, i64, i64, i64)
DEF_HELPER_4(fnmadds, i64, env, i64, i64, i64)
DEF_HELPER_4(fnmsubs, i64, env, i64, i64, i64)
DEF_HELPER_2(fsqrt, f64, env, f64)
DEF_HELPER_2(fsqrts, f64, env, f64)
DEF_HELPER_2(FSQRT, f64, env, f64)
DEF_HELPER_2(FSQRTS, f64, env, f64)
DEF_HELPER_2(fre, i64, env, i64)
DEF_HELPER_2(fres, i64, env, i64)
DEF_HELPER_2(frsqrte, i64, env, i64)

View File

@ -20,6 +20,9 @@
&A frt fra frb frc rc:bool
@A ...... frt:5 fra:5 frb:5 frc:5 ..... rc:1 &A
&A_tb frt frb rc:bool
@A_tb ...... frt:5 ..... frb:5 ..... ..... rc:1 &A_tb
&D rt ra si:int64_t
@D ...... rt:5 ra:5 si:s16 &D
@ -172,6 +175,9 @@
@X_TSX ...... ..... ra:5 rb:5 .......... . &X rt=%x_rt_tsx
@X_TSXP ...... ..... ra:5 rb:5 .......... . &X rt=%rt_tsxp
%x_dw 0:1 21:5 !function=dw_compose_ea
@X_DW ...... ..... ra:5 rb:5 .......... . &X rt=%x_dw
&X_frtp_vrb frtp vrb
@X_frtp_vrb ...... ....0 ..... vrb:5 .......... . &X_frtp_vrb frtp=%x_frtp
@ -323,6 +329,13 @@ CNTTZDM 011111 ..... ..... ..... 1000111011 - @X
PDEPD 011111 ..... ..... ..... 0010011100 - @X
PEXTD 011111 ..... ..... ..... 0010111100 - @X
# Fixed-Point Hash Instructions
HASHST 011111 ..... ..... ..... 1011010010 . @X_DW
HASHCHK 011111 ..... ..... ..... 1011110010 . @X_DW
HASHSTP 011111 ..... ..... ..... 1010010010 . @X_DW
HASHCHKP 011111 ..... ..... ..... 1010110010 . @X_DW
## BCD Assist
ADDG6S 011111 ..... ..... ..... - 001001010 - @X
@ -353,6 +366,11 @@ STFDU 110111 ..... ...... ............... @D
STFDX 011111 ..... ...... .... 1011010111 - @X
STFDUX 011111 ..... ...... .... 1011110111 - @X
### Floating-Point Arithmetic Instructions
FSQRT 111111 ..... ----- ..... ----- 10110 . @A_tb
FSQRTS 111011 ..... ----- ..... ----- 10110 . @A_tb
### Floating-Point Select Instruction
FSEL 111111 ..... ..... ..... ..... 10111 . @A

View File

@ -37,9 +37,9 @@
static inline void helper_update_ov_legacy(CPUPPCState *env, int ov)
{
if (unlikely(ov)) {
env->so = env->ov = 1;
env->so = env->ov = env->ov32 = 1;
} else {
env->ov = 0;
env->ov = env->ov32 = 0;
}
}

View File

@ -6443,6 +6443,14 @@ static inline void get_fpr(TCGv_i64 dst, int regno)
static inline void set_fpr(int regno, TCGv_i64 src)
{
tcg_gen_st_i64(src, cpu_env, fpr_offset(regno));
/*
* Before PowerISA v3.1 the result of doubleword 1 of the VSR
* corresponding to the target FPR was undefined. However,
* most (if not all) real hardware were setting the result to 0.
* Starting at ISA v3.1, the result for doubleword 1 is now defined
* to be 0.
*/
tcg_gen_st_i64(tcg_constant_i64(0), cpu_env, vsr64_offset(regno, false));
}
static inline void get_avr64(TCGv_i64 dst, int regno, bool high)
@ -6473,6 +6481,11 @@ static int times_16(DisasContext *ctx, int x)
return x * 16;
}
static int64_t dw_compose_ea(DisasContext *ctx, int x)
{
return deposit64(0xfffffffffffffe00, 3, 6, x);
}
/*
* Helpers for trans_* functions to check for specific insns flags.
* Use token pasting to ensure that we use the proper flag with the

View File

@ -540,3 +540,37 @@ static bool trans_CBCDTD(DisasContext *ctx, arg_X_sa *a)
gen_helper_CBCDTD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
return true;
}
static bool do_hash(DisasContext *ctx, arg_X *a, bool priv,
void (*helper)(TCGv_ptr, TCGv, TCGv, TCGv))
{
TCGv ea;
if (!(ctx->insns_flags2 & PPC2_ISA310)) {
/* if version is before v3.1, this operation is a nop */
return true;
}
if (priv) {
/* if instruction is privileged but the context is in user space */
REQUIRE_SV(ctx);
}
if (unlikely(a->ra == 0)) {
/* if RA=0, the instruction form is invalid */
gen_invalid(ctx);
return true;
}
ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->rt));
helper(cpu_env, ea, cpu_gpr[a->ra], cpu_gpr[a->rb]);
tcg_temp_free(ea);
return true;
}
TRANS(HASHST, do_hash, false, gen_helper_HASHST)
TRANS(HASHCHK, do_hash, false, gen_helper_HASHCHK)
TRANS(HASHSTP, do_hash, true, gen_helper_HASHSTP)
TRANS(HASHCHKP, do_hash, true, gen_helper_HASHCHKP)

View File

@ -254,50 +254,34 @@ static bool trans_FSEL(DisasContext *ctx, arg_A *a)
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
/* Optional: */
/* fsqrt */
static void gen_fsqrt(DisasContext *ctx)
static bool do_helper_fsqrt(DisasContext *ctx, arg_A_tb *a,
void (*helper)(TCGv_i64, TCGv_ptr, TCGv_i64))
{
TCGv_i64 t0;
TCGv_i64 t1;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
TCGv_i64 t0, t1;
REQUIRE_INSNS_FLAGS(ctx, FLOAT_FSQRT);
REQUIRE_FPU(ctx);
t0 = tcg_temp_new_i64();
t1 = tcg_temp_new_i64();
gen_reset_fpstatus();
get_fpr(t0, rB(ctx->opcode));
gen_helper_fsqrt(t1, cpu_env, t0);
set_fpr(rD(ctx->opcode), t1);
get_fpr(t0, a->frb);
helper(t1, cpu_env, t0);
set_fpr(a->frt, t1);
gen_compute_fprf_float64(t1);
if (unlikely(Rc(ctx->opcode) != 0)) {
if (unlikely(a->rc != 0)) {
gen_set_cr1_from_fpscr(ctx);
}
tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1);
return true;
}
static void gen_fsqrts(DisasContext *ctx)
{
TCGv_i64 t0;
TCGv_i64 t1;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
}
t0 = tcg_temp_new_i64();
t1 = tcg_temp_new_i64();
gen_reset_fpstatus();
get_fpr(t0, rB(ctx->opcode));
gen_helper_fsqrts(t1, cpu_env, t0);
set_fpr(rD(ctx->opcode), t1);
gen_compute_fprf_float64(t1);
if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_cr1_from_fpscr(ctx);
}
tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1);
}
TRANS(FSQRT, do_helper_fsqrt, gen_helper_FSQRT);
TRANS(FSQRTS, do_helper_fsqrt, gen_helper_FSQRTS);
/*** Floating-Point multiply-and-add ***/
/* fmadd - fmadds */

View File

@ -62,8 +62,6 @@ GEN_HANDLER_E(stfdepx, 0x1F, 0x1F, 0x16, 0x00000001, PPC_NONE, PPC2_BOOKE206),
GEN_HANDLER_E(stfdpx, 0x1F, 0x17, 0x1C, 0x00200001, PPC_NONE, PPC2_ISA205),
GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES),
GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT),
GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT),
GEN_HANDLER(fabs, 0x3F, 0x08, 0x08, 0x001F0000, PPC_FLOAT),