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:
if (*fmt == 'M') {
++fmt;
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') {
++fmt;
/* 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
unsigned char op0 = 0xD8;
if (out != st0) op0 |= 0x04;
if (attr->pop) op0 |= 0x02;
bemit8(op0);
unsigned op = op_rev;
......@@ -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));
} else {
assert(attr->x87[2] == st0);
assert(!attr->pop);
unsigned const size = get_mode_size_bits(get_ia32_ls_mode(node));
bemit8(size == 32 ? 0xD8 : 0xDC);
......@@ -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)
{
bemit8(op0);
......@@ -3310,11 +3310,6 @@ static void bemit_fadd(const ir_node *node)
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)
{
(void)node;
......@@ -3328,11 +3323,6 @@ static void bemit_fdiv(const ir_node *node)
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)
{
bemit_fop_reg(node, 0xDF, 0xC0);
......@@ -3461,11 +3451,6 @@ static void bemit_fmul(const ir_node *node)
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)
{
bemit_fop_reg(node, 0xDD, 0xD8);
......@@ -3527,11 +3512,6 @@ static void bemit_fsub(const ir_node *node)
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)
{
bemit8(0xD9); // fnstcw
......@@ -3715,10 +3695,8 @@ static void ia32_register_binary_emitters(void)
register_emitter(op_ia32_XorMem8Bit, bemit_xormem8bit);
register_emitter(op_ia32_fabs, bemit_fabs);
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_fdiv, bemit_fdiv);
register_emitter(op_ia32_fdivp, bemit_fdivp);
register_emitter(op_ia32_ffreep, bemit_ffreep);
register_emitter(op_ia32_fild, bemit_fild);
register_emitter(op_ia32_fist, bemit_fist);
......@@ -3728,14 +3706,12 @@ static void ia32_register_binary_emitters(void)
register_emitter(op_ia32_fld1, bemit_fld1);
register_emitter(op_ia32_fldz, bemit_fldz);
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_fpush, bemit_fpush);
register_emitter(op_ia32_fpushCopy, bemit_fpushcopy);
register_emitter(op_ia32_fst, bemit_fst);
register_emitter(op_ia32_fstp, bemit_fstp);
register_emitter(op_ia32_fsub, bemit_fsub);
register_emitter(op_ia32_fsubp, bemit_fsubp);
register_emitter(op_ia32_fxch, bemit_fxch);
/* ignore the following nodes */
......
......@@ -271,6 +271,7 @@ typedef struct ia32_x87_attr_t ia32_x87_attr_t;
struct ia32_x87_attr_t {
ia32_attr_t attr; /**< the generic attribute */
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;
......
......@@ -2273,15 +2273,7 @@ Sahf => {
fadd => {
state => "exc_pinned",
emit => 'fadd%FM %AF',
latency => 4,
attr_type => "ia32_x87_attr_t",
constructors => {},
},
faddp => {
state => "exc_pinned",
emit => 'faddp%FM %AF',
emit => 'fadd%FP%FM %AF',
latency => 4,
attr_type => "ia32_x87_attr_t",
constructors => {},
......@@ -2289,15 +2281,7 @@ faddp => {
fmul => {
state => "exc_pinned",
emit => 'fmul%FM %AF',
latency => 4,
attr_type => "ia32_x87_attr_t",
constructors => {},
},
fmulp => {
state => "exc_pinned",
emit => 'fmulp%FM %AF',,
emit => 'fmul%FP%FM %AF',
latency => 4,
attr_type => "ia32_x87_attr_t",
constructors => {},
......@@ -2305,15 +2289,7 @@ fmulp => {
fsub => {
state => "exc_pinned",
emit => 'fsub%FR%FM %AF',
latency => 4,
attr_type => "ia32_x87_attr_t",
constructors => {},
},
fsubp => {
state => "exc_pinned",
emit => 'fsub%FRp%FM %AF',
emit => 'fsub%FR%FP%FM %AF',
latency => 4,
attr_type => "ia32_x87_attr_t",
constructors => {},
......@@ -2328,15 +2304,7 @@ fprem => {
fdiv => {
state => "exc_pinned",
emit => 'fdiv%FR%FM %AF',
latency => 20,
attr_type => "ia32_x87_attr_t",
constructors => {},
},
fdivp => {
state => "exc_pinned",
emit => 'fdiv%FRp%FM %AF',
emit => 'fdiv%FR%FP%FM %AF',
latency => 20,
attr_type => "ia32_x87_attr_t",
constructors => {},
......
......@@ -736,14 +736,13 @@ static void vfp_dump_live(vfp_liveness live)
*
* @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 out_idx, do_pop = 0;
ia32_x87_attr_t *attr;
int permuted;
ir_node *patched_insn;
ir_op *dst;
x87_simulator *sim = state->sim;
ir_node *op1 = get_irn_n(n, n_ia32_binary_left);
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
op1_idx = 0;
op2_idx += 1;
out_idx = 0;
dst = normal_op;
} else {
/* Second live, first operand is dead here, bring it to tos. */
if (op1_idx != 0) {
......@@ -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) */
out_idx = 0;
dst = normal_op;
}
} else {
/* Second operand is dead. */
......@@ -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) */
out_idx = 0;
dst = normal_op;
} else {
/* Both operands are dead here, pop them from the stack. */
if (op2_idx == 0) {
if (op1_idx == 0) {
/* Both are identically and on tos, no pop needed. */
/* here fxxx (tos = tos X tos) */
dst = normal_op;
out_idx = 0;
} else {
/* now do fxxxp (op = op X tos, pop) */
dst = normal_pop_op;
do_pop = 1;
out_idx = op1_idx;
}
} else if (op1_idx == 0) {
assert(op1_idx != op2_idx);
/* now do fxxxrp (op = tos X op, pop) */
dst = normal_pop_op;
do_pop = 1;
out_idx = op2_idx;
} else {
......@@ -844,13 +837,11 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const norm
op1_idx = 0;
op2_idx = 0;
/* use fxxx (tos = tos X tos) */
dst = normal_op;
out_idx = 0;
} else {
/* op2 is on tos now */
op2_idx = 0;
/* use fxxxp (op = op X tos, pop) */
dst = normal_pop_op;
out_idx = op1_idx;
do_pop = 1;
}
......@@ -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) */
dst = normal_op;
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);
if (do_pop) {
x87_pop(state);
}
/* patch the operation */
attr->pop = do_pop;
attr->x87[0] = op1_reg = get_st_reg(op1_idx);
if (reg_index_2 != REG_VFP_VFP_NOREG) {
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)
#define GEN_BINOP(op) \
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) \
......
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