Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions linux-user/i386/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -408,13 +408,56 @@ static void sync_ymm_high_from_xmm(CPUX86State *env)
#endif
#endif

#ifdef CONFIG_LATX
enum {
LATX_FCSR_FLAGS_SHIFT = 16,
LATX_FCSR_FLAG_I = 1u << 0,
LATX_FCSR_FLAG_U = 1u << 1,
LATX_FCSR_FLAG_O = 1u << 2,
LATX_FCSR_FLAG_Z = 1u << 3,
LATX_FCSR_FLAG_V = 1u << 4,
LATX_FCSR_FLAGS_MASK = 0x1f,
LATX_MXCSR_IE = 1u << 0,
LATX_MXCSR_ZE = 1u << 2,
LATX_MXCSR_OE = 1u << 3,
LATX_MXCSR_UE = 1u << 4,
LATX_MXCSR_PE = 1u << 5,
};

static uint32_t latx_fcsr_flags_to_mxcsr(uint32_t fcsr)
{
uint32_t flags = (fcsr >> LATX_FCSR_FLAGS_SHIFT) &
LATX_FCSR_FLAGS_MASK;

return (flags & LATX_FCSR_FLAG_V ? LATX_MXCSR_IE : 0) |
(flags & LATX_FCSR_FLAG_Z ? LATX_MXCSR_ZE : 0) |
(flags & LATX_FCSR_FLAG_O ? LATX_MXCSR_OE : 0) |
(flags & LATX_FCSR_FLAG_U ? LATX_MXCSR_UE : 0) |
(flags & LATX_FCSR_FLAG_I ? LATX_MXCSR_PE : 0);
}

static void latx_clear_saved_fcsr_flags(CPUX86State *env)
{
env->fcsr &= ~(LATX_FCSR_FLAGS_MASK << LATX_FCSR_FLAGS_SHIFT);
}
#endif

/*
* Set up a signal frame.
*/

static void xsave_sigcontext(CPUX86State *env, struct target_fpstate_fxsave *fxsave,
abi_ulong fxsave_addr)
{
#ifdef CONFIG_LATX
if (option_softfpu) {
/*
* Merge pending native SSE exceptions before saving the guest
* signal frame. Use the saved FCSR, not the live host register.
*/
env->mxcsr |= latx_fcsr_flags_to_mxcsr(env->fcsr);
}
#endif
if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) {
/* fxsave_addr must be 16 byte aligned for fxsave */
assert(!(fxsave_addr & 0xf));
Expand Down Expand Up @@ -751,6 +794,12 @@ static int xrstor_sigcontext(CPUX86State *env, struct target_fpstate_fxsave *fxs
}
if (tswapl(*(uint32_t *) &fxsave->xfeatures[xfeatures_size]) == TARGET_FP_XSTATE_MAGIC2) {
cpu_x86_xrstor(env, fxsave_addr);
#ifdef CONFIG_LATX
if (option_softfpu) {
/* Discard stale flags after restoring guest state. */
latx_clear_saved_fcsr_flags(env);
}
#endif
#ifdef CONFIG_LATX_AVX_OPT
sync_ymm_high_from_xmm(env);
#endif
Expand All @@ -761,6 +810,12 @@ static int xrstor_sigcontext(CPUX86State *env, struct target_fpstate_fxsave *fxs
}

cpu_x86_fxrstor(env, fxsave_addr);
#ifdef CONFIG_LATX
if (option_softfpu) {
/* Discard stale flags after restoring guest state. */
latx_clear_saved_fcsr_flags(env);
}
#endif
return 0;
}

Expand Down
3 changes: 3 additions & 0 deletions target/i386/latx/include/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ typedef struct TRANSLATION_DATA {

int curr_top; /* top value (changes when translating) */

/* Translation-time SSE RM cache for strict SoftFPU paths; reset per TB. */
bool sse_rounding_prepared;

/* TODO : support static translation */
uint8 curr_ir1_skipped_eflags; /* these eflag calculation can be skipped */
/* (because of flag pattern, etc) */
Expand Down
10 changes: 10 additions & 0 deletions target/i386/latx/include/translate.h
Original file line number Diff line number Diff line change
Expand Up @@ -1683,6 +1683,16 @@ void update_fcsr_by_cw(IR2_OPND cw);
IR2_OPND set_fpu_fcsr_rounding_field_by_x86(void);
void set_fpu_rounding_mode(IR2_OPND rm);

/*
* Lightweight SSE/AVX FCSR synchronization for SoftFPU modes without native
* x87 fast paths. x87 exceptions are maintained by SoftFloat in env->fpus,
* so native FCSR0 carries only pending SSE/AVX state. This is not a complete
* cross-domain scheme when LATX_SOFTFPU_FAST enables native x87 operations.
*/
void prepare_sse_rounding_mode(void);
void submit_sse_flags_to_mxcsr(IR2_OPND mxcsr_opnd);
void clear_sse_fcsr_flags(void);

int generate_native_rotate_fpu_by(void *code_buf);
void generate_context_switch_bt_to_native(void *code_buf);
void generate_context_switch_native_to_bt(void);
Expand Down
7 changes: 7 additions & 0 deletions target/i386/latx/translator/tr-avx-cvt.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ bool translate_vcvtpd2ps(IR1_INST * pir1) {
return translate_vcvtpd2ps_lsx(pir1);
}

prepare_sse_rounding_mode();
lsassert(ir1_opnd_is_xmm(ir1_get_opnd(pir1, 0)));

if (ir1_opnd_size(ir1_get_opnd(pir1, 1)) == 128) {
Expand Down Expand Up @@ -73,6 +74,7 @@ bool translate_vcvtdq2ps(IR1_INST * pir1) {
return translate_vcvtdq2ps_lsx(pir1);
}

prepare_sse_rounding_mode();
lsassert(ir1_opnd_is_xmm(ir1_get_opnd(pir1, 0)) ||
ir1_opnd_is_ymm(ir1_get_opnd(pir1, 0)));

Expand Down Expand Up @@ -130,6 +132,7 @@ bool translate_vcvtps2dq(IR1_INST * pir1) {
if (!option_enable_lasx) {
return translate_vcvtps2dq_lsx(pir1);
}
prepare_sse_rounding_mode();

if (option_cvt_opt) {
return translate_vcvtps2dq_opt(pir1);
Expand Down Expand Up @@ -429,6 +432,7 @@ bool translate_vcvtpd2dq(IR1_INST * pir1) {
if (!option_enable_lasx) {
return translate_vcvtpd2dq_lsx(pir1);
}
prepare_sse_rounding_mode();

if (option_cvt_opt) {
return translate_vcvtpd2dq_opt(pir1);
Expand Down Expand Up @@ -585,6 +589,9 @@ bool translate_vcvtsi2sd(IR1_INST * pir1) {
lsassert(ir1_opnd_is_xmm(ir1_get_opnd(pir1, 0)) &&
ir1_opnd_is_xmm(ir1_get_opnd(pir1, 1)));
IR1_OPND * opnd2 = ir1_get_opnd(pir1, 2);
if (ir1_opnd_size(opnd2) == 64) {
prepare_sse_rounding_mode();
}
IR2_OPND dest = load_freg128_from_ir1(ir1_get_opnd(pir1, 0));
IR2_OPND src1 = load_freg128_from_ir1(ir1_get_opnd(pir1, 1));
IR2_OPND src2 = load_ireg_from_ir1(opnd2, UNKNOWN_EXTENSION, false);
Expand Down
Loading