Commit 0dd7a06d authored by Christoph Mallon's avatar Christoph Mallon
Browse files

x87: Simplify x87 code generation.

Do not store up to three registers for an instruction.
Instead only store the explicit register operand and whether the operands are permuted and/or the result is to be placed in the explicit register operand or st0.
parent aee4e102
...@@ -498,12 +498,9 @@ end_of_mods: ...@@ -498,12 +498,9 @@ end_of_mods:
goto emit_AM; goto emit_AM;
} else { } else {
assert(get_ia32_op_type(node) == ia32_Normal); assert(get_ia32_op_type(node) == ia32_Normal);
ia32_x87_attr_t const *const x87_attr = get_ia32_x87_attr_const(node); ia32_x87_attr_t const *const attr = get_ia32_x87_attr_const(node);
arch_register_t const *const out = x87_attr->x87[2]; char const *const fmt = attr->res_in_reg ? "%%st, %%%s" : "%%%s, %%st";
arch_register_t const * in = x87_attr->x87[1]; be_emit_irprintf(fmt, attr->reg->name);
if (out == in)
in = x87_attr->x87[0];
be_emit_irprintf("%%%s, %%%s", in->name, out->name);
break; break;
} }
...@@ -570,15 +567,12 @@ emit_AM: ...@@ -570,15 +567,12 @@ emit_AM:
case 'F': case 'F':
if (*fmt == 'M') { if (*fmt == 'M') {
++fmt;
ia32_emit_x87_mode_suffix(node); ia32_emit_x87_mode_suffix(node);
} else if (*fmt == 'P') { } else if (*fmt == 'P') {
++fmt;
ia32_x87_attr_t const *const attr = get_ia32_x87_attr_const(node); ia32_x87_attr_t const *const attr = get_ia32_x87_attr_const(node);
if (attr->pop) if (attr->pop)
be_emit_char('p'); be_emit_char('p');
} else if (*fmt == 'R') { } else if (*fmt == 'R') {
++fmt;
/* NOTE: Work around a gas quirk for non-commutative operations if the /* NOTE: Work around a gas quirk for non-commutative operations if the
* destination register is not %st0. In this case r/non-r is swapped. * destination register is not %st0. In this case r/non-r is swapped.
* %st0 = %st0 - %st1 -> fsub %st1, %st0 (as expected) * %st0 = %st0 - %st1 -> fsub %st1, %st0 (as expected)
...@@ -590,24 +584,20 @@ emit_AM: ...@@ -590,24 +584,20 @@ emit_AM:
* right (r) side of the executed operation. * right (r) side of the executed operation.
* - The placement of %st0 selects whether the result is written to * - The placement of %st0 selects whether the result is written to
* %st0 (right) or the other register (left). * %st0 (right) or the other register (left).
* This results in testing whether the left operand register is %st0 * This means that it is sufficient to test whether the operands are
* instead of the expected test whether the output register equals the * permuted. In particular it is not necessary to consider wether the
* left operand register. */ * result is to be placed into the explicit register operand. */
ia32_x87_attr_t const *const attr = get_ia32_x87_attr_const(node); if (get_ia32_x87_attr_const(node)->attr.data.ins_permuted)
if (get_ia32_op_type(node) == ia32_Normal ?
attr->x87[0] != &ia32_registers[REG_ST0] :
attr->attr.data.ins_permuted)
be_emit_char('r'); be_emit_char('r');
} else if (*fmt == 'X') { } else if (*fmt == 'X') {
++fmt;
ia32_emit_xmm_mode_suffix(node); ia32_emit_xmm_mode_suffix(node);
} else if ('0' <= *fmt && *fmt <= '2') { } else if (*fmt == '0') {
const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
be_emit_char('%'); be_emit_char('%');
be_emit_string(attr->x87[*fmt++ - '0']->name); be_emit_string(get_ia32_x87_attr_const(node)->reg->name);
} else { } else {
goto unknown; goto unknown;
} }
++fmt;
break; break;
case 'I': case 'I':
...@@ -3250,38 +3240,30 @@ static void bemit_copybi(const ir_node *node) ...@@ -3250,38 +3240,30 @@ static void bemit_copybi(const ir_node *node)
static void bemit_fbinop(ir_node const *const node, unsigned const op_fwd, unsigned const op_rev) static void bemit_fbinop(ir_node const *const node, unsigned const op_fwd, unsigned const op_rev)
{ {
ia32_x87_attr_t const *const attr = get_ia32_x87_attr_const(node); ia32_x87_attr_t const *const attr = get_ia32_x87_attr_const(node);
arch_register_t const *const st0 = &ia32_registers[REG_ST0]; unsigned const op = attr->attr.data.ins_permuted ? op_rev : op_fwd;
if (get_ia32_op_type(node) == ia32_Normal) { if (get_ia32_op_type(node) == ia32_Normal) {
arch_register_t const *const out = attr->x87[2]; assert(!attr->pop || attr->res_in_reg);
assert(out == attr->x87[0] || out == attr->x87[1]);
assert(!attr->attr.data.ins_permuted);
unsigned char op0 = 0xD8; unsigned char op0 = 0xD8;
if (out != st0) op0 |= 0x04; if (attr->res_in_reg) op0 |= 0x04;
if (attr->pop) op0 |= 0x02; if (attr->pop) op0 |= 0x02;
bemit8(op0); bemit8(op0);
unsigned op = op_rev; bemit8(MOD_REG | ENC_REG(op) | ENC_RM(attr->reg->index));
arch_register_t const *reg = attr->x87[0];
if (reg == st0) {
op = op_fwd;
reg = attr->x87[1];
}
bemit8(MOD_REG | ENC_REG(op) | ENC_RM(reg->index));
} else { } else {
assert(attr->x87[2] == st0); assert(!attr->reg);
assert(!attr->pop); assert(!attr->pop);
unsigned const size = get_mode_size_bits(get_ia32_ls_mode(node)); unsigned const size = get_mode_size_bits(get_ia32_ls_mode(node));
bemit8(size == 32 ? 0xD8 : 0xDC); bemit8(size == 32 ? 0xD8 : 0xDC);
bemit_mod_am(attr->attr.data.ins_permuted ? op_rev : op_fwd, node); bemit_mod_am(op, node);
} }
} }
static void bemit_fop_reg(ir_node const *const node, unsigned char const op0, unsigned char const op1) static void bemit_fop_reg(ir_node const *const node, unsigned char const op0, unsigned char const op1)
{ {
bemit8(op0); bemit8(op0);
bemit8(op1 + get_ia32_x87_attr_const(node)->x87[0]->index); bemit8(op1 + get_ia32_x87_attr_const(node)->reg->index);
} }
static void bemit_fabs(const ir_node *node) static void bemit_fabs(const ir_node *node)
...@@ -3478,14 +3460,14 @@ static void bemit_fucomi(const ir_node *node) ...@@ -3478,14 +3460,14 @@ static void bemit_fucomi(const ir_node *node)
{ {
const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node); const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
bemit8(attr->pop ? 0xDF : 0xDB); // fucom[p]i bemit8(attr->pop ? 0xDF : 0xDB); // fucom[p]i
bemit8(0xE8 + attr->x87[1]->index); bemit8(0xE8 + attr->reg->index);
} }
static void bemit_fucomfnstsw(const ir_node *node) static void bemit_fucomfnstsw(const ir_node *node)
{ {
const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node); const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
bemit8(0xDD); // fucom[p] bemit8(0xDD); // fucom[p]
bemit8((attr->pop ? 0xE8 : 0xE0) + attr->x87[1]->index); bemit8((attr->pop ? 0xE8 : 0xE0) + attr->reg->index);
bemit_fnstsw(); bemit_fnstsw();
} }
......
...@@ -269,9 +269,10 @@ struct ia32_immediate_attr_t { ...@@ -269,9 +269,10 @@ struct ia32_immediate_attr_t {
*/ */
typedef struct ia32_x87_attr_t ia32_x87_attr_t; typedef struct ia32_x87_attr_t ia32_x87_attr_t;
struct ia32_x87_attr_t { struct ia32_x87_attr_t {
ia32_attr_t attr; /**< the generic attribute */ ia32_attr_t attr; /**< the generic attribute */
const arch_register_t *x87[3]; /**< register slots for x87 register */ arch_register_t const *reg; /**< The explicit register operand. */
bool pop; /**< Emit a pop suffix. */ bool res_in_reg; /**< True if the result is in the explicit register operand, %st0 otherwise. */
bool pop; /**< Emit a pop suffix. */
}; };
typedef struct ia32_asm_reg_t ia32_asm_reg_t; typedef struct ia32_asm_reg_t ia32_asm_reg_t;
......
...@@ -2509,7 +2509,7 @@ femms => { ...@@ -2509,7 +2509,7 @@ femms => {
FucomFnstsw => { FucomFnstsw => {
reg_req => { }, reg_req => { },
emit => "fucom%FP %F1\n". emit => "fucom%FP %F0\n".
"fnstsw %%ax", "fnstsw %%ax",
attr_type => "ia32_x87_attr_t", attr_type => "ia32_x87_attr_t",
latency => 2, latency => 2,
...@@ -2525,7 +2525,7 @@ FucomppFnstsw => { ...@@ -2525,7 +2525,7 @@ FucomppFnstsw => {
Fucomi => { Fucomi => {
reg_req => { }, reg_req => { },
emit => 'fucom%FPi %F1', emit => 'fucom%FPi %F0',
attr_type => "ia32_x87_attr_t", attr_type => "ia32_x87_attr_t",
latency => 1, latency => 1,
}, },
......
...@@ -395,12 +395,12 @@ static void x87_create_fxch(x87_state *state, ir_node *n, int pos) ...@@ -395,12 +395,12 @@ static void x87_create_fxch(x87_state *state, ir_node *n, int pos)
ir_node *const block = get_nodes_block(n); ir_node *const block = get_nodes_block(n);
ir_node *const fxch = new_bd_ia32_fxch(NULL, block); ir_node *const fxch = new_bd_ia32_fxch(NULL, block);
ia32_x87_attr_t *const attr = get_ia32_x87_attr(fxch); ia32_x87_attr_t *const attr = get_ia32_x87_attr(fxch);
attr->x87[0] = get_st_reg(pos); attr->reg = get_st_reg(pos);
keep_alive(fxch); keep_alive(fxch);
sched_add_before(n, fxch); sched_add_before(n, fxch);
DB((dbg, LEVEL_1, "<<< %s %s, %s\n", get_irn_opname(fxch), attr->x87[0]->name, get_st_reg(0)->name)); DB((dbg, LEVEL_1, "<<< %s %s\n", get_irn_opname(fxch), attr->reg->name));
} }
/* -------------- x87 perm --------------- */ /* -------------- x87 perm --------------- */
...@@ -539,12 +539,12 @@ static void x87_create_fpush(x87_state *state, ir_node *n, int pos, int const ou ...@@ -539,12 +539,12 @@ static void x87_create_fpush(x87_state *state, ir_node *n, int pos, int const ou
ir_node *const fpush = new_bd_ia32_fpush(NULL, get_nodes_block(n)); ir_node *const fpush = new_bd_ia32_fpush(NULL, get_nodes_block(n));
ia32_x87_attr_t *const attr = get_ia32_x87_attr(fpush); ia32_x87_attr_t *const attr = get_ia32_x87_attr(fpush);
attr->x87[0] = get_st_reg(pos); attr->reg = get_st_reg(pos);
keep_alive(fpush); keep_alive(fpush);
sched_add_before(n, fpush); sched_add_before(n, fpush);
DB((dbg, LEVEL_1, "<<< %s %s, %s\n", get_irn_opname(fpush), attr->x87[0]->name, get_st_reg(0)->name)); DB((dbg, LEVEL_1, "<<< %s %s\n", get_irn_opname(fpush), attr->reg->name));
} }
/** /**
...@@ -569,11 +569,11 @@ static ir_node *x87_create_fpop(x87_state *state, ir_node *n, int num) ...@@ -569,11 +569,11 @@ static ir_node *x87_create_fpop(x87_state *state, ir_node *n, int num)
else else
fpop = new_bd_ia32_fpop(NULL, get_nodes_block(n)); fpop = new_bd_ia32_fpop(NULL, get_nodes_block(n));
attr = get_ia32_x87_attr(fpop); attr = get_ia32_x87_attr(fpop);
attr->x87[0] = get_st_reg(0); attr->reg = get_st_reg(0);
keep_alive(fpop); keep_alive(fpop);
sched_add_before(n, fpop); sched_add_before(n, fpop);
DB((dbg, LEVEL_1, "<<< %s %s\n", get_irn_opname(fpop), attr->x87[0]->name)); DB((dbg, LEVEL_1, "<<< %s %s\n", get_irn_opname(fpop), attr->reg->name));
} while (--num > 0); } while (--num > 0);
return fpop; return fpop;
} }
...@@ -734,10 +734,6 @@ static void vfp_dump_live(vfp_liveness live) ...@@ -734,10 +734,6 @@ static void vfp_dump_live(vfp_liveness live)
*/ */
static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op) static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op)
{ {
int op2_idx = 0, op1_idx;
int out_idx, do_pop = 0;
ia32_x87_attr_t *attr;
int permuted;
ir_node *patched_insn; ir_node *patched_insn;
x87_simulator *sim = state->sim; x87_simulator *sim = state->sim;
ir_node *op1 = get_irn_n(n, n_ia32_binary_left); ir_node *op1 = get_irn_n(n, n_ia32_binary_left);
...@@ -756,17 +752,16 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op) ...@@ -756,17 +752,16 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op)
DB((dbg, LEVEL_1, "Stack before: ")); DB((dbg, LEVEL_1, "Stack before: "));
DEBUG_ONLY(x87_dump_stack(state);) DEBUG_ONLY(x87_dump_stack(state);)
op1_idx = x87_on_stack(state, reg_index_1); int op1_idx = x87_on_stack(state, reg_index_1);
assert(op1_idx >= 0); assert(op1_idx >= 0);
op1_live_after = is_vfp_live(reg_index_1, live); op1_live_after = is_vfp_live(reg_index_1, live);
attr = get_ia32_x87_attr(n); int op2_idx;
permuted = attr->attr.data.ins_permuted; int out_idx;
bool pop = false;
int const out_reg_idx = out->index; int const out_reg_idx = out->index;
ia32_x87_attr_t *const attr = get_ia32_x87_attr(n);
if (reg_index_2 != REG_VFP_VFP_NOREG) { if (reg_index_2 != REG_VFP_VFP_NOREG) {
assert(!permuted);
/* second operand is a vfp register */ /* second operand is a vfp register */
op2_idx = x87_on_stack(state, reg_index_2); op2_idx = x87_on_stack(state, reg_index_2);
assert(op2_idx >= 0); assert(op2_idx >= 0);
...@@ -815,14 +810,14 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op) ...@@ -815,14 +810,14 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op)
out_idx = 0; out_idx = 0;
} else { } else {
/* now do fxxxp (op = op X tos, pop) */ /* now do fxxxp (op = op X tos, pop) */
do_pop = 1;
out_idx = op1_idx; out_idx = op1_idx;
pop = true;
} }
} else if (op1_idx == 0) { } else if (op1_idx == 0) {
assert(op1_idx != op2_idx); assert(op1_idx != op2_idx);
/* now do fxxxrp (op = tos X op, pop) */ /* now do fxxxrp (op = tos X op, pop) */
do_pop = 1;
out_idx = op2_idx; out_idx = op2_idx;
pop = true;
} else { } else {
/* Bring the second on top. */ /* Bring the second on top. */
x87_create_fxch(state, n, op2_idx); x87_create_fxch(state, n, op2_idx);
...@@ -837,7 +832,7 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op) ...@@ -837,7 +832,7 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op)
op2_idx = 0; op2_idx = 0;
/* use fxxxp (op = op X tos, pop) */ /* use fxxxp (op = op X tos, pop) */
out_idx = op1_idx; out_idx = op1_idx;
do_pop = 1; pop = true;
} }
} }
} }
...@@ -847,38 +842,37 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op) ...@@ -847,38 +842,37 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op)
if (op1_live_after) { if (op1_live_after) {
/* first operand is live: push it here */ /* first operand is live: push it here */
x87_create_fpush(state, n, op1_idx, out_reg_idx, op1); x87_create_fpush(state, n, op1_idx, out_reg_idx, op1);
op1_idx = 0;
} else { } else {
/* first operand is dead: bring it to tos */ /* first operand is dead: bring it to tos */
if (op1_idx != 0) { if (op1_idx != 0)
x87_create_fxch(state, n, op1_idx); x87_create_fxch(state, n, op1_idx);
op1_idx = 0;
}
} }
/* use fxxx (tos = tos X mem) */ op1_idx = attr->attr.data.ins_permuted ? -1 : 0;
op2_idx = attr->attr.data.ins_permuted ? 0 : -1;
out_idx = 0; out_idx = 0;
} }
assert(op1_idx == 0 || op2_idx == 0);
assert(out_idx == op1_idx || out_idx == op2_idx);
patched_insn = x87_patch_insn(n, op); patched_insn = x87_patch_insn(n, op);
x87_set_st(state, out_reg_idx, patched_insn, out_idx); x87_set_st(state, out_reg_idx, patched_insn, out_idx);
if (do_pop) { if (pop)
x87_pop(state); x87_pop(state);
}
/* patch the operation */ /* patch the operation */
attr->pop = do_pop; int const reg_idx = op1_idx != 0 ? op1_idx : op2_idx;
attr->x87[0] = op1_reg = get_st_reg(op1_idx); attr->reg = reg_idx >= 0 ? get_st_reg(reg_idx) : NULL;
if (reg_index_2 != REG_VFP_VFP_NOREG) { attr->attr.data.ins_permuted = op1_idx != 0;
attr->x87[1] = op2_reg = get_st_reg(op2_idx); attr->res_in_reg = out_idx != 0;
} attr->pop = pop;
attr->x87[2] = out = get_st_reg(out_idx);
DEBUG_ONLY(
if (reg_index_2 != REG_VFP_VFP_NOREG) { char const *const l = op1_idx >= 0 ? get_st_reg(op1_idx)->name : "[AM]";
DB((dbg, LEVEL_1, "<<< %s %s, %s -> %s\n", get_irn_opname(n), op1_reg->name, op2_reg->name, out->name)); char const *const r = op2_idx >= 0 ? get_st_reg(op2_idx)->name : "[AM]";
} else { char const *const o = get_st_reg(out_idx)->name;
DB((dbg, LEVEL_1, "<<< %s %s, [AM] -> %s\n", get_irn_opname(n), op1_reg->name, out->name)); DB((dbg, LEVEL_1, "<<< %s %s, %s -> %s\n", get_irn_opname(n), l, r, o));
} );
return NO_NODE_ADDED; return NO_NODE_ADDED;
} }
...@@ -1178,8 +1172,6 @@ static int sim_FtstFnstsw(x87_state *state, ir_node *n) ...@@ -1178,8 +1172,6 @@ static int sim_FtstFnstsw(x87_state *state, ir_node *n)
*/ */
static int sim_Fucom(x87_state *state, ir_node *n) static int sim_Fucom(x87_state *state, ir_node *n)
{ {
int op1_idx;
int op2_idx = -1;
ia32_x87_attr_t *attr = get_ia32_x87_attr(n); ia32_x87_attr_t *attr = get_ia32_x87_attr(n);
ir_op *dst; ir_op *dst;
x87_simulator *sim = state->sim; x87_simulator *sim = state->sim;
...@@ -1190,16 +1182,17 @@ static int sim_Fucom(x87_state *state, ir_node *n) ...@@ -1190,16 +1182,17 @@ static int sim_Fucom(x87_state *state, ir_node *n)
int reg_index_1 = op1->index; int reg_index_1 = op1->index;
int reg_index_2 = op2->index; int reg_index_2 = op2->index;
unsigned live = vfp_live_args_after(sim, n, 0); unsigned live = vfp_live_args_after(sim, n, 0);
int pops = 0;
DB((dbg, LEVEL_1, ">>> %+F %s, %s\n", n, op1->name, op2->name)); DB((dbg, LEVEL_1, ">>> %+F %s, %s\n", n, op1->name, op2->name));
DEBUG_ONLY(vfp_dump_live(live);) DEBUG_ONLY(vfp_dump_live(live);)
DB((dbg, LEVEL_1, "Stack before: ")); DB((dbg, LEVEL_1, "Stack before: "));
DEBUG_ONLY(x87_dump_stack(state);) DEBUG_ONLY(x87_dump_stack(state);)
op1_idx = x87_on_stack(state, reg_index_1); int op1_idx = x87_on_stack(state, reg_index_1);
assert(op1_idx >= 0); assert(op1_idx >= 0);
int op2_idx;
int pops = 0;
/* BEWARE: check for comp a,a cases, they might happen */ /* BEWARE: check for comp a,a cases, they might happen */
if (reg_index_2 != REG_VFP_VFP_NOREG) { if (reg_index_2 != REG_VFP_VFP_NOREG) {
/* second operand is a vfp register */ /* second operand is a vfp register */
...@@ -1316,21 +1309,16 @@ static int sim_Fucom(x87_state *state, ir_node *n) ...@@ -1316,21 +1309,16 @@ static int sim_Fucom(x87_state *state, ir_node *n)
} }
} else { } else {
/* second operand is an address mode */ /* second operand is an address mode */
if (is_vfp_live(reg_index_1, live)) { if (op1_idx != 0)
/* first operand is live: bring it to TOS */ x87_create_fxch(state, n, op1_idx);
if (op1_idx != 0) { /* Pop first operand, if it is dead. */
x87_create_fxch(state, n, op1_idx); if (!is_vfp_live(reg_index_1, live))
op1_idx = 0;
}
} else {
/* first operand is dead: bring it to tos */
if (op1_idx != 0) {
x87_create_fxch(state, n, op1_idx);
op1_idx = 0;
}
pops = 1; pops = 1;
}
op1_idx = attr->attr.data.ins_permuted ? -1 : 0;
op2_idx = attr->attr.data.ins_permuted ? 0 : -1;
} }
assert(op1_idx == 0 || op2_idx == 0);
/* patch the operation */ /* patch the operation */
if (is_ia32_vFucomFnstsw(n)) { if (is_ia32_vFucomFnstsw(n)) {
...@@ -1348,26 +1336,17 @@ static int sim_Fucom(x87_state *state, ir_node *n) ...@@ -1348,26 +1336,17 @@ static int sim_Fucom(x87_state *state, ir_node *n)
} }
x87_patch_insn(n, dst); x87_patch_insn(n, dst);
if (op1_idx != 0) {
int tmp = op1_idx;
op1_idx = op2_idx;
op2_idx = tmp;
attr->attr.data.ins_permuted ^= true;
}
op1 = get_st_reg(op1_idx); int const reg_idx = op1_idx != 0 ? op1_idx : op2_idx;
attr->x87[0] = op1; attr->reg = reg_idx >= 0 ? get_st_reg(reg_idx) : NULL;
if (op2_idx >= 0) { attr->attr.data.ins_permuted = op1_idx != 0;
op2 = get_st_reg(op2_idx);
attr->x87[1] = op2;
}
attr->pop = pops != 0; attr->pop = pops != 0;
if (op2_idx >= 0) { DEBUG_ONLY(
DB((dbg, LEVEL_1, "<<< %s %s, %s\n", get_irn_opname(n), op1->name, op2->name)); char const *const l = op1_idx >= 0 ? get_st_reg(op1_idx)->name : "[AM]";
} else { char const *const r = op2_idx >= 0 ? get_st_reg(op2_idx)->name : "[AM]";
DB((dbg, LEVEL_1, "<<< %s %s, [AM]\n", get_irn_opname(n), op1->name)); DB((dbg, LEVEL_1, "<<< %s %s, %s\n", get_irn_opname(n), l, r));
} );
return NO_NODE_ADDED; return NO_NODE_ADDED;
} }
...@@ -1486,7 +1465,7 @@ static ir_node *create_Copy(x87_state *state, ir_node *n) ...@@ -1486,7 +1465,7 @@ static ir_node *create_Copy(x87_state *state, ir_node *n)
x87_push(state, out->index, res); x87_push(state, out->index, res);
ia32_x87_attr_t *const attr = get_ia32_x87_attr(res); ia32_x87_attr_t *const attr = get_ia32_x87_attr(res);
attr->x87[0] = get_st_reg(op1_idx); attr->reg = get_st_reg(op1_idx);
} }
arch_set_irn_register(res, out); arch_set_irn_register(res, out);
......
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