mirror of https://github.com/xemu-project/xemu.git
Patch queue for ppc - 2014-04-08
This is the final queue for 2.0! It fixes a lot of bugs people have seen during testing: - Fix e500 SMP - Fix book3s_64 DEC - Fix VSX (new feature in 2.0) for LE hosts - Fix PR KVM on top of pHyp (SLOF update) -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABAgAGBQJTQ8BCAAoJECszeR4D/txgX98QAI9ccJung8AY7KT5X6gaKZqH rC2bBuB6Cg/Lkm8sUIEhsYJKpT4F2LTwQvWpi/L9JbXR2L39o5Gt9LD3a00VG4gC eKIm9utZN7GJw61w6GzGIEjQX3eQh0GJUqP+U3KEh8Vzdl+Vr3sEpeuVQzwucO1Z dYPKXK9ZVXLcTgCDbCO/D6R4129mnbZvyTiJIJLPewVXcBB0fKWHdu5x+VexaVXz tuwa1UfMVqUBFcBxDvqRmvTCLwCwa0Gn2kVSl0sNb/cw/MRatb0uomJCr6OQCgXX Fu6pEur+Tvsq/8twuqnTz/7Hs+EruYr6+4kB63ZZwRabJ1UmRmGUrIh+BvMJvgii lGLV4F4VCqxakDLuFqvS98Ww+HhgBUqjnRPkKP+Epyg6JFV4yh+CWXIWY0ck27E9 aVSgeEgmNISIQs5vJ7JTNcGmF8KXvHc74HCtNQyenC89EoVaGHxI/ssJIk3u4dVA TxYgb7tttG+qXAEeaxXziwptd5Tb4mWxx1j6Pz/Es9kqURWCnIBAfuoihDXIsKwc +D6pv1GQ5vkTIyLbWjZ7LSkFNfJBFQzzbxXVBxzK1gOoklQBjJXNOylcuyOYLUD2 HjDDkVdolRv6xMWYQltUc2UlMos5rGC3rNvtJ4K9CeoIo7hZiSRnM9gnbIf/TwBo 55n53ZvZhIksFQXArmfH =U2m0 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/agraf/tags/signed-ppc-for-upstream' into staging Patch queue for ppc - 2014-04-08 This is the final queue for 2.0! It fixes a lot of bugs people have seen during testing: - Fix e500 SMP - Fix book3s_64 DEC - Fix VSX (new feature in 2.0) for LE hosts - Fix PR KVM on top of pHyp (SLOF update) # gpg: Signature made Tue 08 Apr 2014 10:24:18 BST using RSA key ID 03FEDC60 # gpg: Can't check signature: public key not found * remotes/agraf/tags/signed-ppc-for-upstream: PPC: Add l1 cache sizes for 970 and above systems ppce500_spin: Initialize struct properly PPC: Only enter MSR_POW when no interrupts pending PPC: Clean up DECR implementation target-ppc: Correct VSX Integer to FP Conversion target-ppc: Correct VSX FP to Integer Conversion target-ppc: Correct VSX FP to FP Conversions target-ppc: Correct VSX Scalar Compares target-ppc: Correct Simple VSR LE Host Inversions target-ppc: Correct LE Host Inversion of Lower VSRs target-ppc: Define Endian-Correct Accessors for VSR Field Access target-ppc: Bug: VSX Convert to Integer Should Truncate softfloat: Introduce float32_to_uint64_round_to_zero pseries: Update SLOF firmware image to qemu-slof-20140404 PPC: E500: Set PIR default reset value rather than SPR value Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
9a4fb6aa19
|
@ -1626,6 +1626,26 @@ uint64 float32_to_uint64(float32 a STATUS_PARAM)
|
|||
return roundAndPackUint64(aSign, aSig64, aSigExtra STATUS_VAR);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the single-precision floating-point value
|
||||
| `a' to the 64-bit unsigned integer format. The conversion is
|
||||
| performed according to the IEC/IEEE Standard for Binary Floating-Point
|
||||
| Arithmetic, except that the conversion is always rounded toward zero. If
|
||||
| `a' is a NaN, the largest unsigned integer is returned. Otherwise, if the
|
||||
| conversion overflows, the largest unsigned integer is returned. If the
|
||||
| 'a' is negative, the result is rounded and zero is returned; values that do
|
||||
| not round to zero will raise the inexact flag.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
uint64 float32_to_uint64_round_to_zero(float32 a STATUS_PARAM)
|
||||
{
|
||||
signed char current_rounding_mode = STATUS(float_rounding_mode);
|
||||
set_float_rounding_mode(float_round_to_zero STATUS_VAR);
|
||||
int64_t v = float32_to_uint64(a STATUS_VAR);
|
||||
set_float_rounding_mode(current_rounding_mode STATUS_VAR);
|
||||
return v;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the single-precision floating-point value
|
||||
| `a' to the 64-bit two's complement integer format. The conversion is
|
||||
|
|
|
@ -649,7 +649,7 @@ void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params)
|
|||
input = (qemu_irq *)env->irq_inputs;
|
||||
irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
|
||||
irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
|
||||
env->spr[SPR_BOOKE_PIR] = cs->cpu_index = i;
|
||||
env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i;
|
||||
env->mpic_iack = MPC8544_CCSRBAR_BASE +
|
||||
MPC8544_MPIC_REGS_OFFSET + 0xa0;
|
||||
|
||||
|
|
92
hw/ppc/ppc.c
92
hw/ppc/ppc.c
|
@ -620,6 +620,13 @@ static void cpu_ppc_tb_start (CPUPPCState *env)
|
|||
}
|
||||
}
|
||||
|
||||
bool ppc_decr_clear_on_delivery(CPUPPCState *env)
|
||||
{
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
int flags = PPC_DECR_UNDERFLOW_TRIGGERED | PPC_DECR_UNDERFLOW_LEVEL;
|
||||
return ((tb_env->flags & flags) == PPC_DECR_UNDERFLOW_TRIGGERED);
|
||||
}
|
||||
|
||||
static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
|
||||
{
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
|
@ -677,6 +684,11 @@ static inline void cpu_ppc_decr_excp(PowerPCCPU *cpu)
|
|||
ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 1);
|
||||
}
|
||||
|
||||
static inline void cpu_ppc_decr_lower(PowerPCCPU *cpu)
|
||||
{
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 0);
|
||||
}
|
||||
|
||||
static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
|
||||
{
|
||||
/* Raise it */
|
||||
|
@ -684,11 +696,16 @@ static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
|
|||
ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
|
||||
}
|
||||
|
||||
static inline void cpu_ppc_hdecr_lower(PowerPCCPU *cpu)
|
||||
{
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 0);
|
||||
}
|
||||
|
||||
static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
|
||||
QEMUTimer *timer,
|
||||
void (*raise_excp)(PowerPCCPU *),
|
||||
uint32_t decr, uint32_t value,
|
||||
int is_excp)
|
||||
void (*raise_excp)(void *),
|
||||
void (*lower_excp)(PowerPCCPU *),
|
||||
uint32_t decr, uint32_t value)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
|
@ -702,59 +719,74 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Going from 2 -> 1, 1 -> 0 or 0 -> -1 is the event to generate a DEC
|
||||
* interrupt.
|
||||
*
|
||||
* If we get a really small DEC value, we can assume that by the time we
|
||||
* handled it we should inject an interrupt already.
|
||||
*
|
||||
* On MSB level based DEC implementations the MSB always means the interrupt
|
||||
* is pending, so raise it on those.
|
||||
*
|
||||
* On MSB edge based DEC implementations the MSB going from 0 -> 1 triggers
|
||||
* an edge interrupt, so raise it here too.
|
||||
*/
|
||||
if ((value < 3) ||
|
||||
((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && (value & 0x80000000)) ||
|
||||
((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && (value & 0x80000000)
|
||||
&& !(decr & 0x80000000))) {
|
||||
(*raise_excp)(cpu);
|
||||
return;
|
||||
}
|
||||
|
||||
/* On MSB level based systems a 0 for the MSB stops interrupt delivery */
|
||||
if (!(value & 0x80000000) && (tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL)) {
|
||||
(*lower_excp)(cpu);
|
||||
}
|
||||
|
||||
/* Calculate the next timer event */
|
||||
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
next = now + muldiv64(value, get_ticks_per_sec(), tb_env->decr_freq);
|
||||
if (is_excp) {
|
||||
next += *nextp - now;
|
||||
}
|
||||
if (next == now) {
|
||||
next++;
|
||||
}
|
||||
*nextp = next;
|
||||
|
||||
/* Adjust timer */
|
||||
timer_mod(timer, next);
|
||||
|
||||
/* If we set a negative value and the decrementer was positive, raise an
|
||||
* exception.
|
||||
*/
|
||||
if ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED)
|
||||
&& (value & 0x80000000)
|
||||
&& !(decr & 0x80000000)) {
|
||||
(*raise_excp)(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, uint32_t decr,
|
||||
uint32_t value, int is_excp)
|
||||
uint32_t value)
|
||||
{
|
||||
ppc_tb_t *tb_env = cpu->env.tb_env;
|
||||
|
||||
__cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer,
|
||||
&cpu_ppc_decr_excp, decr, value, is_excp);
|
||||
tb_env->decr_timer->cb, &cpu_ppc_decr_lower, decr,
|
||||
value);
|
||||
}
|
||||
|
||||
void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
|
||||
_cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value, 0);
|
||||
_cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value);
|
||||
}
|
||||
|
||||
static void cpu_ppc_decr_cb(void *opaque)
|
||||
{
|
||||
PowerPCCPU *cpu = opaque;
|
||||
|
||||
_cpu_ppc_store_decr(cpu, 0x00000000, 0xFFFFFFFF, 1);
|
||||
cpu_ppc_decr_excp(cpu);
|
||||
}
|
||||
|
||||
static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, uint32_t hdecr,
|
||||
uint32_t value, int is_excp)
|
||||
uint32_t value)
|
||||
{
|
||||
ppc_tb_t *tb_env = cpu->env.tb_env;
|
||||
|
||||
if (tb_env->hdecr_timer != NULL) {
|
||||
__cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer,
|
||||
&cpu_ppc_hdecr_excp, hdecr, value, is_excp);
|
||||
tb_env->hdecr_timer->cb, &cpu_ppc_hdecr_lower,
|
||||
hdecr, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -762,14 +794,14 @@ void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value)
|
|||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
|
||||
_cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value, 0);
|
||||
_cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value);
|
||||
}
|
||||
|
||||
static void cpu_ppc_hdecr_cb(void *opaque)
|
||||
{
|
||||
PowerPCCPU *cpu = opaque;
|
||||
|
||||
_cpu_ppc_store_hdecr(cpu, 0x00000000, 0xFFFFFFFF, 1);
|
||||
cpu_ppc_hdecr_excp(cpu);
|
||||
}
|
||||
|
||||
static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value)
|
||||
|
@ -792,8 +824,8 @@ static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
|
|||
* if a decrementer exception is pending when it enables msr_ee at startup,
|
||||
* it's not ready to handle it...
|
||||
*/
|
||||
_cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
|
||||
_cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
|
||||
_cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF);
|
||||
_cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF);
|
||||
cpu_ppc_store_purr(cpu, 0x0000000000000000ULL);
|
||||
}
|
||||
|
||||
|
@ -806,6 +838,10 @@ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
|
|||
tb_env = g_malloc0(sizeof(ppc_tb_t));
|
||||
env->tb_env = tb_env;
|
||||
tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
|
||||
if (env->insns_flags & PPC_SEGMENT_64B) {
|
||||
/* All Book3S 64bit CPUs implement level based DEC logic */
|
||||
tb_env->flags |= PPC_DECR_UNDERFLOW_LEVEL;
|
||||
}
|
||||
/* Create new timer */
|
||||
tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_decr_cb, cpu);
|
||||
if (0) {
|
||||
|
|
|
@ -65,9 +65,9 @@ static void spin_reset(void *opaque)
|
|||
for (i = 0; i < MAX_CPUS; i++) {
|
||||
SpinInfo *info = &s->spin[i];
|
||||
|
||||
info->pir = i;
|
||||
info->r3 = i;
|
||||
info->addr = 1;
|
||||
stl_p(&info->pir, i);
|
||||
stq_p(&info->r3, i);
|
||||
stq_p(&info->addr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -342,6 +342,7 @@ uint32 float32_to_uint32( float32 STATUS_PARAM );
|
|||
uint32 float32_to_uint32_round_to_zero( float32 STATUS_PARAM );
|
||||
int64 float32_to_int64( float32 STATUS_PARAM );
|
||||
uint64 float32_to_uint64(float32 STATUS_PARAM);
|
||||
uint64 float32_to_uint64_round_to_zero(float32 STATUS_PARAM);
|
||||
int64 float32_to_int64_round_to_zero( float32 STATUS_PARAM );
|
||||
float64 float32_to_float64( float32 STATUS_PARAM );
|
||||
floatx80 float32_to_floatx80( float32 STATUS_PARAM );
|
||||
|
|
|
@ -44,6 +44,9 @@ struct ppc_tb_t {
|
|||
#define PPC_DECR_ZERO_TRIGGERED (1 << 3) /* Decr interrupt triggered when
|
||||
* the decrementer reaches zero.
|
||||
*/
|
||||
#define PPC_DECR_UNDERFLOW_LEVEL (1 << 4) /* Decr interrupt active when
|
||||
* the most significant bit is 1.
|
||||
*/
|
||||
|
||||
uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset);
|
||||
clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
|
||||
implementation for certain IBM POWER hardware. The sources are at
|
||||
https://github.com/aik/SLOF, and the image currently in qemu is
|
||||
built from git tag qemu-slof-20140304.
|
||||
built from git tag qemu-slof-20140404.
|
||||
|
||||
- sgabios (the Serial Graphics Adapter option ROM) provides a means for
|
||||
legacy x86 software to communicate with an attached serial console as
|
||||
|
|
BIN
pc-bios/slof.bin
BIN
pc-bios/slof.bin
Binary file not shown.
|
@ -1 +1 @@
|
|||
Subproject commit af6b7bf5879b6cd6825de2a107cb0e3219fb1df5
|
||||
Subproject commit c90b50b5055f976a0da3c032f26fb80157292adc
|
|
@ -1133,6 +1133,7 @@ uint64_t cpu_ppc_load_atbl (CPUPPCState *env);
|
|||
uint32_t cpu_ppc_load_atbu (CPUPPCState *env);
|
||||
void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value);
|
||||
void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value);
|
||||
bool ppc_decr_clear_on_delivery(CPUPPCState *env);
|
||||
uint32_t cpu_ppc_load_decr (CPUPPCState *env);
|
||||
void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value);
|
||||
uint32_t cpu_ppc_load_hdecr (CPUPPCState *env);
|
||||
|
|
|
@ -723,7 +723,6 @@ void ppc_hw_interrupt(CPUPPCState *env)
|
|||
if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
|
||||
/* Hypervisor decrementer exception */
|
||||
if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
|
||||
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
|
||||
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
|
||||
return;
|
||||
}
|
||||
|
@ -767,7 +766,9 @@ void ppc_hw_interrupt(CPUPPCState *env)
|
|||
}
|
||||
/* Decrementer exception */
|
||||
if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
|
||||
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
|
||||
if (ppc_decr_clear_on_delivery(env)) {
|
||||
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
|
||||
}
|
||||
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1782,11 +1782,19 @@ typedef union _ppc_vsr_t {
|
|||
float64 f64[2];
|
||||
} ppc_vsr_t;
|
||||
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
#define VsrW(i) u32[i]
|
||||
#define VsrD(i) u64[i]
|
||||
#else
|
||||
#define VsrW(i) u32[3-(i)]
|
||||
#define VsrD(i) u64[1-(i)]
|
||||
#endif
|
||||
|
||||
static void getVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env)
|
||||
{
|
||||
if (n < 32) {
|
||||
vsr->f64[0] = env->fpr[n];
|
||||
vsr->u64[1] = env->vsr[n];
|
||||
vsr->VsrD(0) = env->fpr[n];
|
||||
vsr->VsrD(1) = env->vsr[n];
|
||||
} else {
|
||||
vsr->u64[0] = env->avr[n-32].u64[0];
|
||||
vsr->u64[1] = env->avr[n-32].u64[1];
|
||||
|
@ -1796,8 +1804,8 @@ static void getVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env)
|
|||
static void putVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env)
|
||||
{
|
||||
if (n < 32) {
|
||||
env->fpr[n] = vsr->f64[0];
|
||||
env->vsr[n] = vsr->u64[1];
|
||||
env->fpr[n] = vsr->VsrD(0);
|
||||
env->vsr[n] = vsr->VsrD(1);
|
||||
} else {
|
||||
env->avr[n-32].u64[0] = vsr->u64[0];
|
||||
env->avr[n-32].u64[1] = vsr->u64[1];
|
||||
|
@ -1812,7 +1820,7 @@ static void putVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env)
|
|||
* op - operation (add or sub)
|
||||
* nels - number of elements (1, 2 or 4)
|
||||
* tp - type (float32 or float64)
|
||||
* fld - vsr_t field (f32 or f64)
|
||||
* fld - vsr_t field (VsrD(*) or VsrW(*))
|
||||
* sfprf - set FPRF
|
||||
*/
|
||||
#define VSX_ADD_SUB(name, op, nels, tp, fld, sfprf, r2sp) \
|
||||
|
@ -1829,44 +1837,44 @@ void helper_##name(CPUPPCState *env, uint32_t opcode) \
|
|||
for (i = 0; i < nels; i++) { \
|
||||
float_status tstat = env->fp_status; \
|
||||
set_float_exception_flags(0, &tstat); \
|
||||
xt.fld[i] = tp##_##op(xa.fld[i], xb.fld[i], &tstat); \
|
||||
xt.fld = tp##_##op(xa.fld, xb.fld, &tstat); \
|
||||
env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
|
||||
\
|
||||
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
|
||||
if (tp##_is_infinity(xa.fld[i]) && tp##_is_infinity(xb.fld[i])) {\
|
||||
if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf); \
|
||||
} else if (tp##_is_signaling_nan(xa.fld[i]) || \
|
||||
tp##_is_signaling_nan(xb.fld[i])) { \
|
||||
} else if (tp##_is_signaling_nan(xa.fld) || \
|
||||
tp##_is_signaling_nan(xb.fld)) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (r2sp) { \
|
||||
xt.fld[i] = helper_frsp(env, xt.fld[i]); \
|
||||
xt.fld = helper_frsp(env, xt.fld); \
|
||||
} \
|
||||
\
|
||||
if (sfprf) { \
|
||||
helper_compute_fprf(env, xt.fld[i], sfprf); \
|
||||
helper_compute_fprf(env, xt.fld, sfprf); \
|
||||
} \
|
||||
} \
|
||||
putVSR(xT(opcode), &xt, env); \
|
||||
helper_float_check_status(env); \
|
||||
}
|
||||
|
||||
VSX_ADD_SUB(xsadddp, add, 1, float64, f64, 1, 0)
|
||||
VSX_ADD_SUB(xsaddsp, add, 1, float64, f64, 1, 1)
|
||||
VSX_ADD_SUB(xvadddp, add, 2, float64, f64, 0, 0)
|
||||
VSX_ADD_SUB(xvaddsp, add, 4, float32, f32, 0, 0)
|
||||
VSX_ADD_SUB(xssubdp, sub, 1, float64, f64, 1, 0)
|
||||
VSX_ADD_SUB(xssubsp, sub, 1, float64, f64, 1, 1)
|
||||
VSX_ADD_SUB(xvsubdp, sub, 2, float64, f64, 0, 0)
|
||||
VSX_ADD_SUB(xvsubsp, sub, 4, float32, f32, 0, 0)
|
||||
VSX_ADD_SUB(xsadddp, add, 1, float64, VsrD(0), 1, 0)
|
||||
VSX_ADD_SUB(xsaddsp, add, 1, float64, VsrD(0), 1, 1)
|
||||
VSX_ADD_SUB(xvadddp, add, 2, float64, VsrD(i), 0, 0)
|
||||
VSX_ADD_SUB(xvaddsp, add, 4, float32, VsrW(i), 0, 0)
|
||||
VSX_ADD_SUB(xssubdp, sub, 1, float64, VsrD(0), 1, 0)
|
||||
VSX_ADD_SUB(xssubsp, sub, 1, float64, VsrD(0), 1, 1)
|
||||
VSX_ADD_SUB(xvsubdp, sub, 2, float64, VsrD(i), 0, 0)
|
||||
VSX_ADD_SUB(xvsubsp, sub, 4, float32, VsrW(i), 0, 0)
|
||||
|
||||
/* VSX_MUL - VSX floating point multiply
|
||||
* op - instruction mnemonic
|
||||
* nels - number of elements (1, 2 or 4)
|
||||
* tp - type (float32 or float64)
|
||||
* fld - vsr_t field (f32 or f64)
|
||||
* fld - vsr_t field (VsrD(*) or VsrW(*))
|
||||
* sfprf - set FPRF
|
||||
*/
|
||||
#define VSX_MUL(op, nels, tp, fld, sfprf, r2sp) \
|
||||
|
@ -1883,25 +1891,25 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
for (i = 0; i < nels; i++) { \
|
||||
float_status tstat = env->fp_status; \
|
||||
set_float_exception_flags(0, &tstat); \
|
||||
xt.fld[i] = tp##_mul(xa.fld[i], xb.fld[i], &tstat); \
|
||||
xt.fld = tp##_mul(xa.fld, xb.fld, &tstat); \
|
||||
env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
|
||||
\
|
||||
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
|
||||
if ((tp##_is_infinity(xa.fld[i]) && tp##_is_zero(xb.fld[i])) || \
|
||||
(tp##_is_infinity(xb.fld[i]) && tp##_is_zero(xa.fld[i]))) { \
|
||||
if ((tp##_is_infinity(xa.fld) && tp##_is_zero(xb.fld)) || \
|
||||
(tp##_is_infinity(xb.fld) && tp##_is_zero(xa.fld))) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, sfprf); \
|
||||
} else if (tp##_is_signaling_nan(xa.fld[i]) || \
|
||||
tp##_is_signaling_nan(xb.fld[i])) { \
|
||||
} else if (tp##_is_signaling_nan(xa.fld) || \
|
||||
tp##_is_signaling_nan(xb.fld)) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (r2sp) { \
|
||||
xt.fld[i] = helper_frsp(env, xt.fld[i]); \
|
||||
xt.fld = helper_frsp(env, xt.fld); \
|
||||
} \
|
||||
\
|
||||
if (sfprf) { \
|
||||
helper_compute_fprf(env, xt.fld[i], sfprf); \
|
||||
helper_compute_fprf(env, xt.fld, sfprf); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
|
@ -1909,16 +1917,16 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
helper_float_check_status(env); \
|
||||
}
|
||||
|
||||
VSX_MUL(xsmuldp, 1, float64, f64, 1, 0)
|
||||
VSX_MUL(xsmulsp, 1, float64, f64, 1, 1)
|
||||
VSX_MUL(xvmuldp, 2, float64, f64, 0, 0)
|
||||
VSX_MUL(xvmulsp, 4, float32, f32, 0, 0)
|
||||
VSX_MUL(xsmuldp, 1, float64, VsrD(0), 1, 0)
|
||||
VSX_MUL(xsmulsp, 1, float64, VsrD(0), 1, 1)
|
||||
VSX_MUL(xvmuldp, 2, float64, VsrD(i), 0, 0)
|
||||
VSX_MUL(xvmulsp, 4, float32, VsrW(i), 0, 0)
|
||||
|
||||
/* VSX_DIV - VSX floating point divide
|
||||
* op - instruction mnemonic
|
||||
* nels - number of elements (1, 2 or 4)
|
||||
* tp - type (float32 or float64)
|
||||
* fld - vsr_t field (f32 or f64)
|
||||
* fld - vsr_t field (VsrD(*) or VsrW(*))
|
||||
* sfprf - set FPRF
|
||||
*/
|
||||
#define VSX_DIV(op, nels, tp, fld, sfprf, r2sp) \
|
||||
|
@ -1935,27 +1943,27 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
for (i = 0; i < nels; i++) { \
|
||||
float_status tstat = env->fp_status; \
|
||||
set_float_exception_flags(0, &tstat); \
|
||||
xt.fld[i] = tp##_div(xa.fld[i], xb.fld[i], &tstat); \
|
||||
xt.fld = tp##_div(xa.fld, xb.fld, &tstat); \
|
||||
env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
|
||||
\
|
||||
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
|
||||
if (tp##_is_infinity(xa.fld[i]) && tp##_is_infinity(xb.fld[i])) { \
|
||||
if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, sfprf); \
|
||||
} else if (tp##_is_zero(xa.fld[i]) && \
|
||||
tp##_is_zero(xb.fld[i])) { \
|
||||
} else if (tp##_is_zero(xa.fld) && \
|
||||
tp##_is_zero(xb.fld)) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, sfprf); \
|
||||
} else if (tp##_is_signaling_nan(xa.fld[i]) || \
|
||||
tp##_is_signaling_nan(xb.fld[i])) { \
|
||||
} else if (tp##_is_signaling_nan(xa.fld) || \
|
||||
tp##_is_signaling_nan(xb.fld)) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (r2sp) { \
|
||||
xt.fld[i] = helper_frsp(env, xt.fld[i]); \
|
||||
xt.fld = helper_frsp(env, xt.fld); \
|
||||
} \
|
||||
\
|
||||
if (sfprf) { \
|
||||
helper_compute_fprf(env, xt.fld[i], sfprf); \
|
||||
helper_compute_fprf(env, xt.fld, sfprf); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
|
@ -1963,16 +1971,16 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
helper_float_check_status(env); \
|
||||
}
|
||||
|
||||
VSX_DIV(xsdivdp, 1, float64, f64, 1, 0)
|
||||
VSX_DIV(xsdivsp, 1, float64, f64, 1, 1)
|
||||
VSX_DIV(xvdivdp, 2, float64, f64, 0, 0)
|
||||
VSX_DIV(xvdivsp, 4, float32, f32, 0, 0)
|
||||
VSX_DIV(xsdivdp, 1, float64, VsrD(0), 1, 0)
|
||||
VSX_DIV(xsdivsp, 1, float64, VsrD(0), 1, 1)
|
||||
VSX_DIV(xvdivdp, 2, float64, VsrD(i), 0, 0)
|
||||
VSX_DIV(xvdivsp, 4, float32, VsrW(i), 0, 0)
|
||||
|
||||
/* VSX_RE - VSX floating point reciprocal estimate
|
||||
* op - instruction mnemonic
|
||||
* nels - number of elements (1, 2 or 4)
|
||||
* tp - type (float32 or float64)
|
||||
* fld - vsr_t field (f32 or f64)
|
||||
* fld - vsr_t field (VsrD(*) or VsrW(*))
|
||||
* sfprf - set FPRF
|
||||
*/
|
||||
#define VSX_RE(op, nels, tp, fld, sfprf, r2sp) \
|
||||
|
@ -1986,17 +1994,17 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
helper_reset_fpstatus(env); \
|
||||
\
|
||||
for (i = 0; i < nels; i++) { \
|
||||
if (unlikely(tp##_is_signaling_nan(xb.fld[i]))) { \
|
||||
if (unlikely(tp##_is_signaling_nan(xb.fld))) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
|
||||
} \
|
||||
xt.fld[i] = tp##_div(tp##_one, xb.fld[i], &env->fp_status); \
|
||||
xt.fld = tp##_div(tp##_one, xb.fld, &env->fp_status); \
|
||||
\
|
||||
if (r2sp) { \
|
||||
xt.fld[i] = helper_frsp(env, xt.fld[i]); \
|
||||
xt.fld = helper_frsp(env, xt.fld); \
|
||||
} \
|
||||
\
|
||||
if (sfprf) { \
|
||||
helper_compute_fprf(env, xt.fld[0], sfprf); \
|
||||
helper_compute_fprf(env, xt.fld, sfprf); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
|
@ -2004,16 +2012,16 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
helper_float_check_status(env); \
|
||||
}
|
||||
|
||||
VSX_RE(xsredp, 1, float64, f64, 1, 0)
|
||||
VSX_RE(xsresp, 1, float64, f64, 1, 1)
|
||||
VSX_RE(xvredp, 2, float64, f64, 0, 0)
|
||||
VSX_RE(xvresp, 4, float32, f32, 0, 0)
|
||||
VSX_RE(xsredp, 1, float64, VsrD(0), 1, 0)
|
||||
VSX_RE(xsresp, 1, float64, VsrD(0), 1, 1)
|
||||
VSX_RE(xvredp, 2, float64, VsrD(i), 0, 0)
|
||||
VSX_RE(xvresp, 4, float32, VsrW(i), 0, 0)
|
||||
|
||||
/* VSX_SQRT - VSX floating point square root
|
||||
* op - instruction mnemonic
|
||||
* nels - number of elements (1, 2 or 4)
|
||||
* tp - type (float32 or float64)
|
||||
* fld - vsr_t field (f32 or f64)
|
||||
* fld - vsr_t field (VsrD(*) or VsrW(*))
|
||||
* sfprf - set FPRF
|
||||
*/
|
||||
#define VSX_SQRT(op, nels, tp, fld, sfprf, r2sp) \
|
||||
|
@ -2029,23 +2037,23 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
for (i = 0; i < nels; i++) { \
|
||||
float_status tstat = env->fp_status; \
|
||||
set_float_exception_flags(0, &tstat); \
|
||||
xt.fld[i] = tp##_sqrt(xb.fld[i], &tstat); \
|
||||
xt.fld = tp##_sqrt(xb.fld, &tstat); \
|
||||
env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
|
||||
\
|
||||
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
|
||||
if (tp##_is_neg(xb.fld[i]) && !tp##_is_zero(xb.fld[i])) { \
|
||||
if (tp##_is_neg(xb.fld) && !tp##_is_zero(xb.fld)) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf); \
|
||||
} else if (tp##_is_signaling_nan(xb.fld[i])) { \
|
||||
} else if (tp##_is_signaling_nan(xb.fld)) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (r2sp) { \
|
||||
xt.fld[i] = helper_frsp(env, xt.fld[i]); \
|
||||
xt.fld = helper_frsp(env, xt.fld); \
|
||||
} \
|
||||
\
|
||||
if (sfprf) { \
|
||||
helper_compute_fprf(env, xt.fld[i], sfprf); \
|
||||
helper_compute_fprf(env, xt.fld, sfprf); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
|
@ -2053,16 +2061,16 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
helper_float_check_status(env); \
|
||||
}
|
||||
|
||||
VSX_SQRT(xssqrtdp, 1, float64, f64, 1, 0)
|
||||
VSX_SQRT(xssqrtsp, 1, float64, f64, 1, 1)
|
||||
VSX_SQRT(xvsqrtdp, 2, float64, f64, 0, 0)
|
||||
VSX_SQRT(xvsqrtsp, 4, float32, f32, 0, 0)
|
||||
VSX_SQRT(xssqrtdp, 1, float64, VsrD(0), 1, 0)
|
||||
VSX_SQRT(xssqrtsp, 1, float64, VsrD(0), 1, 1)
|
||||
VSX_SQRT(xvsqrtdp, 2, float64, VsrD(i), 0, 0)
|
||||
VSX_SQRT(xvsqrtsp, 4, float32, VsrW(i), 0, 0)
|
||||
|
||||
/* VSX_RSQRTE - VSX floating point reciprocal square root estimate
|
||||
* op - instruction mnemonic
|
||||
* nels - number of elements (1, 2 or 4)
|
||||
* tp - type (float32 or float64)
|
||||
* fld - vsr_t field (f32 or f64)
|
||||
* fld - vsr_t field (VsrD(*) or VsrW(*))
|
||||
* sfprf - set FPRF
|
||||
*/
|
||||
#define VSX_RSQRTE(op, nels, tp, fld, sfprf, r2sp) \
|
||||
|
@ -2078,24 +2086,24 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
for (i = 0; i < nels; i++) { \
|
||||
float_status tstat = env->fp_status; \
|
||||
set_float_exception_flags(0, &tstat); \
|
||||
xt.fld[i] = tp##_sqrt(xb.fld[i], &tstat); \
|
||||
xt.fld[i] = tp##_div(tp##_one, xt.fld[i], &tstat); \
|
||||
xt.fld = tp##_sqrt(xb.fld, &tstat); \
|
||||
xt.fld = tp##_div(tp##_one, xt.fld, &tstat); \
|
||||
env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
|
||||
\
|
||||
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
|
||||
if (tp##_is_neg(xb.fld[i]) && !tp##_is_zero(xb.fld[i])) { \
|
||||
if (tp##_is_neg(xb.fld) && !tp##_is_zero(xb.fld)) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf); \
|
||||
} else if (tp##_is_signaling_nan(xb.fld[i])) { \
|
||||
} else if (tp##_is_signaling_nan(xb.fld)) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (r2sp) { \
|
||||
xt.fld[i] = helper_frsp(env, xt.fld[i]); \
|
||||
xt.fld = helper_frsp(env, xt.fld); \
|
||||
} \
|
||||
\
|
||||
if (sfprf) { \
|
||||
helper_compute_fprf(env, xt.fld[i], sfprf); \
|
||||
helper_compute_fprf(env, xt.fld, sfprf); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
|
@ -2103,16 +2111,16 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
helper_float_check_status(env); \
|
||||
}
|
||||
|
||||
VSX_RSQRTE(xsrsqrtedp, 1, float64, f64, 1, 0)
|
||||
VSX_RSQRTE(xsrsqrtesp, 1, float64, f64, 1, 1)
|
||||
VSX_RSQRTE(xvrsqrtedp, 2, float64, f64, 0, 0)
|
||||
VSX_RSQRTE(xvrsqrtesp, 4, float32, f32, 0, 0)
|
||||
VSX_RSQRTE(xsrsqrtedp, 1, float64, VsrD(0), 1, 0)
|
||||
VSX_RSQRTE(xsrsqrtesp, 1, float64, VsrD(0), 1, 1)
|
||||
VSX_RSQRTE(xvrsqrtedp, 2, float64, VsrD(i), 0, 0)
|
||||
VSX_RSQRTE(xvrsqrtesp, 4, float32, VsrW(i), 0, 0)
|
||||
|
||||
/* VSX_TDIV - VSX floating point test for divide
|
||||
* op - instruction mnemonic
|
||||
* nels - number of elements (1, 2 or 4)
|
||||
* tp - type (float32 or float64)
|
||||
* fld - vsr_t field (f32 or f64)
|
||||
* fld - vsr_t field (VsrD(*) or VsrW(*))
|
||||
* emin - minimum unbiased exponent
|
||||
* emax - maximum unbiased exponent
|
||||
* nbits - number of fraction bits
|
||||
|
@ -2129,28 +2137,28 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
getVSR(xB(opcode), &xb, env); \
|
||||
\
|
||||
for (i = 0; i < nels; i++) { \
|
||||
if (unlikely(tp##_is_infinity(xa.fld[i]) || \
|
||||
tp##_is_infinity(xb.fld[i]) || \
|
||||
tp##_is_zero(xb.fld[i]))) { \
|
||||
if (unlikely(tp##_is_infinity(xa.fld) || \
|
||||
tp##_is_infinity(xb.fld) || \
|
||||
tp##_is_zero(xb.fld))) { \
|
||||
fe_flag = 1; \
|
||||
fg_flag = 1; \
|
||||
} else { \
|
||||
int e_a = ppc_##tp##_get_unbiased_exp(xa.fld[i]); \
|
||||
int e_b = ppc_##tp##_get_unbiased_exp(xb.fld[i]); \
|
||||
int e_a = ppc_##tp##_get_unbiased_exp(xa.fld); \
|
||||
int e_b = ppc_##tp##_get_unbiased_exp(xb.fld); \
|
||||
\
|
||||
if (unlikely(tp##_is_any_nan(xa.fld[i]) || \
|
||||
tp##_is_any_nan(xb.fld[i]))) { \
|
||||
if (unlikely(tp##_is_any_nan(xa.fld) || \
|
||||
tp##_is_any_nan(xb.fld))) { \
|
||||
fe_flag = 1; \
|
||||
} else if ((e_b <= emin) || (e_b >= (emax-2))) { \
|
||||
fe_flag = 1; \
|
||||
} else if (!tp##_is_zero(xa.fld[i]) && \
|
||||
} else if (!tp##_is_zero(xa.fld) && \
|
||||
(((e_a - e_b) >= emax) || \
|
||||
((e_a - e_b) <= (emin+1)) || \
|
||||
(e_a <= (emin+nbits)))) { \
|
||||
fe_flag = 1; \
|
||||
} \
|
||||
\
|
||||
if (unlikely(tp##_is_zero_or_denormal(xb.fld[i]))) { \
|
||||
if (unlikely(tp##_is_zero_or_denormal(xb.fld))) { \
|
||||
/* XB is not zero because of the above check and */ \
|
||||
/* so must be denormalized. */ \
|
||||
fg_flag = 1; \
|
||||
|
@ -2161,15 +2169,15 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
env->crf[BF(opcode)] = 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0); \
|
||||
}
|
||||
|
||||
VSX_TDIV(xstdivdp, 1, float64, f64, -1022, 1023, 52)
|
||||
VSX_TDIV(xvtdivdp, 2, float64, f64, -1022, 1023, 52)
|
||||
VSX_TDIV(xvtdivsp, 4, float32, f32, -126, 127, 23)
|
||||
VSX_TDIV(xstdivdp, 1, float64, VsrD(0), -1022, 1023, 52)
|
||||
VSX_TDIV(xvtdivdp, 2, float64, VsrD(i), -1022, 1023, 52)
|
||||
VSX_TDIV(xvtdivsp, 4, float32, VsrW(i), -126, 127, 23)
|
||||
|
||||
/* VSX_TSQRT - VSX floating point test for square root
|
||||
* op - instruction mnemonic
|
||||
* nels - number of elements (1, 2 or 4)
|
||||
* tp - type (float32 or float64)
|
||||
* fld - vsr_t field (f32 or f64)
|
||||
* fld - vsr_t field (VsrD(*) or VsrW(*))
|
||||
* emin - minimum unbiased exponent
|
||||
* emax - maximum unbiased exponent
|
||||
* nbits - number of fraction bits
|
||||
|
@ -2186,25 +2194,25 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
getVSR(xB(opcode), &xb, env); \
|
||||
\
|
||||
for (i = 0; i < nels; i++) { \
|
||||
if (unlikely(tp##_is_infinity(xb.fld[i]) || \
|
||||
tp##_is_zero(xb.fld[i]))) { \
|
||||
if (unlikely(tp##_is_infinity(xb.fld) || \
|
||||
tp##_is_zero(xb.fld))) { \
|
||||
fe_flag = 1; \
|
||||
fg_flag = 1; \
|
||||
} else { \
|
||||
int e_b = ppc_##tp##_get_unbiased_exp(xb.fld[i]); \
|
||||
int e_b = ppc_##tp##_get_unbiased_exp(xb.fld); \
|
||||
\
|
||||
if (unlikely(tp##_is_any_nan(xb.fld[i]))) { \
|
||||
if (unlikely(tp##_is_any_nan(xb.fld))) { \
|
||||
fe_flag = 1; \
|
||||
} else if (unlikely(tp##_is_zero(xb.fld[i]))) { \
|
||||
} else if (unlikely(tp##_is_zero(xb.fld))) { \
|
||||
fe_flag = 1; \
|
||||
} else if (unlikely(tp##_is_neg(xb.fld[i]))) { \
|
||||
} else if (unlikely(tp##_is_neg(xb.fld))) { \
|
||||
fe_flag = 1; \
|
||||
} else if (!tp##_is_zero(xb.fld[i]) && \
|
||||
} else if (!tp##_is_zero(xb.fld) && \
|
||||
(e_b <= (emin+nbits))) { \
|
||||
fe_flag = 1; \
|
||||
} \
|
||||
\
|
||||
if (unlikely(tp##_is_zero_or_denormal(xb.fld[i]))) { \
|
||||
if (unlikely(tp##_is_zero_or_denormal(xb.fld))) { \
|
||||
/* XB is not zero because of the above check and */ \
|
||||
/* therefore must be denormalized. */ \
|
||||
fg_flag = 1; \
|
||||
|
@ -2215,15 +2223,15 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
env->crf[BF(opcode)] = 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0); \
|
||||
}
|
||||
|
||||
VSX_TSQRT(xstsqrtdp, 1, float64, f64, -1022, 52)
|
||||
VSX_TSQRT(xvtsqrtdp, 2, float64, f64, -1022, 52)
|
||||
VSX_TSQRT(xvtsqrtsp, 4, float32, f32, -126, 23)
|
||||
VSX_TSQRT(xstsqrtdp, 1, float64, VsrD(0), -1022, 52)
|
||||
VSX_TSQRT(xvtsqrtdp, 2, float64, VsrD(i), -1022, 52)
|
||||
VSX_TSQRT(xvtsqrtsp, 4, float32, VsrW(i), -126, 23)
|
||||
|
||||
/* VSX_MADD - VSX floating point muliply/add variations
|
||||
* op - instruction mnemonic
|
||||
* nels - number of elements (1, 2 or 4)
|
||||
* tp - type (float32 or float64)
|
||||
* fld - vsr_t field (f32 or f64)
|
||||
* fld - vsr_t field (VsrD(*) or VsrW(*))
|
||||
* maddflgs - flags for the float*muladd routine that control the
|
||||
* various forms (madd, msub, nmadd, nmsub)
|
||||
* afrm - A form (1=A, 0=M)
|
||||
|
@ -2259,43 +2267,43 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
/* Avoid double rounding errors by rounding the intermediate */ \
|
||||
/* result to odd. */ \
|
||||
set_float_rounding_mode(float_round_to_zero, &tstat); \
|
||||
xt_out.fld[i] = tp##_muladd(xa.fld[i], b->fld[i], c->fld[i], \
|
||||
xt_out.fld = tp##_muladd(xa.fld, b->fld, c->fld, \
|
||||
maddflgs, &tstat); \
|
||||
xt_out.fld[i] |= (get_float_exception_flags(&tstat) & \
|
||||
xt_out.fld |= (get_float_exception_flags(&tstat) & \
|
||||
float_flag_inexact) != 0; \
|
||||
} else { \
|
||||
xt_out.fld[i] = tp##_muladd(xa.fld[i], b->fld[i], c->fld[i], \
|
||||
xt_out.fld = tp##_muladd(xa.fld, b->fld, c->fld, \
|
||||
maddflgs, &tstat); \
|
||||
} \
|
||||
env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
|
||||
\
|
||||
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
|
||||
if (tp##_is_signaling_nan(xa.fld[i]) || \
|
||||
tp##_is_signaling_nan(b->fld[i]) || \
|
||||
tp##_is_signaling_nan(c->fld[i])) { \
|
||||
if (tp##_is_signaling_nan(xa.fld) || \
|
||||
tp##_is_signaling_nan(b->fld) || \
|
||||
tp##_is_signaling_nan(c->fld)) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
|
||||
tstat.float_exception_flags &= ~float_flag_invalid; \
|
||||
} \
|
||||
if ((tp##_is_infinity(xa.fld[i]) && tp##_is_zero(b->fld[i])) || \
|
||||
(tp##_is_zero(xa.fld[i]) && tp##_is_infinity(b->fld[i]))) { \
|
||||
xt_out.fld[i] = float64_to_##tp(fload_invalid_op_excp(env, \
|
||||
if ((tp##_is_infinity(xa.fld) && tp##_is_zero(b->fld)) || \
|
||||
(tp##_is_zero(xa.fld) && tp##_is_infinity(b->fld))) { \
|
||||
xt_out.fld = float64_to_##tp(fload_invalid_op_excp(env, \
|
||||
POWERPC_EXCP_FP_VXIMZ, sfprf), &env->fp_status); \
|
||||
tstat.float_exception_flags &= ~float_flag_invalid; \
|
||||
} \
|
||||
if ((tstat.float_exception_flags & float_flag_invalid) && \
|
||||
((tp##_is_infinity(xa.fld[i]) || \
|
||||
tp##_is_infinity(b->fld[i])) && \
|
||||
tp##_is_infinity(c->fld[i]))) { \
|
||||
((tp##_is_infinity(xa.fld) || \
|
||||
tp##_is_infinity(b->fld)) && \
|
||||
tp##_is_infinity(c->fld))) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (r2sp) { \
|
||||
xt_out.fld[i] = helper_frsp(env, xt_out.fld[i]); \
|
||||
xt_out.fld = helper_frsp(env, xt_out.fld); \
|
||||
} \
|
||||
\
|
||||
if (sfprf) { \
|
||||
helper_compute_fprf(env, xt_out.fld[i], sfprf); \
|
||||
helper_compute_fprf(env, xt_out.fld, sfprf); \
|
||||
} \
|
||||
} \
|
||||
putVSR(xT(opcode), &xt_out, env); \
|
||||
|
@ -2307,41 +2315,41 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
#define NMADD_FLGS float_muladd_negate_result
|
||||
#define NMSUB_FLGS (float_muladd_negate_c | float_muladd_negate_result)
|
||||
|
||||
VSX_MADD(xsmaddadp, 1, float64, f64, MADD_FLGS, 1, 1, 0)
|
||||
VSX_MADD(xsmaddmdp, 1, float64, f64, MADD_FLGS, 0, 1, 0)
|
||||
VSX_MADD(xsmsubadp, 1, float64, f64, MSUB_FLGS, 1, 1, 0)
|
||||
VSX_MADD(xsmsubmdp, 1, float64, f64, MSUB_FLGS, 0, 1, 0)
|
||||
VSX_MADD(xsnmaddadp, 1, float64, f64, NMADD_FLGS, 1, 1, 0)
|
||||
VSX_MADD(xsnmaddmdp, 1, float64, f64, NMADD_FLGS, 0, 1, 0)
|
||||
VSX_MADD(xsnmsubadp, 1, float64, f64, NMSUB_FLGS, 1, 1, 0)
|
||||
VSX_MADD(xsnmsubmdp, 1, float64, f64, NMSUB_FLGS, 0, 1, 0)
|
||||
VSX_MADD(xsmaddadp, 1, float64, VsrD(0), MADD_FLGS, 1, 1, 0)
|
||||
VSX_MADD(xsmaddmdp, 1, float64, VsrD(0), MADD_FLGS, 0, 1, 0)
|
||||
VSX_MADD(xsmsubadp, 1, float64, VsrD(0), MSUB_FLGS, 1, 1, 0)
|
||||
VSX_MADD(xsmsubmdp, 1, float64, VsrD(0), MSUB_FLGS, 0, 1, 0)
|
||||
VSX_MADD(xsnmaddadp, 1, float64, VsrD(0), NMADD_FLGS, 1, 1, 0)
|
||||
VSX_MADD(xsnmaddmdp, 1, float64, VsrD(0), NMADD_FLGS, 0, 1, 0)
|
||||
VSX_MADD(xsnmsubadp, 1, float64, VsrD(0), NMSUB_FLGS, 1, 1, 0)
|
||||
VSX_MADD(xsnmsubmdp, 1, float64, VsrD(0), NMSUB_FLGS, 0, 1, 0)
|
||||
|
||||
VSX_MADD(xsmaddasp, 1, float64, f64, MADD_FLGS, 1, 1, 1)
|
||||
VSX_MADD(xsmaddmsp, 1, float64, f64, MADD_FLGS, 0, 1, 1)
|
||||
VSX_MADD(xsmsubasp, 1, float64, f64, MSUB_FLGS, 1, 1, 1)
|
||||
VSX_MADD(xsmsubmsp, 1, float64, f64, MSUB_FLGS, 0, 1, 1)
|
||||
VSX_MADD(xsnmaddasp, 1, float64, f64, NMADD_FLGS, 1, 1, 1)
|
||||
VSX_MADD(xsnmaddmsp, 1, float64, f64, NMADD_FLGS, 0, 1, 1)
|
||||
VSX_MADD(xsnmsubasp, 1, float64, f64, NMSUB_FLGS, 1, 1, 1)
|
||||
VSX_MADD(xsnmsubmsp, 1, float64, f64, NMSUB_FLGS, 0, 1, 1)
|
||||
VSX_MADD(xsmaddasp, 1, float64, VsrD(0), MADD_FLGS, 1, 1, 1)
|
||||
VSX_MADD(xsmaddmsp, 1, float64, VsrD(0), MADD_FLGS, 0, 1, 1)
|
||||
VSX_MADD(xsmsubasp, 1, float64, VsrD(0), MSUB_FLGS, 1, 1, 1)
|
||||
VSX_MADD(xsmsubmsp, 1, float64, VsrD(0), MSUB_FLGS, 0, 1, 1)
|
||||
VSX_MADD(xsnmaddasp, 1, float64, VsrD(0), NMADD_FLGS, 1, 1, 1)
|
||||
VSX_MADD(xsnmaddmsp, 1, float64, VsrD(0), NMADD_FLGS, 0, 1, 1)
|
||||
VSX_MADD(xsnmsubasp, 1, float64, VsrD(0), NMSUB_FLGS, 1, 1, 1)
|
||||
VSX_MADD(xsnmsubmsp, 1, float64, VsrD(0), NMSUB_FLGS, 0, 1, 1)
|
||||
|
||||
VSX_MADD(xvmaddadp, 2, float64, f64, MADD_FLGS, 1, 0, 0)
|
||||
VSX_MADD(xvmaddmdp, 2, float64, f64, MADD_FLGS, 0, 0, 0)
|
||||
VSX_MADD(xvmsubadp, 2, float64, f64, MSUB_FLGS, 1, 0, 0)
|
||||
VSX_MADD(xvmsubmdp, 2, float64, f64, MSUB_FLGS, 0, 0, 0)
|
||||
VSX_MADD(xvnmaddadp, 2, float64, f64, NMADD_FLGS, 1, 0, 0)
|
||||
VSX_MADD(xvnmaddmdp, 2, float64, f64, NMADD_FLGS, 0, 0, 0)
|
||||
VSX_MADD(xvnmsubadp, 2, float64, f64, NMSUB_FLGS, 1, 0, 0)
|
||||
VSX_MADD(xvnmsubmdp, 2, float64, f64, NMSUB_FLGS, 0, 0, 0)
|
||||
VSX_MADD(xvmaddadp, 2, float64, VsrD(i), MADD_FLGS, 1, 0, 0)
|
||||
VSX_MADD(xvmaddmdp, 2, float64, VsrD(i), MADD_FLGS, 0, 0, 0)
|
||||
VSX_MADD(xvmsubadp, 2, float64, VsrD(i), MSUB_FLGS, 1, 0, 0)
|
||||
VSX_MADD(xvmsubmdp, 2, float64, VsrD(i), MSUB_FLGS, 0, 0, 0)
|
||||
VSX_MADD(xvnmaddadp, 2, float64, VsrD(i), NMADD_FLGS, 1, 0, 0)
|
||||
VSX_MADD(xvnmaddmdp, 2, float64, VsrD(i), NMADD_FLGS, 0, 0, 0)
|
||||
VSX_MADD(xvnmsubadp, 2, float64, VsrD(i), NMSUB_FLGS, 1, 0, 0)
|
||||
VSX_MADD(xvnmsubmdp, 2, float64, VsrD(i), NMSUB_FLGS, 0, 0, 0)
|
||||
|
||||
VSX_MADD(xvmaddasp, 4, float32, f32, MADD_FLGS, 1, 0, 0)
|
||||
VSX_MADD(xvmaddmsp, 4, float32, f32, MADD_FLGS, 0, 0, 0)
|
||||
VSX_MADD(xvmsubasp, 4, float32, f32, MSUB_FLGS, 1, 0, 0)
|
||||
VSX_MADD(xvmsubmsp, 4, float32, f32, MSUB_FLGS, 0, 0, 0)
|
||||
VSX_MADD(xvnmaddasp, 4, float32, f32, NMADD_FLGS, 1, 0, 0)
|
||||
VSX_MADD(xvnmaddmsp, 4, float32, f32, NMADD_FLGS, 0, 0, 0)
|
||||
VSX_MADD(xvnmsubasp, 4, float32, f32, NMSUB_FLGS, 1, 0, 0)
|
||||
VSX_MADD(xvnmsubmsp, 4, float32, f32, NMSUB_FLGS, 0, 0, 0)
|
||||
VSX_MADD(xvmaddasp, 4, float32, VsrW(i), MADD_FLGS, 1, 0, 0)
|
||||
VSX_MADD(xvmaddmsp, 4, float32, VsrW(i), MADD_FLGS, 0, 0, 0)
|
||||
VSX_MADD(xvmsubasp, 4, float32, VsrW(i), MSUB_FLGS, 1, 0, 0)
|
||||
VSX_MADD(xvmsubmsp, 4, float32, VsrW(i), MSUB_FLGS, 0, 0, 0)
|
||||
VSX_MADD(xvnmaddasp, 4, float32, VsrW(i), NMADD_FLGS, 1, 0, 0)
|
||||
VSX_MADD(xvnmaddmsp, 4, float32, VsrW(i), NMADD_FLGS, 0, 0, 0)
|
||||
VSX_MADD(xvnmsubasp, 4, float32, VsrW(i), NMSUB_FLGS, 1, 0, 0)
|
||||
VSX_MADD(xvnmsubmsp, 4, float32, VsrW(i), NMSUB_FLGS, 0, 0, 0)
|
||||
|
||||
#define VSX_SCALAR_CMP(op, ordered) \
|
||||
void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
||||
|
@ -2352,10 +2360,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
getVSR(xA(opcode), &xa, env); \
|
||||
getVSR(xB(opcode), &xb, env); \
|
||||
\
|
||||
if (unlikely(float64_is_any_nan(xa.f64[0]) || \
|
||||
float64_is_any_nan(xb.f64[0]))) { \
|
||||
if (float64_is_signaling_nan(xa.f64[0]) || \
|
||||
float64_is_signaling_nan(xb.f64[0])) { \
|
||||
if (unlikely(float64_is_any_nan(xa.VsrD(0)) || \
|
||||
float64_is_any_nan(xb.VsrD(0)))) { \
|
||||
if (float64_is_signaling_nan(xa.VsrD(0)) || \
|
||||
float64_is_signaling_nan(xb.VsrD(0))) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
|
||||
} \
|
||||
if (ordered) { \
|
||||
|
@ -2363,9 +2371,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
} \
|
||||
cc = 1; \
|
||||
} else { \
|
||||
if (float64_lt(xa.f64[0], xb.f64[0], &env->fp_status)) { \
|
||||
if (float64_lt(xa.VsrD(0), xb.VsrD(0), &env->fp_status)) { \
|
||||
cc = 8; \
|
||||
} else if (!float64_le(xa.f64[0], xb.f64[0], &env->fp_status)) { \
|
||||
} else if (!float64_le(xa.VsrD(0), xb.VsrD(0), \
|
||||
&env->fp_status)) { \
|
||||
cc = 4; \
|
||||
} else { \
|
||||
cc = 2; \
|
||||
|
@ -2390,7 +2399,7 @@ VSX_SCALAR_CMP(xscmpudp, 0)
|
|||
* op - operation (max or min)
|
||||
* nels - number of elements (1, 2 or 4)
|
||||
* tp - type (float32 or float64)
|
||||
* fld - vsr_t field (f32 or f64)
|
||||
* fld - vsr_t field (VsrD(*) or VsrW(*))
|
||||
*/
|
||||
#define VSX_MAX_MIN(name, op, nels, tp, fld) \
|
||||
void helper_##name(CPUPPCState *env, uint32_t opcode) \
|
||||
|
@ -2403,9 +2412,9 @@ void helper_##name(CPUPPCState *env, uint32_t opcode) \
|
|||
getVSR(xT(opcode), &xt, env); \
|
||||
\
|
||||
for (i = 0; i < nels; i++) { \
|
||||
xt.fld[i] = tp##_##op(xa.fld[i], xb.fld[i], &env->fp_status); \
|
||||
if (unlikely(tp##_is_signaling_nan(xa.fld[i]) || \
|
||||
tp##_is_signaling_nan(xb.fld[i]))) { \
|
||||
xt.fld = tp##_##op(xa.fld, xb.fld, &env->fp_status); \
|
||||
if (unlikely(tp##_is_signaling_nan(xa.fld) || \
|
||||
tp##_is_signaling_nan(xb.fld))) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
|
||||
} \
|
||||
} \
|
||||
|
@ -2414,18 +2423,18 @@ void helper_##name(CPUPPCState *env, uint32_t opcode) \
|
|||
helper_float_check_status(env); \
|
||||
}
|
||||
|
||||
VSX_MAX_MIN(xsmaxdp, maxnum, 1, float64, f64)
|
||||
VSX_MAX_MIN(xvmaxdp, maxnum, 2, float64, f64)
|
||||
VSX_MAX_MIN(xvmaxsp, maxnum, 4, float32, f32)
|
||||
VSX_MAX_MIN(xsmindp, minnum, 1, float64, f64)
|
||||
VSX_MAX_MIN(xvmindp, minnum, 2, float64, f64)
|
||||
VSX_MAX_MIN(xvminsp, minnum, 4, float32, f32)
|
||||
VSX_MAX_MIN(xsmaxdp, maxnum, 1, float64, VsrD(0))
|
||||
VSX_MAX_MIN(xvmaxdp, maxnum, 2, float64, VsrD(i))
|
||||
VSX_MAX_MIN(xvmaxsp, maxnum, 4, float32, VsrW(i))
|
||||
VSX_MAX_MIN(xsmindp, minnum, 1, float64, VsrD(0))
|
||||
VSX_MAX_MIN(xvmindp, minnum, 2, float64, VsrD(i))
|
||||
VSX_MAX_MIN(xvminsp, minnum, 4, float32, VsrW(i))
|
||||
|
||||
/* VSX_CMP - VSX floating point compare
|
||||
* op - instruction mnemonic
|
||||
* nels - number of elements (1, 2 or 4)
|
||||
* tp - type (float32 or float64)
|
||||
* fld - vsr_t field (f32 or f64)
|
||||
* fld - vsr_t field (VsrD(*) or VsrW(*))
|
||||
* cmp - comparison operation
|
||||
* svxvc - set VXVC bit
|
||||
*/
|
||||
|
@ -2442,23 +2451,23 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
getVSR(xT(opcode), &xt, env); \
|
||||
\
|
||||
for (i = 0; i < nels; i++) { \
|
||||
if (unlikely(tp##_is_any_nan(xa.fld[i]) || \
|
||||
tp##_is_any_nan(xb.fld[i]))) { \
|
||||
if (tp##_is_signaling_nan(xa.fld[i]) || \
|
||||
tp##_is_signaling_nan(xb.fld[i])) { \
|
||||
if (unlikely(tp##_is_any_nan(xa.fld) || \
|
||||
tp##_is_any_nan(xb.fld))) { \
|
||||
if (tp##_is_signaling_nan(xa.fld) || \
|
||||
tp##_is_signaling_nan(xb.fld)) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
|
||||
} \
|
||||
if (svxvc) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0); \
|
||||
} \
|
||||
xt.fld[i] = 0; \
|
||||
xt.fld = 0; \
|
||||
all_true = 0; \
|
||||
} else { \
|
||||
if (tp##_##cmp(xb.fld[i], xa.fld[i], &env->fp_status) == 1) { \
|
||||
xt.fld[i] = -1; \
|
||||
if (tp##_##cmp(xb.fld, xa.fld, &env->fp_status) == 1) { \
|
||||
xt.fld = -1; \
|
||||
all_false = 0; \
|
||||
} else { \
|
||||
xt.fld[i] = 0; \
|
||||
xt.fld = 0; \
|
||||
all_true = 0; \
|
||||
} \
|
||||
} \
|
||||
|
@ -2471,18 +2480,12 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
helper_float_check_status(env); \
|
||||
}
|
||||
|
||||
VSX_CMP(xvcmpeqdp, 2, float64, f64, eq, 0)
|
||||
VSX_CMP(xvcmpgedp, 2, float64, f64, le, 1)
|
||||
VSX_CMP(xvcmpgtdp, 2, float64, f64, lt, 1)
|
||||
VSX_CMP(xvcmpeqsp, 4, float32, f32, eq, 0)
|
||||
VSX_CMP(xvcmpgesp, 4, float32, f32, le, 1)
|
||||
VSX_CMP(xvcmpgtsp, 4, float32, f32, lt, 1)
|
||||
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
#define JOFFSET 0
|
||||
#else
|
||||
#define JOFFSET 1
|
||||
#endif
|
||||
VSX_CMP(xvcmpeqdp, 2, float64, VsrD(i), eq, 0)
|
||||
VSX_CMP(xvcmpgedp, 2, float64, VsrD(i), le, 1)
|
||||
VSX_CMP(xvcmpgtdp, 2, float64, VsrD(i), lt, 1)
|
||||
VSX_CMP(xvcmpeqsp, 4, float32, VsrW(i), eq, 0)
|
||||
VSX_CMP(xvcmpgesp, 4, float32, VsrW(i), le, 1)
|
||||
VSX_CMP(xvcmpgtsp, 4, float32, VsrW(i), lt, 1)
|
||||
|
||||
/* VSX_CVT_FP_TO_FP - VSX floating point/floating point conversion
|
||||
* op - instruction mnemonic
|
||||
|
@ -2503,7 +2506,6 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
getVSR(xT(opcode), &xt, env); \
|
||||
\
|
||||
for (i = 0; i < nels; i++) { \
|
||||
int j = 2*i + JOFFSET; \
|
||||
xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \
|
||||
if (unlikely(stp##_is_signaling_nan(xb.sfld))) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
|
||||
|
@ -2519,10 +2521,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
helper_float_check_status(env); \
|
||||
}
|
||||
|
||||
VSX_CVT_FP_TO_FP(xscvdpsp, 1, float64, float32, f64[i], f32[j], 1)
|
||||
VSX_CVT_FP_TO_FP(xscvspdp, 1, float32, float64, f32[j], f64[i], 1)
|
||||
VSX_CVT_FP_TO_FP(xvcvdpsp, 2, float64, float32, f64[i], f32[j], 0)
|
||||
VSX_CVT_FP_TO_FP(xvcvspdp, 2, float32, float64, f32[j], f64[i], 0)
|
||||
VSX_CVT_FP_TO_FP(xscvdpsp, 1, float64, float32, VsrD(0), VsrW(0), 1)
|
||||
VSX_CVT_FP_TO_FP(xscvspdp, 1, float32, float64, VsrW(0), VsrD(0), 1)
|
||||
VSX_CVT_FP_TO_FP(xvcvdpsp, 2, float64, float32, VsrD(i), VsrW(2*i), 0)
|
||||
VSX_CVT_FP_TO_FP(xvcvspdp, 2, float32, float64, VsrW(2*i), VsrD(i), 0)
|
||||
|
||||
uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb)
|
||||
{
|
||||
|
@ -2547,10 +2549,9 @@ uint64_t helper_xscvspdpn(CPUPPCState *env, uint64_t xb)
|
|||
* ttp - target type (int32, uint32, int64 or uint64)
|
||||
* sfld - source vsr_t field
|
||||
* tfld - target vsr_t field
|
||||
* jdef - definition of the j index (i or 2*i)
|
||||
* rnan - resulting NaN
|
||||
*/
|
||||
#define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, jdef, rnan) \
|
||||
#define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, rnan) \
|
||||
void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
||||
{ \
|
||||
ppc_vsr_t xt, xb; \
|
||||
|
@ -2560,7 +2561,6 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
getVSR(xT(opcode), &xt, env); \
|
||||
\
|
||||
for (i = 0; i < nels; i++) { \
|
||||
int j = jdef; \
|
||||
if (unlikely(stp##_is_any_nan(xb.sfld))) { \
|
||||
if (stp##_is_signaling_nan(xb.sfld)) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
|
||||
|
@ -2568,7 +2568,8 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0); \
|
||||
xt.tfld = rnan; \
|
||||
} else { \
|
||||
xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \
|
||||
xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld, \
|
||||
&env->fp_status); \
|
||||
if (env->fp_status.float_exception_flags & float_flag_invalid) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0); \
|
||||
} \
|
||||
|
@ -2579,27 +2580,23 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
helper_float_check_status(env); \
|
||||
}
|
||||
|
||||
VSX_CVT_FP_TO_INT(xscvdpsxds, 1, float64, int64, f64[j], u64[i], i, \
|
||||
VSX_CVT_FP_TO_INT(xscvdpsxds, 1, float64, int64, VsrD(0), VsrD(0), \
|
||||
0x8000000000000000ULL)
|
||||
VSX_CVT_FP_TO_INT(xscvdpsxws, 1, float64, int32, f64[i], u32[j], \
|
||||
2*i + JOFFSET, 0x80000000U)
|
||||
VSX_CVT_FP_TO_INT(xscvdpuxds, 1, float64, uint64, f64[j], u64[i], i, 0ULL)
|
||||
VSX_CVT_FP_TO_INT(xscvdpuxws, 1, float64, uint32, f64[i], u32[j], \
|
||||
2*i + JOFFSET, 0U)
|
||||
VSX_CVT_FP_TO_INT(xvcvdpsxds, 2, float64, int64, f64[j], u64[i], i, \
|
||||
0x8000000000000000ULL)
|
||||
VSX_CVT_FP_TO_INT(xvcvdpsxws, 2, float64, int32, f64[i], u32[j], \
|
||||
2*i + JOFFSET, 0x80000000U)
|
||||
VSX_CVT_FP_TO_INT(xvcvdpuxds, 2, float64, uint64, f64[j], u64[i], i, 0ULL)
|
||||
VSX_CVT_FP_TO_INT(xvcvdpuxws, 2, float64, uint32, f64[i], u32[j], \
|
||||
2*i + JOFFSET, 0U)
|
||||
VSX_CVT_FP_TO_INT(xvcvspsxds, 2, float32, int64, f32[j], u64[i], \
|
||||
2*i + JOFFSET, 0x8000000000000000ULL)
|
||||
VSX_CVT_FP_TO_INT(xvcvspsxws, 4, float32, int32, f32[j], u32[j], i, \
|
||||
VSX_CVT_FP_TO_INT(xscvdpsxws, 1, float64, int32, VsrD(0), VsrW(1), \
|
||||
0x80000000U)
|
||||
VSX_CVT_FP_TO_INT(xvcvspuxds, 2, float32, uint64, f32[j], u64[i], \
|
||||
2*i + JOFFSET, 0ULL)
|
||||
VSX_CVT_FP_TO_INT(xvcvspuxws, 4, float32, uint32, f32[j], u32[i], i, 0U)
|
||||
VSX_CVT_FP_TO_INT(xscvdpuxds, 1, float64, uint64, VsrD(0), VsrD(0), 0ULL)
|
||||
VSX_CVT_FP_TO_INT(xscvdpuxws, 1, float64, uint32, VsrD(0), VsrW(1), 0U)
|
||||
VSX_CVT_FP_TO_INT(xvcvdpsxds, 2, float64, int64, VsrD(i), VsrD(i), \
|
||||
0x8000000000000000ULL)
|
||||
VSX_CVT_FP_TO_INT(xvcvdpsxws, 2, float64, int32, VsrD(i), VsrW(2*i), \
|
||||
0x80000000U)
|
||||
VSX_CVT_FP_TO_INT(xvcvdpuxds, 2, float64, uint64, VsrD(i), VsrD(i), 0ULL)
|
||||
VSX_CVT_FP_TO_INT(xvcvdpuxws, 2, float64, uint32, VsrD(i), VsrW(2*i), 0U)
|
||||
VSX_CVT_FP_TO_INT(xvcvspsxds, 2, float32, int64, VsrW(2*i), VsrD(i), \
|
||||
0x8000000000000000ULL)
|
||||
VSX_CVT_FP_TO_INT(xvcvspsxws, 4, float32, int32, VsrW(i), VsrW(i), 0x80000000U)
|
||||
VSX_CVT_FP_TO_INT(xvcvspuxds, 2, float32, uint64, VsrW(2*i), VsrD(i), 0ULL)
|
||||
VSX_CVT_FP_TO_INT(xvcvspuxws, 4, float32, uint32, VsrW(i), VsrW(i), 0U)
|
||||
|
||||
/* VSX_CVT_INT_TO_FP - VSX integer to floating point conversion
|
||||
* op - instruction mnemonic
|
||||
|
@ -2611,7 +2608,7 @@ VSX_CVT_FP_TO_INT(xvcvspuxws, 4, float32, uint32, f32[j], u32[i], i, 0U)
|
|||
* jdef - definition of the j index (i or 2*i)
|
||||
* sfprf - set FPRF
|
||||
*/
|
||||
#define VSX_CVT_INT_TO_FP(op, nels, stp, ttp, sfld, tfld, jdef, sfprf, r2sp) \
|
||||
#define VSX_CVT_INT_TO_FP(op, nels, stp, ttp, sfld, tfld, sfprf, r2sp) \
|
||||
void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
||||
{ \
|
||||
ppc_vsr_t xt, xb; \
|
||||
|
@ -2621,7 +2618,6 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
getVSR(xT(opcode), &xt, env); \
|
||||
\
|
||||
for (i = 0; i < nels; i++) { \
|
||||
int j = jdef; \
|
||||
xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \
|
||||
if (r2sp) { \
|
||||
xt.tfld = helper_frsp(env, xt.tfld); \
|
||||
|
@ -2635,22 +2631,18 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
helper_float_check_status(env); \
|
||||
}
|
||||
|
||||
VSX_CVT_INT_TO_FP(xscvsxddp, 1, int64, float64, u64[j], f64[i], i, 1, 0)
|
||||
VSX_CVT_INT_TO_FP(xscvuxddp, 1, uint64, float64, u64[j], f64[i], i, 1, 0)
|
||||
VSX_CVT_INT_TO_FP(xscvsxdsp, 1, int64, float64, u64[j], f64[i], i, 1, 1)
|
||||
VSX_CVT_INT_TO_FP(xscvuxdsp, 1, uint64, float64, u64[j], f64[i], i, 1, 1)
|
||||
VSX_CVT_INT_TO_FP(xvcvsxddp, 2, int64, float64, u64[j], f64[i], i, 0, 0)
|
||||
VSX_CVT_INT_TO_FP(xvcvuxddp, 2, uint64, float64, u64[j], f64[i], i, 0, 0)
|
||||
VSX_CVT_INT_TO_FP(xvcvsxwdp, 2, int32, float64, u32[j], f64[i], \
|
||||
2*i + JOFFSET, 0, 0)
|
||||
VSX_CVT_INT_TO_FP(xvcvuxwdp, 2, uint64, float64, u32[j], f64[i], \
|
||||
2*i + JOFFSET, 0, 0)
|
||||
VSX_CVT_INT_TO_FP(xvcvsxdsp, 2, int64, float32, u64[i], f32[j], \
|
||||
2*i + JOFFSET, 0, 0)
|
||||
VSX_CVT_INT_TO_FP(xvcvuxdsp, 2, uint64, float32, u64[i], f32[j], \
|
||||
2*i + JOFFSET, 0, 0)
|
||||
VSX_CVT_INT_TO_FP(xvcvsxwsp, 4, int32, float32, u32[j], f32[i], i, 0, 0)
|
||||
VSX_CVT_INT_TO_FP(xvcvuxwsp, 4, uint32, float32, u32[j], f32[i], i, 0, 0)
|
||||
VSX_CVT_INT_TO_FP(xscvsxddp, 1, int64, float64, VsrD(0), VsrD(0), 1, 0)
|
||||
VSX_CVT_INT_TO_FP(xscvuxddp, 1, uint64, float64, VsrD(0), VsrD(0), 1, 0)
|
||||
VSX_CVT_INT_TO_FP(xscvsxdsp, 1, int64, float64, VsrD(0), VsrD(0), 1, 1)
|
||||
VSX_CVT_INT_TO_FP(xscvuxdsp, 1, uint64, float64, VsrD(0), VsrD(0), 1, 1)
|
||||
VSX_CVT_INT_TO_FP(xvcvsxddp, 2, int64, float64, VsrD(i), VsrD(i), 0, 0)
|
||||
VSX_CVT_INT_TO_FP(xvcvuxddp, 2, uint64, float64, VsrD(i), VsrD(i), 0, 0)
|
||||
VSX_CVT_INT_TO_FP(xvcvsxwdp, 2, int32, float64, VsrW(2*i), VsrD(i), 0, 0)
|
||||
VSX_CVT_INT_TO_FP(xvcvuxwdp, 2, uint64, float64, VsrW(2*i), VsrD(i), 0, 0)
|
||||
VSX_CVT_INT_TO_FP(xvcvsxdsp, 2, int64, float32, VsrD(i), VsrW(2*i), 0, 0)
|
||||
VSX_CVT_INT_TO_FP(xvcvuxdsp, 2, uint64, float32, VsrD(i), VsrW(2*i), 0, 0)
|
||||
VSX_CVT_INT_TO_FP(xvcvsxwsp, 4, int32, float32, VsrW(i), VsrW(i), 0, 0)
|
||||
VSX_CVT_INT_TO_FP(xvcvuxwsp, 4, uint32, float32, VsrW(i), VsrW(i), 0, 0)
|
||||
|
||||
/* For "use current rounding mode", define a value that will not be one of
|
||||
* the existing rounding model enums.
|
||||
|
@ -2662,7 +2654,7 @@ VSX_CVT_INT_TO_FP(xvcvuxwsp, 4, uint32, float32, u32[j], f32[i], i, 0, 0)
|
|||
* op - instruction mnemonic
|
||||
* nels - number of elements (1, 2 or 4)
|
||||
* tp - type (float32 or float64)
|
||||
* fld - vsr_t field (f32 or f64)
|
||||
* fld - vsr_t field (VsrD(*) or VsrW(*))
|
||||
* rmode - rounding mode
|
||||
* sfprf - set FPRF
|
||||
*/
|
||||
|
@ -2679,14 +2671,14 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
} \
|
||||
\
|
||||
for (i = 0; i < nels; i++) { \
|
||||
if (unlikely(tp##_is_signaling_nan(xb.fld[i]))) { \
|
||||
if (unlikely(tp##_is_signaling_nan(xb.fld))) { \
|
||||
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
|
||||
xt.fld[i] = tp##_snan_to_qnan(xb.fld[i]); \
|
||||
xt.fld = tp##_snan_to_qnan(xb.fld); \
|
||||
} else { \
|
||||
xt.fld[i] = tp##_round_to_int(xb.fld[i], &env->fp_status); \
|
||||
xt.fld = tp##_round_to_int(xb.fld, &env->fp_status); \
|
||||
} \
|
||||
if (sfprf) { \
|
||||
helper_compute_fprf(env, xt.fld[i], sfprf); \
|
||||
helper_compute_fprf(env, xt.fld, sfprf); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
|
@ -2702,23 +2694,23 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
|
|||
helper_float_check_status(env); \
|
||||
}
|
||||
|
||||
VSX_ROUND(xsrdpi, 1, float64, f64, float_round_nearest_even, 1)
|
||||
VSX_ROUND(xsrdpic, 1, float64, f64, FLOAT_ROUND_CURRENT, 1)
|
||||
VSX_ROUND(xsrdpim, 1, float64, f64, float_round_down, 1)
|
||||
VSX_ROUND(xsrdpip, 1, float64, f64, float_round_up, 1)
|
||||
VSX_ROUND(xsrdpiz, 1, float64, f64, float_round_to_zero, 1)
|
||||
VSX_ROUND(xsrdpi, 1, float64, VsrD(0), float_round_nearest_even, 1)
|
||||
VSX_ROUND(xsrdpic, 1, float64, VsrD(0), FLOAT_ROUND_CURRENT, 1)
|
||||
VSX_ROUND(xsrdpim, 1, float64, VsrD(0), float_round_down, 1)
|
||||
VSX_ROUND(xsrdpip, 1, float64, VsrD(0), float_round_up, 1)
|
||||
VSX_ROUND(xsrdpiz, 1, float64, VsrD(0), float_round_to_zero, 1)
|
||||
|
||||
VSX_ROUND(xvrdpi, 2, float64, f64, float_round_nearest_even, 0)
|
||||
VSX_ROUND(xvrdpic, 2, float64, f64, FLOAT_ROUND_CURRENT, 0)
|
||||
VSX_ROUND(xvrdpim, 2, float64, f64, float_round_down, 0)
|
||||
VSX_ROUND(xvrdpip, 2, float64, f64, float_round_up, 0)
|
||||
VSX_ROUND(xvrdpiz, 2, float64, f64, float_round_to_zero, 0)
|
||||
VSX_ROUND(xvrdpi, 2, float64, VsrD(i), float_round_nearest_even, 0)
|
||||
VSX_ROUND(xvrdpic, 2, float64, VsrD(i), FLOAT_ROUND_CURRENT, 0)
|
||||
VSX_ROUND(xvrdpim, 2, float64, VsrD(i), float_round_down, 0)
|
||||
VSX_ROUND(xvrdpip, 2, float64, VsrD(i), float_round_up, 0)
|
||||
VSX_ROUND(xvrdpiz, 2, float64, VsrD(i), float_round_to_zero, 0)
|
||||
|
||||
VSX_ROUND(xvrspi, 4, float32, f32, float_round_nearest_even, 0)
|
||||
VSX_ROUND(xvrspic, 4, float32, f32, FLOAT_ROUND_CURRENT, 0)
|
||||
VSX_ROUND(xvrspim, 4, float32, f32, float_round_down, 0)
|
||||
VSX_ROUND(xvrspip, 4, float32, f32, float_round_up, 0)
|
||||
VSX_ROUND(xvrspiz, 4, float32, f32, float_round_to_zero, 0)
|
||||
VSX_ROUND(xvrspi, 4, float32, VsrW(i), float_round_nearest_even, 0)
|
||||
VSX_ROUND(xvrspic, 4, float32, VsrW(i), FLOAT_ROUND_CURRENT, 0)
|
||||
VSX_ROUND(xvrspim, 4, float32, VsrW(i), float_round_down, 0)
|
||||
VSX_ROUND(xvrspip, 4, float32, VsrW(i), float_round_up, 0)
|
||||
VSX_ROUND(xvrspiz, 4, float32, VsrW(i), float_round_to_zero, 0)
|
||||
|
||||
uint64_t helper_xsrsp(CPUPPCState *env, uint64_t xb)
|
||||
{
|
||||
|
|
|
@ -101,7 +101,7 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
|
|||
hreg_compute_hflags(env);
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
if (unlikely(msr_pow == 1)) {
|
||||
if ((*env->check_pow)(env)) {
|
||||
if (!env->pending_interrupts && (*env->check_pow)(env)) {
|
||||
cs->halted = 1;
|
||||
excp = EXCP_HALTED;
|
||||
}
|
||||
|
|
|
@ -6699,6 +6699,8 @@ POWERPC_FAMILY(970)(ObjectClass *oc, void *data)
|
|||
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
|
||||
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
|
||||
POWERPC_FLAG_BUS_CLK;
|
||||
pcc->l1_dcache_size = 0x8000;
|
||||
pcc->l1_icache_size = 0x10000;
|
||||
}
|
||||
|
||||
static int check_pow_970FX (CPUPPCState *env)
|
||||
|
@ -6791,6 +6793,8 @@ POWERPC_FAMILY(970FX)(ObjectClass *oc, void *data)
|
|||
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
|
||||
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
|
||||
POWERPC_FLAG_BUS_CLK;
|
||||
pcc->l1_dcache_size = 0x8000;
|
||||
pcc->l1_icache_size = 0x10000;
|
||||
}
|
||||
|
||||
static int check_pow_970MP (CPUPPCState *env)
|
||||
|
@ -6877,6 +6881,8 @@ POWERPC_FAMILY(970MP)(ObjectClass *oc, void *data)
|
|||
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
|
||||
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
|
||||
POWERPC_FLAG_BUS_CLK;
|
||||
pcc->l1_dcache_size = 0x8000;
|
||||
pcc->l1_icache_size = 0x10000;
|
||||
}
|
||||
|
||||
static void init_proc_power5plus(CPUPPCState *env)
|
||||
|
@ -6967,6 +6973,8 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
|
|||
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
|
||||
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
|
||||
POWERPC_FLAG_BUS_CLK;
|
||||
pcc->l1_dcache_size = 0x8000;
|
||||
pcc->l1_icache_size = 0x10000;
|
||||
}
|
||||
|
||||
static void init_proc_POWER7 (CPUPPCState *env)
|
||||
|
|
Loading…
Reference in New Issue