mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 15:53:54 -06:00
target/ppc: Implemented xvf*ger*
Implement the following PowerISA v3.1 instructions: xvf32ger: VSX Vector 32-bit Floating-Point GER (rank-1 update) xvf32gernn: VSX Vector 32-bit Floating-Point GER (rank-1 update) Negative multiply, Negative accumulate xvf32gernp: VSX Vector 32-bit Floating-Point GER (rank-1 update) Negative multiply, Positive accumulate xvf32gerpn: VSX Vector 32-bit Floating-Point GER (rank-1 update) Positive multiply, Negative accumulate xvf32gerpp: VSX Vector 32-bit Floating-Point GER (rank-1 update) Positive multiply, Positive accumulate xvf64ger: VSX Vector 64-bit Floating-Point GER (rank-1 update) xvf64gernn: VSX Vector 64-bit Floating-Point GER (rank-1 update) Negative multiply, Negative accumulate xvf64gernp: VSX Vector 64-bit Floating-Point GER (rank-1 update) Negative multiply, Positive accumulate xvf64gerpn: VSX Vector 64-bit Floating-Point GER (rank-1 update) Positive multiply, Negative accumulate xvf64gerpp: VSX Vector 64-bit Floating-Point GER (rank-1 update) Positive multiply, Positive accumulate Signed-off-by: Lucas Mateus Castro (alqotel) <lucas.araujo@eldorado.org.br> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20220524140537.27451-5-lucas.araujo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
This commit is contained in:
parent
6d525ca972
commit
c29018cc73
5 changed files with 231 additions and 2 deletions
|
@ -414,7 +414,7 @@ void helper_store_fpscr(CPUPPCState *env, uint64_t val, uint32_t nibbles)
|
|||
ppc_store_fpscr(env, val);
|
||||
}
|
||||
|
||||
void helper_fpscr_check_status(CPUPPCState *env)
|
||||
static void do_fpscr_check_status(CPUPPCState *env, uintptr_t raddr)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
target_ulong fpscr = env->fpscr;
|
||||
|
@ -455,13 +455,19 @@ void helper_fpscr_check_status(CPUPPCState *env)
|
|||
}
|
||||
cs->exception_index = POWERPC_EXCP_PROGRAM;
|
||||
env->error_code = error | POWERPC_EXCP_FP;
|
||||
env->fpscr |= error ? FP_FEX : 0;
|
||||
/* Deferred floating-point exception after target FPSCR update */
|
||||
if (fp_exceptions_enabled(env)) {
|
||||
raise_exception_err_ra(env, cs->exception_index,
|
||||
env->error_code, GETPC());
|
||||
env->error_code, raddr);
|
||||
}
|
||||
}
|
||||
|
||||
void helper_fpscr_check_status(CPUPPCState *env)
|
||||
{
|
||||
do_fpscr_check_status(env, GETPC());
|
||||
}
|
||||
|
||||
static void do_float_check_status(CPUPPCState *env, bool change_fi,
|
||||
uintptr_t raddr)
|
||||
{
|
||||
|
@ -3468,3 +3474,187 @@ void helper_xssubqp(CPUPPCState *env, uint32_t opcode,
|
|||
*xt = t;
|
||||
do_float_check_status(env, true, GETPC());
|
||||
}
|
||||
|
||||
static inline void vsxger_excp(CPUPPCState *env, uintptr_t retaddr)
|
||||
{
|
||||
/*
|
||||
* XV*GER instructions execute and set the FPSCR as if exceptions
|
||||
* are disabled and only at the end throw an exception
|
||||
*/
|
||||
target_ulong enable;
|
||||
enable = env->fpscr & (FP_ENABLES | FP_FI | FP_FR);
|
||||
env->fpscr &= ~(FP_ENABLES | FP_FI | FP_FR);
|
||||
int status = get_float_exception_flags(&env->fp_status);
|
||||
if (unlikely(status & float_flag_invalid)) {
|
||||
if (status & float_flag_invalid_snan) {
|
||||
float_invalid_op_vxsnan(env, 0);
|
||||
}
|
||||
if (status & float_flag_invalid_imz) {
|
||||
float_invalid_op_vximz(env, false, 0);
|
||||
}
|
||||
if (status & float_flag_invalid_isi) {
|
||||
float_invalid_op_vxisi(env, false, 0);
|
||||
}
|
||||
}
|
||||
do_float_check_status(env, false, retaddr);
|
||||
env->fpscr |= enable;
|
||||
do_fpscr_check_status(env, retaddr);
|
||||
}
|
||||
|
||||
typedef void vsxger_zero(ppc_vsr_t *at, int, int);
|
||||
|
||||
typedef void vsxger_muladd_f(ppc_vsr_t *, ppc_vsr_t *, ppc_vsr_t *, int, int,
|
||||
int flags, float_status *s);
|
||||
|
||||
static void vsxger_muladd32(ppc_vsr_t *at, ppc_vsr_t *a, ppc_vsr_t *b, int i,
|
||||
int j, int flags, float_status *s)
|
||||
{
|
||||
at[i].VsrSF(j) = float32_muladd(a->VsrSF(i), b->VsrSF(j),
|
||||
at[i].VsrSF(j), flags, s);
|
||||
}
|
||||
|
||||
static void vsxger_mul32(ppc_vsr_t *at, ppc_vsr_t *a, ppc_vsr_t *b, int i,
|
||||
int j, int flags, float_status *s)
|
||||
{
|
||||
at[i].VsrSF(j) = float32_mul(a->VsrSF(i), b->VsrSF(j), s);
|
||||
}
|
||||
|
||||
static void vsxger_zero32(ppc_vsr_t *at, int i, int j)
|
||||
{
|
||||
at[i].VsrSF(j) = float32_zero;
|
||||
}
|
||||
|
||||
static void vsxger_muladd64(ppc_vsr_t *at, ppc_vsr_t *a, ppc_vsr_t *b, int i,
|
||||
int j, int flags, float_status *s)
|
||||
{
|
||||
if (j >= 2) {
|
||||
j -= 2;
|
||||
at[i].VsrDF(j) = float64_muladd(a[i / 2].VsrDF(i % 2), b->VsrDF(j),
|
||||
at[i].VsrDF(j), flags, s);
|
||||
}
|
||||
}
|
||||
|
||||
static void vsxger_mul64(ppc_vsr_t *at, ppc_vsr_t *a, ppc_vsr_t *b, int i,
|
||||
int j, int flags, float_status *s)
|
||||
{
|
||||
if (j >= 2) {
|
||||
j -= 2;
|
||||
at[i].VsrDF(j) = float64_mul(a[i / 2].VsrDF(i % 2), b->VsrDF(j), s);
|
||||
}
|
||||
}
|
||||
|
||||
static void vsxger_zero64(ppc_vsr_t *at, int i, int j)
|
||||
{
|
||||
if (j >= 2) {
|
||||
j -= 2;
|
||||
at[i].VsrDF(j) = float64_zero;
|
||||
}
|
||||
}
|
||||
|
||||
static void vsxger(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
|
||||
ppc_acc_t *at, uint32_t mask, bool acc, bool neg_mul,
|
||||
bool neg_acc, vsxger_muladd_f mul, vsxger_muladd_f muladd,
|
||||
vsxger_zero zero)
|
||||
{
|
||||
int i, j, xmsk_bit, ymsk_bit, op_flags;
|
||||
uint8_t xmsk = mask & 0x0F;
|
||||
uint8_t ymsk = (mask >> 4) & 0x0F;
|
||||
float_status *excp_ptr = &env->fp_status;
|
||||
op_flags = (neg_acc ^ neg_mul) ? float_muladd_negate_c : 0;
|
||||
op_flags |= (neg_mul) ? float_muladd_negate_result : 0;
|
||||
helper_reset_fpstatus(env);
|
||||
for (i = 0, xmsk_bit = 1 << 3; i < 4; i++, xmsk_bit >>= 1) {
|
||||
for (j = 0, ymsk_bit = 1 << 3; j < 4; j++, ymsk_bit >>= 1) {
|
||||
if ((xmsk_bit & xmsk) && (ymsk_bit & ymsk)) {
|
||||
if (acc) {
|
||||
muladd(at, a, b, i, j, op_flags, excp_ptr);
|
||||
} else {
|
||||
mul(at, a, b, i, j, op_flags, excp_ptr);
|
||||
}
|
||||
} else {
|
||||
zero(at, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
vsxger_excp(env, GETPC());
|
||||
}
|
||||
|
||||
QEMU_FLATTEN
|
||||
void helper_XVF32GER(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
|
||||
ppc_acc_t *at, uint32_t mask)
|
||||
{
|
||||
vsxger(env, a, b, at, mask, false, false, false, vsxger_mul32,
|
||||
vsxger_muladd32, vsxger_zero32);
|
||||
}
|
||||
|
||||
QEMU_FLATTEN
|
||||
void helper_XVF32GERPP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
|
||||
ppc_acc_t *at, uint32_t mask)
|
||||
{
|
||||
vsxger(env, a, b, at, mask, true, false, false, vsxger_mul32,
|
||||
vsxger_muladd32, vsxger_zero32);
|
||||
}
|
||||
|
||||
QEMU_FLATTEN
|
||||
void helper_XVF32GERPN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
|
||||
ppc_acc_t *at, uint32_t mask)
|
||||
{
|
||||
vsxger(env, a, b, at, mask, true, false, true, vsxger_mul32,
|
||||
vsxger_muladd32, vsxger_zero32);
|
||||
}
|
||||
|
||||
QEMU_FLATTEN
|
||||
void helper_XVF32GERNP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
|
||||
ppc_acc_t *at, uint32_t mask)
|
||||
{
|
||||
vsxger(env, a, b, at, mask, true, true, false, vsxger_mul32,
|
||||
vsxger_muladd32, vsxger_zero32);
|
||||
}
|
||||
|
||||
QEMU_FLATTEN
|
||||
void helper_XVF32GERNN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
|
||||
ppc_acc_t *at, uint32_t mask)
|
||||
{
|
||||
vsxger(env, a, b, at, mask, true, true, true, vsxger_mul32,
|
||||
vsxger_muladd32, vsxger_zero32);
|
||||
}
|
||||
|
||||
QEMU_FLATTEN
|
||||
void helper_XVF64GER(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
|
||||
ppc_acc_t *at, uint32_t mask)
|
||||
{
|
||||
vsxger(env, a, b, at, mask, false, false, false, vsxger_mul64,
|
||||
vsxger_muladd64, vsxger_zero64);
|
||||
}
|
||||
|
||||
QEMU_FLATTEN
|
||||
void helper_XVF64GERPP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
|
||||
ppc_acc_t *at, uint32_t mask)
|
||||
{
|
||||
vsxger(env, a, b, at, mask, true, false, false, vsxger_mul64,
|
||||
vsxger_muladd64, vsxger_zero64);
|
||||
}
|
||||
|
||||
QEMU_FLATTEN
|
||||
void helper_XVF64GERPN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
|
||||
ppc_acc_t *at, uint32_t mask)
|
||||
{
|
||||
vsxger(env, a, b, at, mask, true, false, true, vsxger_mul64,
|
||||
vsxger_muladd64, vsxger_zero64);
|
||||
}
|
||||
|
||||
QEMU_FLATTEN
|
||||
void helper_XVF64GERNP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
|
||||
ppc_acc_t *at, uint32_t mask)
|
||||
{
|
||||
vsxger(env, a, b, at, mask, true, true, false, vsxger_mul64,
|
||||
vsxger_muladd64, vsxger_zero64);
|
||||
}
|
||||
|
||||
QEMU_FLATTEN
|
||||
void helper_XVF64GERNN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
|
||||
ppc_acc_t *at, uint32_t mask)
|
||||
{
|
||||
vsxger(env, a, b, at, mask, true, true, true, vsxger_mul64,
|
||||
vsxger_muladd64, vsxger_zero64);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue