#include "../belive_t.h"
#include "../besched_t.h"
#include "../benode_t.h"
+#include "bearch_ia32_t.h"
#include "ia32_new_nodes.h"
#include "gen_ia32_new_nodes.h"
#include "gen_ia32_regalloc_if.h"
#define N_x87_REGS 8
-/* first and second binop index */
-#define BINOP_IDX_1 2
-#define BINOP_IDX_2 3
-
/* the unop index */
#define UNOP_IDX 0
-/* the store val index */
-#define STORE_VAL_IDX 2
-
#define MASK_TOS(x) ((x) & (N_x87_REGS - 1))
/** the debug handle */
vfp_liveness *live; /**< Liveness information. */
unsigned n_idx; /**< The cached get_irg_last_idx() result. */
waitq *worklist; /**< Worklist of blocks that must be processed. */
+ ia32_isa_t *isa; /**< the ISA object */
};
/**
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.
*
{
ir_node *fpop;
ia32_x87_attr_t *attr;
+ int cpu = state->sim->isa->opt_arch;
while (num > 0) {
x87_pop(state);
- fpop = new_rd_ia32_fpop(NULL, get_irn_irg(n), get_nodes_block(n), mode_E);
+ if (ARCH_ATHLON(cpu))
+ fpop = new_rd_ia32_ffreep(NULL, get_irn_irg(n), get_nodes_block(n), mode_E);
+ else
+ fpop = new_rd_ia32_fpop(NULL, get_irn_irg(n), get_nodes_block(n), mode_E);
attr = get_ia32_x87_attr(fpop);
attr->x87[0] = &ia32_st_regs[0];
attr->x87[1] = &ia32_st_regs[0];
ir_node *patched_insn;
ir_op *dst;
x87_simulator *sim = state->sim;
- ir_node *op1 = get_irn_n(n, BINOP_IDX_1);
- ir_node *op2 = get_irn_n(n, BINOP_IDX_2);
+ ir_node *op1 = get_irn_n(n, n_ia32_binary_left);
+ ir_node *op2 = get_irn_n(n, n_ia32_binary_right);
const arch_register_t *op1_reg = x87_get_irn_register(sim, op1);
const arch_register_t *op2_reg = x87_get_irn_register(sim, op2);
const arch_register_t *out = x87_get_irn_register(sim, n);
if (op1_live_after) {
/* Both operands are live: push the first one.
This works even for op1 == op2. */
- x87_create_fpush(state, n, op1_idx, BINOP_IDX_2);
+ x87_create_fpush(state, n, op1_idx, n_ia32_binary_right);
/* now do fxxx (tos=tos X op) */
op1_idx = 0;
op2_idx += 1;
/* second operand is an address mode */
if (op1_live_after) {
/* first operand is live: push it here */
- x87_create_fpush(state, n, op1_idx, BINOP_IDX_1);
+ x87_create_fpush(state, n, op1_idx, n_ia32_binary_left);
op1_idx = 0;
/* use fxxx (tos = tos X mem) */
dst = tmpl->normal_op;
*/
static int sim_store(x87_state *state, ir_node *n, ir_op *op, ir_op *op_p) {
x87_simulator *sim = state->sim;
- ir_node *val = get_irn_n(n, STORE_VAL_IDX);
+ ir_node *val = get_irn_n(n, n_ia32_vfst_val);
const arch_register_t *op2 = x87_get_irn_register(sim, val);
unsigned live = vfp_live_args_after(sim, n, 0);
int insn = NO_NODE_ADDED;
if (mode == mode_E) {
if (depth < N_x87_REGS) {
/* ok, we have a free register: push + fstp */
- x87_create_fpush(state, n, op2_idx, STORE_VAL_IDX);
+ x87_create_fpush(state, n, op2_idx, n_ia32_vfst_val);
x87_pop(state);
x87_patch_insn(n, op_p);
} else {
set_ia32_frame_ent(vfld, get_ia32_frame_ent(n));
if (is_ia32_use_frame(n))
set_ia32_use_frame(vfld);
- set_ia32_am_flavour(vfld, get_ia32_am_flavour(n));
set_ia32_op_type(vfld, ia32_am_Source);
add_ia32_am_offs_int(vfld, get_ia32_am_offs_int(n));
set_ia32_am_sc(vfld, get_ia32_am_sc(n));
/* reroute all former users of the store memory to the load memory */
edges_reroute(mem, mproj, irg);
/* set the memory input of the load to the store memory */
- set_irn_n(vfld, 2, mem);
+ set_irn_n(vfld, n_ia32_vfld_mem, mem);
sched_add_after(n, vfld);
sched_add_after(vfld, rproj);
*
* @return NO_NODE_ADDED
*/
-static int sim_fCondJmp(x87_state *state, ir_node *n) {
+static int sim_fCmpJmp(x87_state *state, ir_node *n) {
int op1_idx;
int op2_idx = -1;
int pop_cnt = 0;
ia32_x87_attr_t *attr;
ir_op *dst;
x87_simulator *sim = state->sim;
- ir_node *op1_node = get_irn_n(n, n_ia32_vfCondJmp_left);
- ir_node *op2_node = get_irn_n(n, n_ia32_vfCondJmp_right);
+ ir_node *op1_node = get_irn_n(n, n_ia32_vfCmpJmp_left);
+ ir_node *op2_node = get_irn_n(n, n_ia32_vfCmpJmp_right);
const arch_register_t *op1 = x87_get_irn_register(sim, op1_node);
const arch_register_t *op2 = x87_get_irn_register(sim, op2_node);
int reg_index_1 = arch_register_get_index(op1);
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 */
sim->arch_env = arch_env;
sim->n_idx = get_irg_last_idx(irg);
sim->live = obstack_alloc(&sim->obst, sizeof(*sim->live) * sim->n_idx);
+ sim->isa = (ia32_isa_t *)arch_env->isa;
DB((dbg, LEVEL_1, "--------------------------------\n"
"x87 Simulator started for %+F\n", irg));
ASSOC_IA32(fchs);
ASSOC_IA32(fist);
ASSOC_IA32(fst);
- ASSOC_IA32(fCondJmp);
+ ASSOC_IA32(fCmpJmp);
ASSOC_BE(Copy);
ASSOC_BE(Call);
ASSOC_BE(Spill);