Commit eea84fd0 authored by Michael Beck's avatar Michael Beck
Browse files

use EMMS/FEMMS on AMD machines to clear x87 state

[r15810]
parent 7fc81e62
......@@ -93,7 +93,10 @@ enum cpu_support {
#define ARCH_AMD(x) _IN_RANGE((x), arch_k6, arch_opteron)
/** return true if it's a Athlon/Opteron */
#define ARCH_ATHLON(x) _IN_RANGE((x), arch_athlon, arch_opteron)
#define ARCH_ATHLON(x) _IN_RANGE((x), arch_athlon, arch_opteron)
/** return true if the CPU has MMX support */
#define ARCH_MMX(x) _IN_RANGE((x), arch_pentium_mmx, arch_opteron)
#define IS_P6_ARCH(x) (_IN_RANGE((x), arch_pentium_pro, arch_core) || \
_IN_RANGE((x), arch_athlon, arch_opteron))
......
......@@ -2238,7 +2238,7 @@ fpushCopy => {
},
fpop => {
op_flags => "R|K",
op_flags => "K",
reg_req => { },
cmp_attr => "return 1;",
emit => '. fstp %X0',
......@@ -2246,13 +2246,29 @@ fpop => {
},
ffreep => {
op_flags => "R|K",
op_flags => "K",
reg_req => { },
cmp_attr => "return 1;",
emit => '. ffreep %X0',
attr_type => "ia32_x87_attr_t",
},
emms => {
op_flags => "K",
reg_req => { },
cmp_attr => "return 1;",
emit => '. emms',
attr_type => "ia32_x87_attr_t",
},
femms => {
op_flags => "K",
reg_req => { },
cmp_attr => "return 1;",
emit => '. femms',
attr_type => "ia32_x87_attr_t",
},
# compare
fcomJmp => {
......
......@@ -308,6 +308,16 @@ static void x87_pop(x87_state *state) {
DB((dbg, LEVEL_2, "After POP: ")); DEBUG_ONLY(x87_dump_stack(state));
} /* x87_pop */
/**
* Empty the fpu stack
*
* @param state the x87 state
*/
static void x87_emms(x87_state *state) {
state->depth = 0;
state->tos = 0;
}
/**
* Returns the block state of a block.
*
......@@ -2027,6 +2037,24 @@ static x87_state *x87_kill_deads(x87_simulator *sim, ir_node *block, x87_state *
DEBUG_ONLY(vfp_dump_live(live));
DEBUG_ONLY(x87_dump_stack(state));
if (kill_mask != 0 && live == 0) {
int cpu = sim->isa->arch;
/* special case: kill all registers */
if (ARCH_ATHLON(sim->isa->opt_arch) && ARCH_MMX(cpu)) {
if (ARCH_AMD(cpu)) {
/* use FEMMS on AMD processors to clear all */
keep = new_rd_ia32_femms(NULL, get_irn_irg(block), block, mode_E);
} else {
/* use EMMS to clear all */
keep = new_rd_ia32_emms(NULL, get_irn_irg(block), block, mode_E);
}
sched_add_before(first_insn, keep);
keep_alive(keep);
x87_emms(state);
return state;
}
}
/* now kill registers */
while (kill_mask) {
/* we can only kill from TOS, so bring them up */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment