Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
27521ff6
Commit
27521ff6
authored
Nov 11, 2012
by
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
Changes
4
Show whitespace changes
Inline
Side-by-side
ir/be/ia32/ia32_emitter.c
View file @
27521ff6
...
...
@@ -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 */
...
...
ir/be/ia32/ia32_nodes_attr.h
View file @
27521ff6
...
...
@@ -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
;
...
...
ir/be/ia32/ia32_spec.pl
View file @
27521ff6
...
...
@@ -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
=>
{},
...
...
ir/be/ia32/ia32_x87.c
View file @
27521ff6
...
...
@@ -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) \
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment