From 56a4d5cf83a046febd60c2932bdfcffc191f032f Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 10 Jan 2019 21:33:29 +0000 Subject: [PATCH] Use correct rounding mode on x86 and x86-64 recompiled versions of PF2ID. Fixes rendering errors on Unreal 3DNow! software renderer --- src/codegen_backend_x86-64.c | 1 + src/codegen_backend_x86-64_ops.c | 5 +++++ src/codegen_backend_x86-64_uops.c | 2 ++ src/codegen_backend_x86.c | 1 + src/codegen_backend_x86_uops.c | 2 ++ src/ibm.h | 3 +++ 6 files changed, 14 insertions(+) diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index 5de8f75..29ca83a 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -310,6 +310,7 @@ void codegen_backend_init() "stmxcsr %0\n" : "=m" (cpu_state.old_fp_control) ); + cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000; } void codegen_set_rounding_mode(int mode) diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index f077960..0992683 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -541,6 +541,11 @@ void host_x86_LDMXCSR(codeblock_t *block, void *p) { codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ } + else if (offset < (1ull << 32)) + { + codegen_addbyte3(block, 0x0f, 0xae, 0x90 | REG_EBP); /*LDMXCSR offset[EBP]*/ + codegen_addlong(block, offset); + } else { fatal("host_x86_LDMXCSR - out of range %p\n", p); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 049c626..dd164d6 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -1576,7 +1576,9 @@ static int codegen_PF2ID(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_x86_LDMXCSR(block, &cpu_state.trunc_fp_control); host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); } else fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index 4a43ff0..82c1d87 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -333,6 +333,7 @@ pclog(" offsetof(codeblock_t, next_2)=%i\n", offsetof(codeblock_t, next_2)); : "=m" (cpu_state.old_fp_control2), "=m" (cpu_state.old_fp_control) ); + cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000; } void codegen_set_rounding_mode(int mode) diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index e53b91d..aa1c885 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -1579,7 +1579,9 @@ static int codegen_PF2ID(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_x86_LDMXCSR(block, &cpu_state.trunc_fp_control); host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); } else fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); diff --git a/src/ibm.h b/src/ibm.h index e99c232..b587e62 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -181,6 +181,9 @@ struct uint32_t old_fp_control, new_fp_control; #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ uint16_t old_fp_control2, new_fp_control2; +#endif +#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined __amd64__ + uint32_t trunc_fp_control; #endif x86seg seg_cs,seg_ds,seg_es,seg_ss,seg_fs,seg_gs;