Commit 27521ff6 authored by Christoph Mallon's avatar Christoph Mallon
Browse files

Merge the pop and non-pop variants of x87 binary operations.

Let a flag and the emitter handle printing the pop variant.
parent 5d113398
...@@ -580,6 +580,11 @@ emit_AM: ...@@ -580,6 +580,11 @@ emit_AM:
if (*fmt == 'M') { if (*fmt == 'M') {
++fmt; ++fmt;
ia32_emit_x87_mode_suffix(node); ia32_emit_x87_mode_suffix(node);
} else if (*fmt == 'P') {
++fmt;
ia32_x87_attr_t const *const attr = get_ia32_x87_attr_const(node);
if (attr->pop)
be_emit_char('p');
} else if (*fmt == 'R') { } else if (*fmt == 'R') {
++fmt; ++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
...@@ -3266,6 +3271,7 @@ static void bemit_fbinop(ir_node const *const node, unsigned const op_fwd, unsig ...@@ -3266,6 +3271,7 @@ static void bemit_fbinop(ir_node const *const node, unsigned const op_fwd, unsig
unsigned char op0 = 0xD8; unsigned char op0 = 0xD8;
if (out != st0) op0 |= 0x04; if (out != st0) op0 |= 0x04;
if (attr->pop) op0 |= 0x02;
bemit8(op0); bemit8(op0);
unsigned op = op_rev; unsigned op = op_rev;
...@@ -3277,6 +3283,7 @@ static void bemit_fbinop(ir_node const *const node, unsigned const op_fwd, unsig ...@@ -3277,6 +3283,7 @@ static void bemit_fbinop(ir_node const *const node, unsigned const op_fwd, unsig
bemit8(MOD_REG | ENC_REG(op) | ENC_RM(reg->index)); bemit8(MOD_REG | ENC_REG(op) | ENC_RM(reg->index));
} else { } else {
assert(attr->x87[2] == st0); assert(attr->x87[2] == st0);
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);
...@@ -3284,13 +3291,6 @@ static void bemit_fbinop(ir_node const *const node, unsigned const op_fwd, unsig ...@@ -3284,13 +3291,6 @@ static void bemit_fbinop(ir_node const *const node, unsigned const op_fwd, unsig
} }
} }
static void bemit_fbinopp(const ir_node *node, unsigned const op_fwd, unsigned const op_rev)
{
ia32_x87_attr_t const *const attr = get_ia32_x87_attr_const(node);
bemit8(0xDE);
bemit8((attr->x87[0] == &ia32_registers[REG_ST0] ? op_fwd : op_rev) + attr->x87[2]->index);
}
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);
...@@ -3310,11 +3310,6 @@ static void bemit_fadd(const ir_node *node) ...@@ -3310,11 +3310,6 @@ static void bemit_fadd(const ir_node *node)
bemit_fbinop(node, 0, 0); bemit_fbinop(node, 0, 0);
} }
static void bemit_faddp(const ir_node *node)
{
bemit_fbinopp(node, 0xC0, 0xC0);
}
static void bemit_fchs(const ir_node *node) static void bemit_fchs(const ir_node *node)
{ {
(void)node; (void)node;
...@@ -3328,11 +3323,6 @@ static void bemit_fdiv(const ir_node *node) ...@@ -3328,11 +3323,6 @@ static void bemit_fdiv(const ir_node *node)
bemit_fbinop(node, 6, 7); bemit_fbinop(node, 6, 7);
} }
static void bemit_fdivp(const ir_node *node)
{
bemit_fbinopp(node, 0xF0, 0xF8);
}
static void bemit_ffreep(ir_node const *const node) static void bemit_ffreep(ir_node const *const node)
{ {
bemit_fop_reg(node, 0xDF, 0xC0); bemit_fop_reg(node, 0xDF, 0xC0);
...@@ -3461,11 +3451,6 @@ static void bemit_fmul(const ir_node *node) ...@@ -3461,11 +3451,6 @@ static void bemit_fmul(const ir_node *node)
bemit_fbinop(node, 1, 1); bemit_fbinop(node, 1, 1);
} }
static void bemit_fmulp(const ir_node *node)
{
bemit_fbinopp(node, 0xC8, 0xC8);
}
static void bemit_fpop(const ir_node *node) static void bemit_fpop(const ir_node *node)
{ {
bemit_fop_reg(node, 0xDD, 0xD8); bemit_fop_reg(node, 0xDD, 0xD8);
...@@ -3527,11 +3512,6 @@ static void bemit_fsub(const ir_node *node) ...@@ -3527,11 +3512,6 @@ static void bemit_fsub(const ir_node *node)
bemit_fbinop(node, 4, 5); bemit_fbinop(node, 4, 5);
} }
static void bemit_fsubp(const ir_node *node)
{
bemit_fbinopp(node, 0xE0, 0xE8);
}
static void bemit_fnstcw(const ir_node *node) static void bemit_fnstcw(const ir_node *node)
{ {
bemit8(0xD9); // fnstcw bemit8(0xD9); // fnstcw
...@@ -3715,10 +3695,8 @@ static void ia32_register_binary_emitters(void) ...@@ -3715,10 +3695,8 @@ static void ia32_register_binary_emitters(void)
register_emitter(op_ia32_XorMem8Bit, bemit_xormem8bit); register_emitter(op_ia32_XorMem8Bit, bemit_xormem8bit);
register_emitter(op_ia32_fabs, bemit_fabs); register_emitter(op_ia32_fabs, bemit_fabs);
register_emitter(op_ia32_fadd, bemit_fadd); register_emitter(op_ia32_fadd, bemit_fadd);
register_emitter(op_ia32_faddp, bemit_faddp);
register_emitter(op_ia32_fchs, bemit_fchs); register_emitter(op_ia32_fchs, bemit_fchs);
register_emitter(op_ia32_fdiv, bemit_fdiv); register_emitter(op_ia32_fdiv, bemit_fdiv);
register_emitter(op_ia32_fdivp, bemit_fdivp);
register_emitter(op_ia32_ffreep, bemit_ffreep); register_emitter(op_ia32_ffreep, bemit_ffreep);
register_emitter(op_ia32_fild, bemit_fild); register_emitter(op_ia32_fild, bemit_fild);
register_emitter(op_ia32_fist, bemit_fist); register_emitter(op_ia32_fist, bemit_fist);
...@@ -3728,14 +3706,12 @@ static void ia32_register_binary_emitters(void) ...@@ -3728,14 +3706,12 @@ static void ia32_register_binary_emitters(void)
register_emitter(op_ia32_fld1, bemit_fld1); register_emitter(op_ia32_fld1, bemit_fld1);
register_emitter(op_ia32_fldz, bemit_fldz); register_emitter(op_ia32_fldz, bemit_fldz);
register_emitter(op_ia32_fmul, bemit_fmul); register_emitter(op_ia32_fmul, bemit_fmul);
register_emitter(op_ia32_fmulp, bemit_fmulp);
register_emitter(op_ia32_fpop, bemit_fpop); register_emitter(op_ia32_fpop, bemit_fpop);
register_emitter(op_ia32_fpush, bemit_fpush); register_emitter(op_ia32_fpush, bemit_fpush);
register_emitter(op_ia32_fpushCopy, bemit_fpushcopy); register_emitter(op_ia32_fpushCopy, bemit_fpushcopy);
register_emitter(op_ia32_fst, bemit_fst); register_emitter(op_ia32_fst, bemit_fst);
register_emitter(op_ia32_fstp, bemit_fstp); register_emitter(op_ia32_fstp, bemit_fstp);
register_emitter(op_ia32_fsub, bemit_fsub); register_emitter(op_ia32_fsub, bemit_fsub);
register_emitter(op_ia32_fsubp, bemit_fsubp);
register_emitter(op_ia32_fxch, bemit_fxch); register_emitter(op_ia32_fxch, bemit_fxch);
/* ignore the following nodes */ /* ignore the following nodes */
......
...@@ -271,6 +271,7 @@ typedef struct ia32_x87_attr_t ia32_x87_attr_t; ...@@ -271,6 +271,7 @@ 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 */ const arch_register_t *x87[3]; /**< register slots for x87 register */
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;
......
...@@ -2273,15 +2273,7 @@ Sahf => { ...@@ -2273,15 +2273,7 @@ Sahf => {
fadd => { fadd => {
state => "exc_pinned", state => "exc_pinned",
emit => 'fadd%FM %AF', emit => 'fadd%FP%FM %AF',
latency => 4,
attr_type => "ia32_x87_attr_t",
constructors => {},
},
faddp => {
state => "exc_pinned",
emit => 'faddp%FM %AF',
latency => 4, latency => 4,
attr_type => "ia32_x87_attr_t", attr_type => "ia32_x87_attr_t",
constructors => {}, constructors => {},
...@@ -2289,15 +2281,7 @@ faddp => { ...@@ -2289,15 +2281,7 @@ faddp => {
fmul => { fmul => {
state => "exc_pinned", state => "exc_pinned",
emit => 'fmul%FM %AF', emit => 'fmul%FP%FM %AF',
latency => 4,
attr_type => "ia32_x87_attr_t",
constructors => {},
},
fmulp => {
state => "exc_pinned",
emit => 'fmulp%FM %AF',,
latency => 4, latency => 4,
attr_type => "ia32_x87_attr_t", attr_type => "ia32_x87_attr_t",
constructors => {}, constructors => {},
...@@ -2305,15 +2289,7 @@ fmulp => { ...@@ -2305,15 +2289,7 @@ fmulp => {
fsub => { fsub => {
state => "exc_pinned", state => "exc_pinned",
emit => 'fsub%FR%FM %AF', emit => 'fsub%FR%FP%FM %AF',
latency => 4,
attr_type => "ia32_x87_attr_t",
constructors => {},
},
fsubp => {
state => "exc_pinned",
emit => 'fsub%FRp%FM %AF',
latency => 4, latency => 4,
attr_type => "ia32_x87_attr_t", attr_type => "ia32_x87_attr_t",
constructors => {}, constructors => {},
...@@ -2328,15 +2304,7 @@ fprem => { ...@@ -2328,15 +2304,7 @@ fprem => {
fdiv => { fdiv => {
state => "exc_pinned", state => "exc_pinned",
emit => 'fdiv%FR%FM %AF', emit => 'fdiv%FR%FP%FM %AF',
latency => 20,
attr_type => "ia32_x87_attr_t",
constructors => {},
},
fdivp => {
state => "exc_pinned",
emit => 'fdiv%FRp%FM %AF',
latency => 20, latency => 20,
attr_type => "ia32_x87_attr_t", attr_type => "ia32_x87_attr_t",
constructors => {}, constructors => {},
......
...@@ -736,14 +736,13 @@ static void vfp_dump_live(vfp_liveness live) ...@@ -736,14 +736,13 @@ static void vfp_dump_live(vfp_liveness live)
* *
* @return NO_NODE_ADDED * @return NO_NODE_ADDED
*/ */
static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const normal_op, ir_op *const normal_pop_op) static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op)
{ {
int op2_idx = 0, op1_idx; int op2_idx = 0, op1_idx;
int out_idx, do_pop = 0; int out_idx, do_pop = 0;
ia32_x87_attr_t *attr; ia32_x87_attr_t *attr;
int permuted; int permuted;
ir_node *patched_insn; ir_node *patched_insn;
ir_op *dst;
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);
ir_node *op2 = get_irn_n(n, n_ia32_binary_right); ir_node *op2 = get_irn_n(n, n_ia32_binary_right);
...@@ -790,7 +789,6 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const norm ...@@ -790,7 +789,6 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const norm
op1_idx = 0; op1_idx = 0;
op2_idx += 1; op2_idx += 1;
out_idx = 0; out_idx = 0;
dst = normal_op;
} else { } else {
/* Second live, first operand is dead here, bring it to tos. */ /* Second live, first operand is dead here, bring it to tos. */
if (op1_idx != 0) { if (op1_idx != 0) {
...@@ -801,7 +799,6 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const norm ...@@ -801,7 +799,6 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const norm
} }
/* now do fxxx (tos=tos X op) */ /* now do fxxx (tos=tos X op) */
out_idx = 0; out_idx = 0;
dst = normal_op;
} }
} else { } else {
/* Second operand is dead. */ /* Second operand is dead. */
...@@ -815,25 +812,21 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const norm ...@@ -815,25 +812,21 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const norm
} }
/* now do fxxxr (tos = op X tos) */ /* now do fxxxr (tos = op X tos) */
out_idx = 0; out_idx = 0;
dst = normal_op;
} else { } else {
/* Both operands are dead here, pop them from the stack. */ /* Both operands are dead here, pop them from the stack. */
if (op2_idx == 0) { if (op2_idx == 0) {
if (op1_idx == 0) { if (op1_idx == 0) {
/* Both are identically and on tos, no pop needed. */ /* Both are identically and on tos, no pop needed. */
/* here fxxx (tos = tos X tos) */ /* here fxxx (tos = tos X tos) */
dst = normal_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) */
dst = normal_pop_op;
do_pop = 1; do_pop = 1;
out_idx = op1_idx; out_idx = op1_idx;
} }
} 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) */
dst = normal_pop_op;
do_pop = 1; do_pop = 1;
out_idx = op2_idx; out_idx = op2_idx;
} else { } else {
...@@ -844,13 +837,11 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const norm ...@@ -844,13 +837,11 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const norm
op1_idx = 0; op1_idx = 0;
op2_idx = 0; op2_idx = 0;
/* use fxxx (tos = tos X tos) */ /* use fxxx (tos = tos X tos) */
dst = normal_op;
out_idx = 0; out_idx = 0;
} else { } else {
/* op2 is on tos now */ /* op2 is on tos now */
op2_idx = 0; op2_idx = 0;
/* use fxxxp (op = op X tos, pop) */ /* use fxxxp (op = op X tos, pop) */
dst = normal_pop_op;
out_idx = op1_idx; out_idx = op1_idx;
do_pop = 1; do_pop = 1;
} }
...@@ -872,17 +863,17 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const norm ...@@ -872,17 +863,17 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const norm
} }
/* use fxxx (tos = tos X mem) */ /* use fxxx (tos = tos X mem) */
dst = normal_op;
out_idx = 0; out_idx = 0;
} }
patched_insn = x87_patch_insn(n, dst); 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 (do_pop) {
x87_pop(state); x87_pop(state);
} }
/* patch the operation */ /* patch the operation */
attr->pop = do_pop;
attr->x87[0] = op1_reg = get_st_reg(op1_idx); attr->x87[0] = op1_reg = get_st_reg(op1_idx);
if (reg_index_2 != REG_VFP_VFP_NOREG) { if (reg_index_2 != REG_VFP_VFP_NOREG) {
attr->x87[1] = op2_reg = get_st_reg(op2_idx); attr->x87[1] = op2_reg = get_st_reg(op2_idx);
...@@ -1076,7 +1067,7 @@ static int sim_store(x87_state *state, ir_node *n, ir_op *op, ir_op *op_p) ...@@ -1076,7 +1067,7 @@ static int sim_store(x87_state *state, ir_node *n, ir_op *op, ir_op *op_p)
#define GEN_BINOP(op) \ #define GEN_BINOP(op) \
static int sim_##op(x87_state *state, ir_node *n) { \ static int sim_##op(x87_state *state, ir_node *n) { \
return sim_binop(state, n, op_ia32_##op, op_ia32_##op##p); \ return sim_binop(state, n, op_ia32_##op); \
} }
#define GEN_LOAD(op) \ #define GEN_LOAD(op) \
......
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