e2k: Use %pfpfr for f32 and f64 operations.

%fpcr and %fpsr have been used for the operations but
%pfpfr must be used instead.

Signed-off-by: Denis Drakhnya <numas13@gmail.com>
This commit is contained in:
Denis Drakhnia 2021-02-22 16:05:10 +02:00 committed by Denis Drakhnia
parent cd6c5f262f
commit bed634d944
7 changed files with 186 additions and 144 deletions

View File

@ -156,7 +156,7 @@ static abi_long setup_sigcontext(CPUE2KState *env,
__put_user(env->fpcr.raw, &extra->fpcr);
__put_user(env->fpsr.raw, &extra->fpsr);
__put_user(env->pfpfr, &extra->pfpfr);
__put_user(env->pfpfr.raw, &extra->pfpfr);
__put_user(env->ctprs[0].raw, &extra->ctpr1);
__put_user(env->ctprs[1].raw, &extra->ctpr2);

View File

@ -55,8 +55,11 @@ static void e2k_cpu_reset(DeviceState *dev)
env->aau.incrs[0] = 1; /* always one */
env->fpcr._one = 1;
env->fpcr.pc = FPCR_PC_XP;
env->fpcr.em = FP_EM;
env->pfpfr.em = FP_EM;
e2k_update_fp_status(env);
e2k_update_fx_status(env);
// FIXME: testing
env->idr = 0x3a207; /* mimic 8c */

View File

@ -583,12 +583,12 @@ typedef union {
} E2KCtpr;
/* E2K FPU regs are compatible with x87 regs */
#define FPSR_IE (1U << 0) /* invalid operation */
#define FPSR_DE (1U << 1) /* denormalized operand */
#define FPSR_ZE (1U << 2) /* zero divide */
#define FPSR_OE (1U << 3) /* overflow */
#define FPSR_UE (1U << 4) /* underflow */
#define FPSR_PE (1U << 5) /* precision */
#define FP_IE (1U << 0) /* invalid operation */
#define FP_DE (1U << 1) /* denormalized operand */
#define FP_ZE (1U << 2) /* zero divide */
#define FP_OE (1U << 3) /* overflow */
#define FP_UE (1U << 4) /* underflow */
#define FP_PE (1U << 5) /* precision */
typedef union {
struct {
@ -605,17 +605,17 @@ typedef union {
uint32_t raw;
} E2KFpsrState;
#define FPCR_EM (FPSR_IE|FPSR_DE|FPSR_ZE|FPSR_OE|FPSR_UE|FPSR_PE)
#define FP_EM (FP_IE|FP_DE|FP_ZE|FP_OE|FP_UE|FP_PE)
#define FPCR_PC_SP 0 /* single precision (32 bits) */
#define FPCR_PC_RESERVED 1 /* reserved */
#define FPCR_PC_DP 2 /* double precision (64 bits) */
#define FPCR_PC_XP 3 /* extended precision (80 bits) */
#define FPCR_RC_NEAR 0 /* round to nearest */
#define FPCR_RC_DOWN 1 /* round down */
#define FPCR_RC_UP 2 /* round up */
#define FPCR_RC_CHOP 3 /* round toward zero (truncate) */
#define FP_RC_NEAR 0 /* round to nearest */
#define FP_RC_DOWN 1 /* round down */
#define FP_RC_UP 2 /* round up */
#define FP_RC_CHOP 3 /* round toward zero (truncate) */
typedef union {
struct {
@ -630,6 +630,22 @@ typedef union {
uint32_t raw;
} E2KFpcrState;
/*
* Packed Floating Point Flag Register (PFPFR)
*/
typedef union {
struct {
uint32_t ef: 6; /* 5:0 */
uint32_t zero1: 1; /* 6 */
uint32_t em: 6; /* 12:7 */
uint32_t rc: 2; /* 14:13 */
uint32_t fz: 1; /* 15 */
uint32_t zero2: 10; /* 25:16 */
uint32_t dm: 6; /* 31:26 */
};
uint32_t raw;
} E2KPfpfr;
typedef struct {
union {
uint64_t lo;
@ -725,11 +741,12 @@ typedef struct CPUArchState {
uint64_t upsr;
uint64_t idr;
uint32_t pfpfr; // Packed Floating Point Flag Register (PFPFR)
E2KPfpfr pfpfr; // Packed Floating Point Flag Register (PFPFR)
E2KFpsrState fpsr; // Floating point state register (FPSR)
E2KFpcrState fpcr; // Floating point control register (FPCR)
float_status fp_status;
float_status fx_status;
E2KAauState aau;
@ -793,6 +810,7 @@ bool e2k_cpu_tlb_fill(CPUState *cpu, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
void e2k_update_fp_status(CPUE2KState *env);
void e2k_update_fx_status(CPUE2KState *env);
void e2k_pcs_new(E2KPcsState *pcs);
void e2k_ps_new(E2KPsState *ps);

View File

@ -29,6 +29,11 @@
#include "cpu.h"
#include "exec/exec-all.h"
#define glue3(x, y, z) glue(glue(x, y), z)
#define glue4(x, y, z, w) glue(glue3(x, y, z), w)
#define deref(x) *(x)
#define ident(x) (x)
/* helper.c */
void G_NORETURN raise_exception(CPUE2KState *env, int exception_index);
void G_NORETURN raise_exception_ra(CPUE2KState *env, int exception_index,

View File

@ -1,68 +1,61 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "cpu.h"
#include "helper-tcg.h"
#include "exec/exec-all.h"
#include "qemu/host-utils.h"
#include "exec/helper-proto.h"
#define glue3(x, y, z) glue(glue(x, y), z)
#define glue4(x, y, z, w) glue(glue3(x, y, z), w)
#define deref(x) *(x)
#define no_cvt(x) (x) /* when in correct type */
static FloatRoundMode rm[] = {
float_round_nearest_even,
float_round_down,
float_round_up,
float_round_to_zero,
};
static inline void fpu_set_exception(CPUE2KState *env, int mask)
static inline int fpu_flags(int flags)
{
env->fpsr.ef |= mask;
if (env->fpsr.ef & (~env->fpcr.em & FPCR_EM)) {
return (flags & float_flag_invalid ? FP_IE : 0) |
(flags & float_flag_divbyzero ? FP_ZE : 0) |
(flags & float_flag_overflow ? FP_OE : 0) |
(flags & float_flag_underflow ? FP_UE : 0) |
(flags & float_flag_inexact ? FP_PE : 0) |
(flags & float_flag_input_denormal ? FP_DE : 0);
}
static inline void fx_merge_exception_flags(CPUE2KState *env, int old_flags)
{
int new_flags = get_float_exception_flags(&env->fx_status);
float_raise(old_flags, &env->fx_status);
env->fpsr.ef |= fpu_flags(new_flags);
if (env->fpsr.ef & (~env->fpcr.em & FP_EM)) {
env->fpsr.es = 1;
env->fpsr.b = 1;
}
}
static inline int save_exception_flags(CPUE2KState *env)
static inline void fp_merge_exception_flags(CPUE2KState *env, int old_flags)
{
int old_flags = get_float_exception_flags(&env->fp_status);
set_float_exception_flags(0, &env->fp_status);
int new_flags = get_float_exception_flags(&env->fp_status);
float_raise(old_flags, &env->fp_status);
env->pfpfr.ef |= fpu_flags(new_flags);
}
static inline int save_exception_flags(float_status *s)
{
int old_flags = get_float_exception_flags(s);
set_float_exception_flags(0, s);
return old_flags;
}
static inline void merge_exception_flags(CPUE2KState *env, int old_flags)
{
int new_flags = get_float_exception_flags(&env->fp_status);
float_raise((uint8_t)old_flags, &env->fp_status);
fpu_set_exception(env,
((new_flags & float_flag_invalid ? FPSR_IE : 0) |
(new_flags & float_flag_divbyzero ? FPSR_ZE : 0) |
(new_flags & float_flag_overflow ? FPSR_OE : 0) |
(new_flags & float_flag_underflow ? FPSR_UE : 0) |
(new_flags & float_flag_inexact ? FPSR_PE : 0) |
(new_flags & float_flag_input_denormal ? FPSR_DE : 0)));
}
#define fx_save_exception_flags(e) save_exception_flags(&(e)->fx_status)
#define fp_save_exception_flags(e) save_exception_flags(&(e)->fp_status)
void e2k_update_fp_status(CPUE2KState *env)
void e2k_update_fx_status(CPUE2KState *env)
{
FloatRoundMode rm;
int x;
switch(env->fpcr.rc) {
case FPCR_RC_UP:
rm = float_round_up;
break;
case FPCR_RC_DOWN:
rm = float_round_down;
break;
case FPCR_RC_CHOP:
rm = float_round_to_zero;
break;
case FPCR_RC_NEAR:
rm = float_round_nearest_even;
break;
default:
qemu_log_mask(LOG_UNIMP, "unknown rounding mode 0x%x\n", env->fpcr.rc);
abort();
}
set_float_rounding_mode(rm, &env->fp_status);
set_float_rounding_mode(rm[env->fpcr.rc], &env->fx_status);
switch(env->fpcr.pc) {
case FPCR_PC_XP: x = floatx80_precision_x; break;
@ -74,15 +67,20 @@ void e2k_update_fp_status(CPUE2KState *env)
abort();
}
set_floatx80_rounding_precision(x, &env->fp_status);
set_floatx80_rounding_precision(x, &env->fx_status);
}
void e2k_update_fp_status(CPUE2KState *env)
{
set_float_rounding_mode(rm[env->pfpfr.rc], &env->fp_status);
}
#define GENERATE_SIMPLE_FLOAT2_OP(name, function, size) \
uint##size##_t HELPER(name)(CPUE2KState *env, uint##size##_t x, uint##size##_t y) \
{ \
int old_flags = save_exception_flags(env); \
int old_flags = fp_save_exception_flags(env); \
float##size z = float##size##_##function (make_float##size (x), make_float##size (y), &env->fp_status); \
merge_exception_flags(env, old_flags); \
fp_merge_exception_flags(env, old_flags); \
return float##size##_val(z); \
}
@ -93,23 +91,41 @@ void e2k_update_fp_status(CPUE2KState *env)
#define GENERATE_CMP_FLOAT2_OP(ret_type, name, expr, op, in_type, cvt_macro) \
ret_type HELPER(name)(CPUE2KState *env, in_type x, in_type y) \
{ \
int old_flags = save_exception_flags(env); \
int old_flags = fp_save_exception_flags(env); \
ret_type z = expr op(cvt_macro(x), cvt_macro(y), &env->fp_status); \
merge_exception_flags(env, old_flags); \
fp_merge_exception_flags(env, old_flags); \
return z ? -1 : 0; \
}
#define GENERATE_CMP_XFLOAT2_OP(ret_type, name, expr, op, in_type, cvt_macro) \
ret_type HELPER(name)(CPUE2KState *env, in_type x, in_type y) \
{ \
int old_flags = fx_save_exception_flags(env); \
ret_type z = expr op(cvt_macro(x), cvt_macro(y), &env->fx_status); \
fx_merge_exception_flags(env, old_flags); \
return z ? -1 : 0; \
}
#define GENERATE_CMP_FLOAT2_OPS_32_64_80(name, expr, op) \
GENERATE_CMP_FLOAT2_OP(uint32_t, glue3(f, name, s), expr, glue(float32_, op), uint32_t, make_float32) \
GENERATE_CMP_FLOAT2_OP(uint64_t, glue3(f, name, d), expr, glue(float64_, op), uint64_t, make_float32) \
GENERATE_CMP_FLOAT2_OP(uint64_t, glue3(fx, name, x), expr, glue(floatx80_, op), floatx80*, deref)
GENERATE_CMP_XFLOAT2_OP(uint64_t, glue3(fx, name, x), expr, glue(floatx80_, op), floatx80*, deref)
#define GENERATE_CVT_FLOAT1_OP(name, from_t, to_t, size_from, size_to, func_from, func_to) \
size_to HELPER(name)(CPUE2KState *env, size_from x) \
{\
int old_flags = save_exception_flags(env); \
int old_flags = fp_save_exception_flags(env); \
size_to z = func_to( glue3(from_t, _to_, to_t) (func_from(x), &env->fp_status) );\
merge_exception_flags(env, old_flags); \
fp_merge_exception_flags(env, old_flags); \
return z; \
}
#define GENERATE_CVT_XFLOAT1_OP(name, from_t, to_t, size_from, size_to, func_from, func_to) \
size_to HELPER(name)(CPUE2KState *env, size_from x) \
{\
int old_flags = fx_save_exception_flags(env); \
size_to z = func_to( glue3(from_t, _to_, to_t) (func_from(x), &env->fx_status) );\
fx_merge_exception_flags(env, old_flags); \
return z; \
}
@ -128,66 +144,66 @@ GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpnlt, !, lt)
GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpuod, , unordered)
GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpod, !, unordered)
GENERATE_CVT_FLOAT1_OP(fstois, float32, int32, uint32_t, uint32_t, make_float32, no_cvt)
GENERATE_CVT_FLOAT1_OP(istofs, int32, float32, uint32_t, uint32_t, no_cvt, float32_val)
GENERATE_CVT_FLOAT1_OP(fstoistr, float32, int32_round_to_zero, uint32_t, uint32_t, make_float32, no_cvt)
GENERATE_CVT_FLOAT1_OP(fstois, float32, int32, uint32_t, uint32_t, make_float32, ident)
GENERATE_CVT_FLOAT1_OP(istofs, int32, float32, uint32_t, uint32_t, ident, float32_val)
GENERATE_CVT_FLOAT1_OP(fstoistr, float32, int32_round_to_zero, uint32_t, uint32_t, make_float32, ident)
GENERATE_CVT_FLOAT1_OP(fdtoid, float64, int64, uint64_t, uint64_t, make_float64, no_cvt)
GENERATE_CVT_FLOAT1_OP(idtofd, int64, float64, uint64_t, uint64_t, no_cvt, float64_val)
GENERATE_CVT_FLOAT1_OP(fdtoidtr, float64, int64_round_to_zero, uint64_t, uint64_t, make_float64, no_cvt)
GENERATE_CVT_FLOAT1_OP(fdtoid, float64, int64, uint64_t, uint64_t, make_float64, ident)
GENERATE_CVT_FLOAT1_OP(idtofd, int64, float64, uint64_t, uint64_t, ident, float64_val)
GENERATE_CVT_FLOAT1_OP(fdtoidtr, float64, int64_round_to_zero, uint64_t, uint64_t, make_float64, ident)
GENERATE_CVT_FLOAT1_OP(fstofd, float32, float64, uint32_t, uint64_t, make_float32, float64_val)
GENERATE_CVT_FLOAT1_OP(fstoid, float32, int64, uint32_t, uint64_t, make_float32, no_cvt)
GENERATE_CVT_FLOAT1_OP(istofd, int32, float64, uint32_t, uint64_t, no_cvt, float64_val)
GENERATE_CVT_FLOAT1_OP(fstoidtr, float32, int64_round_to_zero, uint32_t, uint64_t, make_float32, no_cvt)
GENERATE_CVT_FLOAT1_OP(fstoid, float32, int64, uint32_t, uint64_t, make_float32, ident)
GENERATE_CVT_FLOAT1_OP(istofd, int32, float64, uint32_t, uint64_t, ident, float64_val)
GENERATE_CVT_FLOAT1_OP(fstoidtr, float32, int64_round_to_zero, uint32_t, uint64_t, make_float32, ident)
GENERATE_CVT_FLOAT1_OP(fdtofs, float64, float32, uint64_t, uint32_t, make_float64, float32_val)
GENERATE_CVT_FLOAT1_OP(fdtois, float64, int32, uint64_t, uint32_t, make_float64, no_cvt)
GENERATE_CVT_FLOAT1_OP(idtofs, int64, float32, uint64_t, uint32_t, no_cvt, float32_val)
GENERATE_CVT_FLOAT1_OP(fdtoistr, float64, int32_round_to_zero, uint64_t, uint32_t, make_float64, no_cvt)
GENERATE_CVT_FLOAT1_OP(fdtois, float64, int32, uint64_t, uint32_t, make_float64, ident)
GENERATE_CVT_FLOAT1_OP(idtofs, int64, float32, uint64_t, uint32_t, ident, float32_val)
GENERATE_CVT_FLOAT1_OP(fdtoistr, float64, int32_round_to_zero, uint64_t, uint32_t, make_float64, ident)
GENERATE_CVT_FLOAT1_OP(fxtofs, floatx80, float32, floatx80*, uint32_t, deref, float32_val)
GENERATE_CVT_FLOAT1_OP(fxtois, floatx80, int32, floatx80*, uint32_t, deref, no_cvt)
GENERATE_CVT_FLOAT1_OP(fxtoistr, floatx80, int32_round_to_zero, floatx80*, uint32_t, deref, no_cvt)
GENERATE_CVT_XFLOAT1_OP(fxtofs, floatx80, float32, floatx80*, uint32_t, deref, float32_val)
GENERATE_CVT_XFLOAT1_OP(fxtois, floatx80, int32, floatx80*, uint32_t, deref, ident)
GENERATE_CVT_XFLOAT1_OP(fxtoistr, floatx80, int32_round_to_zero, floatx80*, uint32_t, deref, ident)
GENERATE_CVT_FLOAT1_OP(fxtofd, floatx80, float64, floatx80*, uint64_t, deref, float64_val)
GENERATE_CVT_FLOAT1_OP(fxtoid, floatx80, int64, floatx80*, uint64_t, deref, no_cvt)
GENERATE_CVT_FLOAT1_OP(fxtoidtr, floatx80, int64_round_to_zero, floatx80*, uint64_t, deref, no_cvt)
GENERATE_CVT_XFLOAT1_OP(fxtofd, floatx80, float64, floatx80*, uint64_t, deref, float64_val)
GENERATE_CVT_XFLOAT1_OP(fxtoid, floatx80, int64, floatx80*, uint64_t, deref, ident)
GENERATE_CVT_XFLOAT1_OP(fxtoidtr, floatx80, int64_round_to_zero, floatx80*, uint64_t, deref, ident)
void HELPER(fstofx)(floatx80 *ret, CPUE2KState *env, uint32_t x)
{
int old_flags = save_exception_flags(env);
int old_flags = fp_save_exception_flags(env);
*ret = float32_to_floatx80(make_float32(x), &env->fp_status);
merge_exception_flags(env, old_flags);
fp_merge_exception_flags(env, old_flags);
}
void HELPER(fdtofx)(floatx80 *ret, CPUE2KState *env, uint64_t x)
{
int old_flags = save_exception_flags(env);
int old_flags = fp_save_exception_flags(env);
*ret = float64_to_floatx80(make_float64(x), &env->fp_status);
merge_exception_flags(env, old_flags);
fp_merge_exception_flags(env, old_flags);
}
void HELPER(istofx)(floatx80 *ret, CPUE2KState *env, uint32_t x)
{
int old_flags = save_exception_flags(env);
*ret = int32_to_floatx80(no_cvt(x), &env->fp_status);
merge_exception_flags(env, old_flags);
int old_flags = fx_save_exception_flags(env);
*ret = int32_to_floatx80(x, &env->fx_status);
fx_merge_exception_flags(env, old_flags);
}
void HELPER(idtofx)(floatx80 *ret, CPUE2KState *env, uint64_t x)
{
int old_flags = save_exception_flags(env);
*ret = int64_to_floatx80(no_cvt(x), &env->fp_status);
merge_exception_flags(env, old_flags);
int old_flags = fx_save_exception_flags(env);
*ret = int64_to_floatx80(x, &env->fx_status);
fx_merge_exception_flags(env, old_flags);
}
#define GEN_OP2_XX(name, op) \
void HELPER(name)(CPUE2KState *env, floatx80 *x, floatx80 *y) \
{ \
int old_flags = save_exception_flags(env); \
*x = glue(floatx80_, op)(*x, *y, &env->fp_status); \
merge_exception_flags(env, old_flags); \
int old_flags = fx_save_exception_flags(env); \
*x = glue(floatx80_, op)(*x, *y, &env->fx_status); \
fx_merge_exception_flags(env, old_flags); \
}
GEN_OP2_XX(fxaddxx, add)
@ -197,22 +213,22 @@ GEN_OP2_XX(fxdivxx, div)
void HELPER(fxrsubxx)(CPUE2KState *env, floatx80 *x, floatx80 *y)
{
int old_flags = save_exception_flags(env);
*x = floatx80_sub(*y, *x, &env->fp_status);
merge_exception_flags(env, old_flags);
int old_flags = fx_save_exception_flags(env);
*x = floatx80_sub(*y, *x, &env->fx_status);
fx_merge_exception_flags(env, old_flags);
}
#define GENERATE_FCMPODF(op, IN, F, cvt_macro) \
#define GENERATE_FCMPODF(op, IN, F, cvt_macro, status, save_flags, merge_flags) \
uint32_t HELPER(op)(CPUE2KState *env, IN _x, IN _y) \
{ \
int old_flags = save_exception_flags(env); \
int old_flags = save_flags(env); \
uint32_t ret; \
F x = cvt_macro(_x); \
F y = cvt_macro(_y); \
if (glue(F, _is_any_nan)(x) || glue(F, _is_any_nan)(y)) { \
ret = 0x45; \
} else { \
FloatRelation relation = glue(F, _compare_quiet)(x, y, &env->fp_status); \
FloatRelation relation = glue(F, _compare_quiet)(x, y, status); \
switch(relation) \
{ \
case float_relation_less: \
@ -230,12 +246,15 @@ void HELPER(fxrsubxx)(CPUE2KState *env, floatx80 *x, floatx80 *y)
break; \
} \
} \
merge_exception_flags(env, old_flags); \
merge_flags(env, old_flags); \
return ret; \
}
GENERATE_FCMPODF(fcmpodsf, uint32_t, float32, make_float32)
GENERATE_FCMPODF(fcmpoddf, uint64_t, float64, make_float64)
GENERATE_FCMPODF(fxcmpodxf, floatx80 *, floatx80, deref)
GENERATE_FCMPODF(fcmpodsf, uint32_t, float32, make_float32, &env->fp_status,
fp_save_exception_flags, fp_merge_exception_flags)
GENERATE_FCMPODF(fcmpoddf, uint64_t, float64, make_float64, &env->fp_status,
fp_save_exception_flags, fp_merge_exception_flags)
GENERATE_FCMPODF(fxcmpodxf, floatx80 *, floatx80, deref, &env->fx_status,
fx_save_exception_flags, fx_merge_exception_flags)
/* didn't found any difference between these instruction
so keep it that way for now */
@ -257,79 +276,74 @@ uint32_t HELPER(fxcmpudxf)(CPUE2KState *env, floatx80 *x, floatx80 *y)
#define TOIF_RC_CURRENT 0x4
#define TOIF_RC_IGNORE_INEXACT 0x8
static inline void toif_set_round_mode(CPUE2KState *env, uint32_t flags)
static inline void toif_set_round_mode(CPUE2KState *env, uint32_t flags,
float_status *s)
{
if(flags <= FPCR_RC_CHOP) {
FloatRoundMode rm;
switch(flags) {
case FPCR_RC_NEAR: rm = float_round_nearest_even; break;
case FPCR_RC_DOWN: rm = float_round_down; break;
case FPCR_RC_UP: rm = float_round_up; break;
case FPCR_RC_CHOP: rm = float_round_to_zero; break;
}
set_float_rounding_mode(rm, &env->fp_status);
if ((flags & TOIF_RC_CURRENT) == 0) {
set_float_rounding_mode(rm[flags & FP_RC_CHOP], s);
}
}
static inline void toif_clear_inexact(CPUE2KState *env, uint32_t flags)
static inline void toif_clear_inexact(CPUE2KState *env, uint32_t flags,
float_status *s)
{
if(flags & TOIF_RC_IGNORE_INEXACT) {
int new_flags = get_float_exception_flags(&env->fp_status);
int new_flags = get_float_exception_flags(s);
new_flags = new_flags & (~float_flag_inexact);
set_float_exception_flags(new_flags, &env->fp_status);
set_float_exception_flags(new_flags, s);
}
}
uint32_t HELPER(fstoifs)(CPUE2KState *env, uint32_t flags, uint32_t f)
{
int old_flags = save_exception_flags(env);
int old_flags = fp_save_exception_flags(env);
FloatRoundMode oldrm = get_float_rounding_mode(&env->fp_status);
uint32_t ret;
toif_set_round_mode(env, flags);
toif_set_round_mode(env, flags, &env->fp_status);
ret = float32_val(float32_round_to_int(make_float32(f), &env->fp_status));
set_float_rounding_mode(oldrm, &env->fp_status);
toif_clear_inexact(env, flags);
merge_exception_flags(env, old_flags);
toif_clear_inexact(env, flags, &env->fp_status);
fp_merge_exception_flags(env, old_flags);
return ret;
}
uint64_t HELPER(fdtoifd)(CPUE2KState *env, uint64_t flags, uint64_t f)
{
int old_flags = save_exception_flags(env);
int old_flags = fp_save_exception_flags(env);
FloatRoundMode oldrm = get_float_rounding_mode(&env->fp_status);
uint64_t ret;
toif_set_round_mode(env, flags);
toif_set_round_mode(env, flags, &env->fp_status);
ret = float64_val(float64_round_to_int(make_float64(f), &env->fp_status));
set_float_rounding_mode(oldrm, &env->fp_status);
toif_clear_inexact(env, flags);
merge_exception_flags(env, old_flags);
toif_clear_inexact(env, flags, &env->fp_status);
fp_merge_exception_flags(env, old_flags);
return ret;
}
/* TODO: test if valid, test exception flags */
uint32_t HELPER(frcps)(CPUE2KState *env, uint32_t x)
{
int old_flags = save_exception_flags(env);
int old_flags = fp_save_exception_flags(env);
uint32_t y = float32_div(float32_one, make_float32(x), &env->fp_status);
merge_exception_flags(env, old_flags);
fp_merge_exception_flags(env, old_flags);
return float32_val(y);
}
uint32_t HELPER(fsqrts)(CPUE2KState *env, uint32_t x)
{
int old_flags = save_exception_flags(env);
int old_flags = fp_save_exception_flags(env);
uint32_t y = float32_sqrt(make_float32(x), &env->fp_status);
merge_exception_flags(env, old_flags);
fp_merge_exception_flags(env, old_flags);
return float32_val(y);
}
uint32_t HELPER(frsqrts)(CPUE2KState *env, uint32_t x)
{
int old_flags = save_exception_flags(env);
int old_flags = fp_save_exception_flags(env);
uint32_t y = float32_div(float32_one,
float32_sqrt(make_float32(x), &env->fp_status),
&env->fp_status);
merge_exception_flags(env, old_flags);
fp_merge_exception_flags(env, old_flags);
return float32_val(y);
}
@ -343,17 +357,17 @@ uint64 HELPER(fsqrtid)(CPUE2KState *env, uint64_t x)
uint64_t HELPER(fsqrttd)(CPUE2KState *env, uint64_t x, uint64_t unused)
{
int old_flags = save_exception_flags(env);
int old_flags = fp_save_exception_flags(env);
uint64_t y = float64_sqrt(make_float64(x), &env->fp_status);
merge_exception_flags(env, old_flags);
fp_merge_exception_flags(env, old_flags);
return float64_val(y);
}
void HELPER(fxsqrttxx)(CPUE2KState *env, floatx80 *x, floatx80 *unused)
{
int old_flags = save_exception_flags(env);
*x = floatx80_sqrt(*x, &env->fp_status);
merge_exception_flags(env, old_flags);
int old_flags = fx_save_exception_flags(env);
*x = floatx80_sqrt(*x, &env->fx_status);
fx_merge_exception_flags(env, old_flags);
}
#define IMPL_FSCALE(name, ty, exp_len, exp_off, mul, cvt) \

View File

@ -64,7 +64,7 @@ uint64_t helper_state_reg_read_i64(CPUE2KState *env, int idx)
lsr = deposit64(lsr, LSR_STRMD_OFF, LSR_STRMD_LEN, env->lsr_strmd);
return lsr;
}
case 0x84: return env->pfpfr; /* %pfpfr */
case 0x84: return env->pfpfr.raw; /* %pfpfr */
case 0x85: return env->fpcr.raw; /* %fpcr */
case 0x86: return env->fpsr.raw; /* %fpsr */
case 0x8a: return env->idr; /* %idr */
@ -96,11 +96,12 @@ void helper_state_reg_write_i64(CPUE2KState *env, int idx, uint64_t val)
env->lsr_strmd = extract64(val, LSR_STRMD_OFF, LSR_STRMD_LEN);
break;
case 0x84: /* %pfpfr */
env->pfpfr = val;
env->pfpfr.raw = val;
e2k_update_fp_status(env);
break;
case 0x85: /* %fpcr */
env->fpcr.raw = val;
e2k_update_fp_status(env);
e2k_update_fx_status(env);
break;
case 0x86: env->fpsr.raw = val; break; /* %fpsr */
default:
@ -119,11 +120,12 @@ void helper_state_reg_write_i32(CPUE2KState *env, int idx, uint32_t val)
env->lsr_lcnt = val;
break;
case 0x84: /* %pfpfr */
env->pfpfr = deposit64(env->pfpfr, 0, 32, val);
env->pfpfr.raw = val;
e2k_update_fp_status(env);
break;
case 0x85: /* %fpcr */
env->fpcr.raw = val;
e2k_update_fp_status(env);
e2k_update_fx_status(env);
break;
case 0x86: env->fpsr.raw = val; break; /* %fpsr */
default:

View File

@ -1,6 +1,7 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "cpu.h"
#include "helper-tcg.h"
#include "exec/exec-all.h"
#include "qemu/host-utils.h"
#include "exec/helper-proto.h"
@ -37,7 +38,6 @@ typedef union {
int64_t sd[vec64_ud];
} vec64;
#define ident(x) x
#define shr16(x) ((x) >> 16)
#define shr14_add1_shr1(x) ((((x) >> 14) + 1) >> 1)
#define and16(x) ((x) & 0xffff)