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
88ec54f1
Commit
88ec54f1
authored
Sep 30, 2007
by
Matthias Braun
Browse files
support for fucom(p)i
[r16014]
parent
277830bf
Changes
4
Hide whitespace changes
Inline
Side-by-side
ir/be/ia32/ia32_emitter.c
View file @
88ec54f1
...
...
@@ -678,7 +678,8 @@ static int determine_final_pnc(const ir_node *node, int flags_pos,
if
(
flags_attr
->
data
.
cmp_flipped
)
pnc
=
get_mirrored_pnc
(
pnc
);
pnc
|=
ia32_pn_Cmp_float
;
}
else
if
(
is_ia32_Ucomi
(
flags
))
{
}
else
if
(
is_ia32_Ucomi
(
flags
)
||
is_ia32_Fucomi
(
flags
)
||
is_ia32_Fucompi
(
flags
))
{
flags_attr
=
get_ia32_attr_const
(
flags
);
if
(
flags_attr
->
data
.
cmp_flipped
)
...
...
ir/be/ia32/ia32_spec.pl
View file @
88ec54f1
...
...
@@ -1829,6 +1829,19 @@ vFucomFnstsw => {
mode
=>
$mode_gp
},
vFucomi
=>
{
irn_flags
=>
"
R
",
reg_req
=>
{
in
=>
[
"
vfp
",
"
vfp
"
],
out
=>
[
"
eflags
"
]
},
ins
=>
[
"
left
",
"
right
"
],
outs
=>
[
"
flags
"
],
attr
=>
"
int flipped
",
init_attr
=>
"
attr->attr.data.cmp_flipped = flipped;
",
latency
=>
3
,
units
=>
[
"
VFP
"
],
attr_type
=>
"
ia32_x87_attr_t
",
mode
=>
$mode_gp
},
vFtstFnstsw
=>
{
# irn_flags => "R",
reg_req
=>
{
in
=>
[
"
vfp
"
],
out
=>
[
"
eax
"
]
},
...
...
@@ -2207,6 +2220,18 @@ FucomppFnstsw => {
attr_type
=>
"
ia32_x87_attr_t
",
},
Fucomi
=>
{
reg_req
=>
{
},
emit
=>
'
. fucomi %X1
',
attr_type
=>
"
ia32_x87_attr_t
",
},
Fucompi
=>
{
reg_req
=>
{
},
emit
=>
'
. fucompi %X1
',
attr_type
=>
"
ia32_x87_attr_t
",
},
FtstFnstsw
=>
{
reg_req
=>
{
},
emit
=>
"
. ftst
\n
"
.
...
...
ir/be/ia32/ia32_transform.c
View file @
88ec54f1
...
...
@@ -2206,20 +2206,27 @@ static ir_node *create_Fucom(ir_node *node)
ir_node
*
new_right
;
ir_node
*
res
;
if
(
transform_config
.
use_ftst
&&
is_Const_null
(
right
))
{
res
=
new_rd_ia32_vFtstFnstsw
(
dbgi
,
irg
,
new_block
,
new_left
,
0
);
}
else
{
if
(
1
||
transform_config
.
use_fucomi
)
{
new_right
=
be_transform_node
(
right
);
res
=
new_rd_ia32_vFucomFnstsw
(
dbgi
,
irg
,
new_block
,
new_left
,
new_right
,
0
);
}
res
=
new_rd_ia32_vFucomi
(
dbgi
,
irg
,
new_block
,
new_left
,
new_right
,
0
);
set_ia32_commutative
(
res
);
SET_IA32_ORIG_NODE
(
res
,
ia32_get_old_node_name
(
env_cg
,
node
));
}
else
{
if
(
transform_config
.
use_ftst
&&
is_Const_null
(
right
))
{
res
=
new_rd_ia32_vFtstFnstsw
(
dbgi
,
irg
,
new_block
,
new_left
,
0
);
}
else
{
new_right
=
be_transform_node
(
right
);
res
=
new_rd_ia32_vFucomFnstsw
(
dbgi
,
irg
,
new_block
,
new_left
,
new_right
,
0
);
}
set_ia32_commutative
(
res
);
set_ia32_commutative
(
res
);
SET_IA32_ORIG_NODE
(
res
,
ia32_get_old_node_name
(
env_cg
,
node
));
SET_IA32_ORIG_NODE
(
res
,
ia32_get_old_node_name
(
env_cg
,
node
));
res
=
new_rd_ia32_Sahf
(
dbgi
,
irg
,
new_block
,
res
);
SET_IA32_ORIG_NODE
(
res
,
ia32_get_old_node_name
(
env_cg
,
node
));
res
=
new_rd_ia32_Sahf
(
dbgi
,
irg
,
new_block
,
res
);
SET_IA32_ORIG_NODE
(
res
,
ia32_get_old_node_name
(
env_cg
,
node
));
}
return
res
;
}
...
...
ir/be/ia32/ia32_x87.c
View file @
88ec54f1
...
...
@@ -1368,13 +1368,10 @@ static int sim_FtstFnstsw(x87_state *state, ir_node *n) {
/**
* @param state the x87 state
* @param n the node that should be simulated (and patched)
*
* @return NO_NODE_ADDED
*/
static
int
sim_Fucom
Fnstsw
(
x87_state
*
state
,
ir_node
*
n
)
{
static
int
sim_Fucom
(
x87_state
*
state
,
ir_node
*
n
)
{
int
op1_idx
;
int
op2_idx
=
-
1
;
int
pop_cnt
=
0
;
ia32_x87_attr_t
*
attr
=
get_ia32_x87_attr
(
n
);
ir_op
*
dst
;
x87_simulator
*
sim
=
state
->
sim
;
...
...
@@ -1387,6 +1384,8 @@ static int sim_FucomFnstsw(x87_state *state, ir_node *n) {
unsigned
live
=
vfp_live_args_after
(
sim
,
n
,
0
);
int
flipped
=
attr
->
attr
.
data
.
cmp_flipped
;
int
xchg
=
0
;
int
pops
=
0
;
int
node_added
=
NO_NODE_ADDED
;
DB
((
dbg
,
LEVEL_1
,
">>> %+F %s, %s
\n
"
,
n
,
arch_register_get_name
(
op1
),
arch_register_get_name
(
op2
)));
...
...
@@ -1403,18 +1402,16 @@ static int sim_FucomFnstsw(x87_state *state, ir_node *n) {
op2_idx
=
x87_on_stack
(
state
,
reg_index_2
);
assert
(
op2_idx
>=
0
);
if
(
is_vfp_live
(
arch_register_get
_index
(
op2
)
,
live
))
{
if
(
is_vfp_live
(
reg
_index
_2
,
live
))
{
/* second operand is live */
if
(
is_vfp_live
(
arch_register_get
_index
(
op1
)
,
live
))
{
if
(
is_vfp_live
(
reg
_index
_1
,
live
))
{
/* both operands are live */
if
(
op1_idx
==
0
)
{
/* res = tos X op */
dst
=
op_ia32_FucomFnstsw
;
}
else
if
(
op2_idx
==
0
)
{
/* res = op X tos */
dst
=
op_ia32_FucomFnstsw
;
flipped
=
!
flipped
;
xchg
=
1
;
}
else
{
...
...
@@ -1424,7 +1421,6 @@ static int sim_FucomFnstsw(x87_state *state, ir_node *n) {
op2_idx
=
op1_idx
;
op1_idx
=
0
;
/* res = tos X op */
dst
=
op_ia32_FucomFnstsw
;
}
}
else
{
/* second live, first operand is dead here, bring it to tos.
...
...
@@ -1437,12 +1433,11 @@ static int sim_FucomFnstsw(x87_state *state, ir_node *n) {
op1_idx
=
0
;
}
/* res = tos X op, pop */
dst
=
op_ia32_FucompFnstsw
;
pop_cnt
=
1
;
pops
=
1
;
}
}
else
{
/* second operand is dead */
if
(
is_vfp_live
(
arch_register_get
_index
(
op1
)
,
live
))
{
if
(
is_vfp_live
(
reg
_index
_1
,
live
))
{
/* first operand is live: bring second to tos.
This means further, op1_idx != op2_idx. */
assert
(
op1_idx
!=
op2_idx
);
...
...
@@ -1453,10 +1448,9 @@ static int sim_FucomFnstsw(x87_state *state, ir_node *n) {
op2_idx
=
0
;
}
/* res = op X tos, pop */
dst
=
op_ia32_FucompFnstsw
;
pops
=
1
;
flipped
=
!
flipped
;
xchg
=
1
;
pop_cnt
=
1
;
}
else
{
/* both operands are dead here, check first for identity. */
if
(
op1_idx
==
op2_idx
)
{
...
...
@@ -1467,8 +1461,7 @@ static int sim_FucomFnstsw(x87_state *state, ir_node *n) {
op2_idx
=
0
;
}
/* res = tos X op, pop */
dst
=
op_ia32_FucompFnstsw
;
pop_cnt
=
1
;
pops
=
1
;
}
/* different, move them to st and st(1) and pop both.
The tricky part is to get one into st(1).*/
...
...
@@ -1481,8 +1474,7 @@ static int sim_FucomFnstsw(x87_state *state, ir_node *n) {
op1_idx
=
0
;
}
/* res = tos X op, pop, pop */
dst
=
op_ia32_FucomppFnstsw
;
pop_cnt
=
2
;
pops
=
2
;
}
else
if
(
op1_idx
==
1
)
{
/* good, first operand is already in the right place, move the second */
if
(
op2_idx
!=
0
)
{
...
...
@@ -1492,10 +1484,9 @@ static int sim_FucomFnstsw(x87_state *state, ir_node *n) {
op2_idx
=
0
;
}
/* res = op X tos, pop, pop */
dst
=
op_ia32_FucomppFnstsw
;
flipped
=
!
flipped
;
xchg
=
1
;
pop
_cnt
=
2
;
pop
s
=
2
;
}
else
{
/* if one is already the TOS, we need two fxch */
if
(
op1_idx
==
0
)
{
...
...
@@ -1506,10 +1497,9 @@ static int sim_FucomFnstsw(x87_state *state, ir_node *n) {
x87_create_fxch
(
state
,
n
,
op2_idx
);
op2_idx
=
0
;
/* res = op X tos, pop, pop */
dst
=
op_ia32_FucomppFnstsw
;
pops
=
2
;
flipped
=
!
flipped
;
xchg
=
1
;
pop_cnt
=
2
;
}
else
if
(
op2_idx
==
0
)
{
/* second one is TOS, move to st(1) */
x87_create_fxch
(
state
,
n
,
1
);
...
...
@@ -1518,8 +1508,7 @@ static int sim_FucomFnstsw(x87_state *state, ir_node *n) {
x87_create_fxch
(
state
,
n
,
op1_idx
);
op1_idx
=
0
;
/* res = tos X op, pop, pop */
dst
=
op_ia32_FucomppFnstsw
;
pop_cnt
=
2
;
pops
=
2
;
}
else
{
/* none of them is either TOS or st(1), 3 fxch needed */
x87_create_fxch
(
state
,
n
,
op2_idx
);
...
...
@@ -1529,46 +1518,66 @@ static int sim_FucomFnstsw(x87_state *state, ir_node *n) {
x87_create_fxch
(
state
,
n
,
op1_idx
);
op1_idx
=
0
;
/* res = tos X op, pop, pop */
dst
=
op_ia32_FucomppFnstsw
;
pop_cnt
=
2
;
pops
=
2
;
}
}
}
}
}
else
{
/* second operand is an address mode */
if
(
is_vfp_live
(
arch_register_get
_index
(
op1
)
,
live
))
{
if
(
is_vfp_live
(
reg
_index
_1
,
live
))
{
/* first operand is live: bring it to TOS */
if
(
op1_idx
!=
0
)
{
x87_create_fxch
(
state
,
n
,
op1_idx
);
op1_idx
=
0
;
}
dst
=
op_ia32_FucomFnstsw
;
}
else
{
/* first operand is dead: bring it to tos */
if
(
op1_idx
!=
0
)
{
x87_create_fxch
(
state
,
n
,
op1_idx
);
op1_idx
=
0
;
}
dst
=
op_ia32_FucompFnstsw
;
pop_cnt
=
1
;
pops
=
1
;
}
}
x87_patch_insn
(
n
,
dst
);
assert
(
pop_cnt
<
3
);
if
(
pop_cnt
>=
2
)
x87_pop
(
state
);
if
(
pop_cnt
>=
1
)
x87_pop
(
state
);
/* patch the operation */
if
(
is_ia32_vFucomFnstsw
(
n
))
{
int
i
;
switch
(
pops
)
{
case
0
:
dst
=
op_ia32_FucomFnstsw
;
break
;
case
1
:
dst
=
op_ia32_FucompFnstsw
;
break
;
case
2
:
dst
=
op_ia32_FucomppFnstsw
;
break
;
default:
panic
(
"invalid popcount in sim_Fucom"
);
}
for
(
i
=
0
;
i
<
pops
;
++
i
)
{
x87_pop
(
state
);
}
}
else
if
(
is_ia32_vFucomi
(
n
))
{
switch
(
pops
)
{
case
0
:
dst
=
op_ia32_Fucomi
;
break
;
case
1
:
dst
=
op_ia32_Fucompi
;
x87_pop
(
state
);
break
;
case
2
:
dst
=
op_ia32_Fucompi
;
x87_pop
(
state
);
x87_create_fpop
(
state
,
sched_next
(
n
),
1
);
node_added
=
NODE_ADDED
;
break
;
default:
panic
(
"invalid popcount in sim_Fucom"
);
}
}
else
{
panic
(
"invalid operation %+F in sim_FucomFnstsw"
,
n
);
}
x87_patch_insn
(
n
,
dst
);
if
(
xchg
)
{
int
tmp
=
op1_idx
;
op1_idx
=
op2_idx
;
op2_idx
=
tmp
;
}
/* patch the operation */
op1
=
&
ia32_st_regs
[
op1_idx
];
attr
->
x87
[
0
]
=
op1
;
if
(
op2_idx
>=
0
)
{
...
...
@@ -1585,7 +1594,7 @@ static int sim_FucomFnstsw(x87_state *state, ir_node *n) {
DB
((
dbg
,
LEVEL_1
,
"<<< %s %s, [AM]
\n
"
,
get_irn_opname
(
n
),
arch_register_get_name
(
op1
)));
return
NO_NODE_ADDED
;
return
node_added
;
}
static
int
sim_Keep
(
x87_state
*
state
,
ir_node
*
node
)
...
...
@@ -1862,18 +1871,16 @@ static ir_node *get_call_result_proj(ir_node *call) {
*
* @param state the x87 state
* @param n the node that should be simulated
* @param arch_env the architecture environment
*
* @return NO_NODE_ADDED
*/
static
int
sim_Call
(
x87_state
*
state
,
ir_node
*
n
,
const
arch_env_t
*
arch_env
)
static
int
sim_Call
(
x87_state
*
state
,
ir_node
*
n
)
{
ir_type
*
call_tp
=
be_Call_get_type
(
n
);
ir_type
*
res_type
;
ir_mode
*
mode
;
ir_node
*
resproj
;
const
arch_register_t
*
reg
;
(
void
)
arch_env
;
DB
((
dbg
,
LEVEL_1
,
">>> %+F
\n
"
,
n
));
...
...
@@ -2266,6 +2273,12 @@ static void x87_simulate_block(x87_simulator *sim, ir_node *block) {
bl_state
->
end
=
state
;
}
/* x87_simulate_block */
static
void
register_sim
(
ir_op
*
op
,
sim_func
func
)
{
assert
(
op
->
ops
.
generic
==
NULL
);
op
->
ops
.
generic
=
(
op_func
)
func
;
}
/**
* Create a new x87 simulator.
*
...
...
@@ -2289,35 +2302,30 @@ static void x87_init_simulator(x87_simulator *sim, ir_graph *irg,
/* set the generic function pointer of instruction we must simulate */
clear_irp_opcodes_generic_func
();
#define ASSOC(op) (op_ ## op)->ops.generic = (op_func)(sim_##op)
#define ASSOC_IA32(op) (op_ia32_v ## op)->ops.generic = (op_func)(sim_##op)
#define ASSOC_BE(op) (op_be_ ## op)->ops.generic = (op_func)(sim_##op)
ASSOC_IA32
(
fld
);
ASSOC_IA32
(
fild
);
ASSOC_IA32
(
fld1
);
ASSOC_IA32
(
fldz
);
ASSOC_IA32
(
fadd
);
ASSOC_IA32
(
fsub
);
ASSOC_IA32
(
fmul
);
ASSOC_IA32
(
fdiv
);
ASSOC_IA32
(
fprem
);
ASSOC_IA32
(
fabs
);
ASSOC_IA32
(
fchs
);
ASSOC_IA32
(
fist
);
ASSOC_IA32
(
fst
);
ASSOC_IA32
(
FucomFnstsw
);
ASSOC_IA32
(
FtstFnstsw
);
ASSOC_BE
(
Copy
);
ASSOC_BE
(
Call
);
ASSOC_BE
(
Spill
);
ASSOC_BE
(
Reload
);
ASSOC_BE
(
Return
);
ASSOC_BE
(
Perm
);
ASSOC_BE
(
Keep
);
ASSOC_BE
(
Barrier
);
#undef ASSOC_BE
#undef ASSOC_IA32
#undef ASSOC
register_sim
(
op_ia32_vfld
,
sim_fld
);
register_sim
(
op_ia32_vfild
,
sim_fild
);
register_sim
(
op_ia32_vfld1
,
sim_fld1
);
register_sim
(
op_ia32_vfldz
,
sim_fldz
);
register_sim
(
op_ia32_vfadd
,
sim_fadd
);
register_sim
(
op_ia32_vfsub
,
sim_fsub
);
register_sim
(
op_ia32_vfmul
,
sim_fmul
);
register_sim
(
op_ia32_vfdiv
,
sim_fdiv
);
register_sim
(
op_ia32_vfprem
,
sim_fprem
);
register_sim
(
op_ia32_vfabs
,
sim_fabs
);
register_sim
(
op_ia32_vfchs
,
sim_fchs
);
register_sim
(
op_ia32_vfist
,
sim_fist
);
register_sim
(
op_ia32_vfst
,
sim_fst
);
register_sim
(
op_ia32_vFtstFnstsw
,
sim_FtstFnstsw
);
register_sim
(
op_ia32_vFucomFnstsw
,
sim_Fucom
);
register_sim
(
op_ia32_vFucomi
,
sim_Fucom
);
register_sim
(
op_be_Copy
,
sim_Copy
);
register_sim
(
op_be_Call
,
sim_Call
);
register_sim
(
op_be_Spill
,
sim_Spill
);
register_sim
(
op_be_Reload
,
sim_Reload
);
register_sim
(
op_be_Return
,
sim_Return
);
register_sim
(
op_be_Perm
,
sim_Perm
);
register_sim
(
op_be_Keep
,
sim_Keep
);
register_sim
(
op_be_Barrier
,
sim_Barrier
);
}
/* x87_init_simulator */
/**
...
...
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