Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
d54ff09c
Commit
d54ff09c
authored
Sep 19, 2015
by
Matthias Braun
Browse files
amd64: Start using x87_sim
parent
ccb426a1
Changes
12
Hide whitespace changes
Inline
Side-by-side
ir/be/amd64/amd64_emitter.c
View file @
d54ff09c
...
...
@@ -343,6 +343,8 @@ static void amd64_emit_am(const ir_node *const node, bool indirect_star)
goto
emit_addr
;
}
case
AMD64_OP_ADDR
:
case
AMD64_OP_X87_ADDR
:
case
AMD64_OP_X87_ADDR_REG
:
if
(
indirect_star
)
be_emit_char
(
'*'
);
goto
emit_addr
;
...
...
@@ -504,8 +506,19 @@ end_of_mods:
amd64_addr_attr_t
const
*
const
attr
=
get_amd64_addr_attr_const
(
node
);
amd64_emit_x87_mode_suffix
(
attr
->
insn_mode
);
}
else
goto
unknown
;
}
else
if
(
*
fmt
==
'P'
)
{
++
fmt
;
x87_attr_t
const
*
const
attr
=
amd64_get_x87_attr_const
(
node
);
if
(
attr
->
pop
)
be_emit_char
(
'p'
);
}
else
{
x87_attr_t
const
*
const
attr
=
amd64_get_x87_attr_const
(
node
);
char
const
*
const
fmt
=
attr
->
res_in_reg
?
"%%st, %%%s"
:
"%%%s, %%st"
;
be_emit_irprintf
(
fmt
,
attr
->
reg
->
name
);
}
break
;
}
...
...
ir/be/amd64/amd64_new_nodes.c
View file @
d54ff09c
...
...
@@ -45,6 +45,28 @@ amd64_insn_mode_t get_amd64_insn_mode(const ir_node *node)
}
}
x87_attr_t
*
amd64_get_x87_attr
(
ir_node
*
const
node
)
{
amd64_attr_t
const
*
const
attr
=
get_amd64_attr_const
(
node
);
switch
(
attr
->
op_mode
)
{
case
AMD64_OP_X87
:
return
&
get_amd64_x87_attr
(
node
)
->
x87
;
case
AMD64_OP_X87_ADDR
:
panic
(
"TODO"
);
case
AMD64_OP_X87_ADDR_REG
:
return
&
get_amd64_x87_binop_addr_attr
(
node
)
->
x87
;
default:
break
;
}
panic
(
"try to get x87 attr from invalid node '%s'"
,
node
);
}
x87_attr_t
const
*
amd64_get_x87_attr_const
(
ir_node
const
*
const
node
)
{
/* hacky */
return
amd64_get_x87_attr
((
ir_node
*
)
node
);
}
int
get_insn_mode_bits
(
amd64_insn_mode_t
insn_mode
)
{
switch
(
insn_mode
)
{
...
...
@@ -61,19 +83,21 @@ int get_insn_mode_bits(amd64_insn_mode_t insn_mode)
static
const
char
*
get_op_mode_string
(
amd64_op_mode_t
mode
)
{
switch
(
mode
)
{
case
AMD64_OP_ADDR_IMM
:
return
"addr+imm"
;
case
AMD64_OP_ADDR_REG
:
return
"addr+reg"
;
case
AMD64_OP_ADDR
:
return
"addr"
;
case
AMD64_OP_IMM32
:
return
"imm32"
;
case
AMD64_OP_IMM64
:
return
"imm64"
;
case
AMD64_OP_NONE
:
return
"none"
;
case
AMD64_OP_REG_ADDR
:
return
"reg+addr"
;
case
AMD64_OP_REG_IMM
:
return
"reg+imm"
;
case
AMD64_OP_REG_REG
:
return
"reg+reg"
;
case
AMD64_OP_REG
:
return
"reg"
;
case
AMD64_OP_SHIFT_IMM
:
return
"shift_imm"
;
case
AMD64_OP_SHIFT_REG
:
return
"shift_reg"
;
case
AMD64_OP_X87
:
return
"x87"
;
case
AMD64_OP_ADDR_IMM
:
return
"addr+imm"
;
case
AMD64_OP_ADDR_REG
:
return
"addr+reg"
;
case
AMD64_OP_ADDR
:
return
"addr"
;
case
AMD64_OP_IMM32
:
return
"imm32"
;
case
AMD64_OP_IMM64
:
return
"imm64"
;
case
AMD64_OP_NONE
:
return
"none"
;
case
AMD64_OP_REG_ADDR
:
return
"reg+addr"
;
case
AMD64_OP_REG_IMM
:
return
"reg+imm"
;
case
AMD64_OP_REG_REG
:
return
"reg+reg"
;
case
AMD64_OP_REG
:
return
"reg"
;
case
AMD64_OP_SHIFT_IMM
:
return
"shift_imm"
;
case
AMD64_OP_SHIFT_REG
:
return
"shift_reg"
;
case
AMD64_OP_X87
:
return
"x87"
;
case
AMD64_OP_X87_ADDR
:
return
"x87+addr"
;
case
AMD64_OP_X87_ADDR_REG
:
return
"x87+addr+reg"
;
}
return
"invalid op_mode"
;
}
...
...
@@ -281,5 +305,26 @@ static int amd64_call_addr_attrs_equal(const ir_node *const a,
return
amd64_addr_attrs_equal
(
a
,
b
)
&&
attr_a
->
call_tp
==
attr_b
->
call_tp
;
}
static
int
amd64_x87_attrs_equal
(
const
ir_node
*
const
a
,
const
ir_node
*
const
b
)
{
/* we ignore x87 attributes for now */
return
amd64_attrs_equal
(
a
,
b
);
}
static
int
amd64_x87_addr_attrs_equal
(
const
ir_node
*
const
a
,
const
ir_node
*
const
b
)
{
/* ignore x87 part for now */
return
amd64_addr_attrs_equal
(
a
,
b
);
}
static
int
amd64_x87_binop_addr_attrs_equal
(
const
ir_node
*
const
a
,
const
ir_node
*
const
b
)
{
/* ignore x87 part for now */
return
amd64_binop_addr_attrs_equal
(
a
,
b
);
}
/* Include the generated constructor functions */
#include
"gen_amd64_new_nodes.c.inl"
ir/be/amd64/amd64_new_nodes.h
View file @
d54ff09c
...
...
@@ -32,7 +32,8 @@ static inline bool amd64_has_binop_attr(const ir_node *node)
||
attr
->
op_mode
==
AMD64_OP_REG_IMM
||
attr
->
op_mode
==
AMD64_OP_REG_ADDR
||
attr
->
op_mode
==
AMD64_OP_ADDR_REG
||
attr
->
op_mode
==
AMD64_OP_ADDR_IMM
;
||
attr
->
op_mode
==
AMD64_OP_ADDR_IMM
||
attr
->
op_mode
==
AMD64_OP_X87_ADDR_REG
;
}
static
inline
bool
amd64_has_addr_attr
(
const
ir_node
*
node
)
...
...
@@ -41,7 +42,8 @@ static inline bool amd64_has_addr_attr(const ir_node *node)
return
amd64_has_binop_attr
(
node
)
||
attr
->
op_mode
==
AMD64_OP_ADDR
||
attr
->
op_mode
==
AMD64_OP_REG
||
attr
->
op_mode
==
AMD64_OP_IMM32
;
||
attr
->
op_mode
==
AMD64_OP_IMM32
||
attr
->
op_mode
==
AMD64_OP_X87_ADDR
;
}
static
inline
amd64_addr_attr_t
*
get_amd64_addr_attr
(
ir_node
*
node
)
...
...
@@ -147,6 +149,29 @@ static inline amd64_call_addr_attr_t *get_amd64_call_addr_attr(ir_node *node)
return
(
amd64_call_addr_attr_t
*
)
get_irn_generic_attr
(
node
);
}
static
inline
const
amd64_x87_attr_t
*
get_amd64_x87_attr_const
(
const
ir_node
*
node
)
{
assert
(
get_amd64_attr_const
(
node
)
->
op_mode
==
AMD64_OP_X87
);
return
(
const
amd64_x87_attr_t
*
)
get_irn_generic_attr_const
(
node
);
}
static
inline
amd64_x87_attr_t
*
get_amd64_x87_attr
(
ir_node
*
node
)
{
assert
(
get_amd64_attr_const
(
node
)
->
op_mode
==
AMD64_OP_X87
);
return
(
amd64_x87_attr_t
*
)
get_irn_generic_attr
(
node
);
}
static
inline
amd64_x87_binop_addr_attr_t
*
get_amd64_x87_binop_addr_attr
(
ir_node
*
const
node
)
{
assert
(
get_amd64_attr_const
(
node
)
->
op_mode
==
AMD64_OP_X87_ADDR_REG
);
return
(
amd64_x87_binop_addr_attr_t
*
)
get_irn_generic_attr
(
node
);
}
x87_attr_t
*
amd64_get_x87_attr
(
ir_node
*
node
);
x87_attr_t
const
*
amd64_get_x87_attr_const
(
ir_node
const
*
node
);
amd64_insn_mode_t
get_amd64_insn_mode
(
const
ir_node
*
node
);
int
get_insn_mode_bits
(
amd64_insn_mode_t
insn_mode
);
...
...
ir/be/amd64/amd64_nodes_attr.h
View file @
d54ff09c
...
...
@@ -12,10 +12,11 @@
#include
<stdint.h>
#include
"../ia32/x86_asm.h"
#include
"../ia32/x86_cc.h"
#include
"../ia32/x86_x87.h"
#include
"compiler.h"
#include
"irnode_t.h"
#include
"../ia32/x86_cc.h"
#include
"../ia32/x86_asm.h"
enum
amd64_arch_irn_flags_t
{
amd64_arch_irn_flag_commutative_binop
=
arch_irn_flag_backend
<<
0
,
...
...
@@ -55,6 +56,8 @@ typedef enum {
AMD64_OP_SHIFT_REG
,
AMD64_OP_SHIFT_IMM
,
AMD64_OP_X87
,
AMD64_OP_X87_ADDR
,
AMD64_OP_X87_ADDR_REG
,
}
amd64_op_mode_t
;
enum
{
...
...
@@ -125,4 +128,19 @@ typedef struct {
ir_type
*
call_tp
;
}
amd64_call_addr_attr_t
;
typedef
struct
{
amd64_attr_t
base
;
x87_attr_t
x87
;
}
amd64_x87_attr_t
;
typedef
struct
{
amd64_addr_attr_t
base
;
x87_attr_t
x87
;
}
amd64_x87_addr_attr_t
;
typedef
struct
{
amd64_binop_addr_attr_t
base
;
x87_attr_t
x87
;
}
amd64_x87_binop_addr_attr_t
;
#endif
ir/be/amd64/amd64_spec.pl
View file @
d54ff09c
...
...
@@ -90,6 +90,17 @@ $mode_x87 = "x86_mode_E";
amd64_call_addr_attr_t
=>
"
be_info_init_irn(res, irn_flags, in_reqs, n_res);
\n
"
.
"
\t
*attr = *attr_init;
",
amd64_x87_attr_t
=>
"
init_amd64_attributes(res, irn_flags, in_reqs, n_res, AMD64_OP_X87);
\n
",
amd64_x87_addr_attr_t
=>
"
init_amd64_attributes(res, irn_flags, in_reqs, n_res, op_mode);
\n
"
.
"
\t
attr->base.insn_mode = insn_mode;
\n
"
.
"
\t
attr->base.addr = addr;
\n
",
amd64_x87_binop_addr_attr_t
=>
"
be_info_init_irn(res, irn_flags, in_reqs, n_res);
\n
"
.
"
\t
attr->base = *attr_init;
\n
"
.
"
\t
assert(attr_init->base.base.op_mode == AMD64_OP_ADDR_REG);
\n
"
.
"
\t
attr->base.base.base.op_mode = AMD64_OP_X87_ADDR_REG;
\n
",
);
my
$binop
=
{
...
...
@@ -742,7 +753,7 @@ fld => {
in_reqs
=>
"
...
",
out_reqs
=>
[
"
x87
",
"
none
",
"
mem
"
],
outs
=>
[
"
res
",
"
unused
",
"
M
"
],
attr_type
=>
"
amd64_addr_attr_t
",
attr_type
=>
"
amd64_
x87_
addr_attr_t
",
attr
=>
"
amd64_insn_mode_t insn_mode, amd64_op_mode_t op_mode, amd64_addr_t addr
",
emit
=>
"
fld%FM %AM
",
},
...
...
@@ -753,10 +764,22 @@ fst => {
in_reqs
=>
"
...
",
out_reqs
=>
[
"
mem
"
],
outs
=>
[
"
M
"
],
attr_type
=>
"
amd64_binop_addr_attr_t
",
attr_type
=>
"
amd64_
x87_
binop_addr_attr_t
",
attr
=>
"
const amd64_binop_addr_attr_t *attr_init
",
mode
=>
"
mode_M
",
emit
=>
"
fst%FM %AM
",
emit
=>
"
fst%FP%FM %AM
",
},
fstp
=>
{
op_flags
=>
[
"
uses_memory
"
],
state
=>
"
exc_pinned
",
in_reqs
=>
"
...
",
out_reqs
=>
[
"
mem
"
],
outs
=>
[
"
M
"
],
attr_type
=>
"
amd64_x87_binop_addr_attr_t
",
attr
=>
"
const amd64_binop_addr_attr_t *attr_init
",
mode
=>
"
mode_M
",
emit
=>
"
fstp%FM %AM
",
},
fchs
=>
{
...
...
@@ -764,4 +787,34 @@ fchs => {
emit
=>
"
fchs
",
},
fdup
=>
{
in_reqs
=>
[
"
x87
"
],
out_reqs
=>
[
"
x87
"
],
ins
=>
[
"
val
"
],
attrs_equal
=>
"
attrs_equal_false
",
attr_type
=>
"
amd64_x87_attr_t
",
attr
=>
"
const arch_register_t *reg
",
init
=>
"
attr->x87.reg = reg;
",
emit
=>
"
fld %F0
",
},
fxch
=>
{
op_flags
=>
[
"
keep
"
],
out_reqs
=>
[
"
none
"
],
attrs_equal
=>
"
attrs_equal_false
",
attr_type
=>
"
amd64_x87_attr_t
",
attr
=>
"
const arch_register_t *reg
",
init
=>
"
attr->x87.reg = reg;
",
emit
=>
"
fxch %F0
",
},
fpop
=>
{
op_flags
=>
[
"
keep
"
],
out_reqs
=>
[
"
none
"
],
attr_type
=>
"
amd64_x87_attr_t
",
attr
=>
"
const arch_register_t *reg
",
init
=>
"
attr->x87.reg = reg;
",
emit
=>
"
fstp %F0
",
},
);
ir/be/amd64/amd64_transform.c
View file @
d54ff09c
...
...
@@ -132,6 +132,12 @@ static const arch_register_req_t amd64_requirement_xmm_same_0_not_1 = {
.
width
=
1
,
};
static
const
arch_register_req_t
amd64_requirement_x87killed
=
{
.
cls
=
&
amd64_reg_classes
[
CLASS_amd64_x87
],
.
width
=
1
,
.
kills_value
=
true
,
};
static
const
arch_register_req_t
*
mem_reqs
[]
=
{
&
arch_memory_requirement
,
};
...
...
@@ -157,8 +163,8 @@ static const arch_register_req_t *xmm_mem_reqs[] = {
&
arch_memory_requirement
,
};
static
const
arch_register_req_t
*
x87_mem_reqs
[]
=
{
&
amd64_
class_reg_req_x87
,
static
const
arch_register_req_t
*
x87
K
_mem_reqs
[]
=
{
&
amd64_
requirement_x87killed
,
&
arch_memory_requirement
,
};
...
...
@@ -180,6 +186,12 @@ static const arch_register_req_t *x87_reg_mem_reqs[] = {
&
arch_memory_requirement
,
};
static
const
arch_register_req_t
*
x87K_reg_mem_reqs
[]
=
{
&
amd64_requirement_x87killed
,
&
amd64_class_reg_req_gp
,
&
arch_memory_requirement
,
};
static
const
arch_register_req_t
*
reg_reg_reg_mem_reqs
[]
=
{
&
amd64_class_reg_req_gp
,
&
amd64_class_reg_req_gp
,
...
...
@@ -194,8 +206,8 @@ static const arch_register_req_t *xmm_reg_reg_mem_reqs[] = {
&
arch_memory_requirement
,
};
static
const
arch_register_req_t
*
x87_reg_reg_mem_reqs
[]
=
{
&
amd64_
class_reg_req_x87
,
static
const
arch_register_req_t
*
x87
K
_reg_reg_mem_reqs
[]
=
{
&
amd64_
requirement_x87killed
,
&
amd64_class_reg_req_gp
,
&
amd64_class_reg_req_gp
,
&
arch_memory_requirement
,
...
...
@@ -279,12 +291,12 @@ static arch_register_req_t const **const xmm_am_reqs[] = {
xmm_reg_reg_mem_reqs
,
};
static
arch_register_req_t
const
**
const
x87_am_reqs
[]
=
{
static
arch_register_req_t
const
**
const
x87
K
_am_reqs
[]
=
{
NULL
,
mem_reqs
,
x87_mem_reqs
,
x87_reg_mem_reqs
,
x87_reg_reg_mem_reqs
,
x87
K
_mem_reqs
,
x87
K
_reg_mem_reqs
,
x87
K
_reg_reg_mem_reqs
,
};
static
inline
bool
mode_needs_gp_reg
(
ir_mode
*
mode
)
...
...
@@ -1728,7 +1740,7 @@ no_call_mem:
ir_node
*
const
nomem
=
get_irg_no_mem
(
irg
);
ir_node
*
const
in
[]
=
{
new_value
,
callframe
,
nomem
};
ir_node
*
const
store
=
mode_is_float
(
mode
)
?
(
mode
==
x86_mode_E
?
new_bd_amd64_fst
(
dbgi
,
new_block
,
ARRAY_SIZE
(
in
),
in
,
x87_reg_mem_reqs
,
&
attr
)
(
mode
==
x86_mode_E
?
new_bd_amd64_fst
p
(
dbgi
,
new_block
,
ARRAY_SIZE
(
in
),
in
,
x87
K
_reg_mem_reqs
,
&
attr
)
:
new_bd_amd64_movs_store_xmm
(
dbgi
,
new_block
,
ARRAY_SIZE
(
in
),
in
,
xmm_reg_mem_reqs
,
&
attr
))
:
new_bd_amd64_mov_store
(
dbgi
,
new_block
,
ARRAY_SIZE
(
in
),
in
,
reg_reg_mem_reqs
,
&
attr
);
...
...
@@ -2097,6 +2109,7 @@ static ir_node *conv_x87_to_sse(dbg_info *dbgi, ir_node *block, ir_node *op,
ir_node
*
in
[
5
];
int
n_in
=
0
;
amd64_addr_t
addr
;
assert
(
get_mode_size_bits
(
dst_mode
)
<=
64
);
store_to_temp
(
new_bd_amd64_fst
,
&
addr
,
dbgi
,
block
,
in
,
&
n_in
,
op
,
dst_mode
);
assert
(
n_in
<
(
int
)
ARRAY_SIZE
(
in
));
...
...
@@ -2302,12 +2315,12 @@ static ir_node *gen_Store(ir_node *const node)
attr
.
base
.
insn_mode
=
get_insn_mode_from_mode
(
mode
);
arch_register_req_t
const
**
const
reqs
=
(
mode_is_float
(
mode
)
?
(
mode
==
x86_mode_E
?
x87_am_reqs
=
(
mode_is_float
(
mode
)
?
(
mode
==
x86_mode_E
?
x87
K
_am_reqs
:
xmm_am_reqs
)
:
gp_am_reqs
)[
arity
];
new_store_func
const
cons
=
mode_is_float
(
mode
)
?
(
mode
==
x86_mode_E
?
&
new_bd_amd64_fst
=
mode_is_float
(
mode
)
?
(
mode
==
x86_mode_E
?
&
new_bd_amd64_fst
p
:
&
new_bd_amd64_movs_store_xmm
)
:
&
new_bd_amd64_mov_store
;
ir_node
*
const
new_store
=
cons
(
dbgi
,
block
,
arity
,
in
,
reqs
,
&
attr
);
...
...
ir/be/amd64/amd64_x87.c
0 → 100644
View file @
d54ff09c
#include
"panic.h"
#include
"bearch_amd64_t.h"
#include
"amd64_new_nodes.h"
#include
"gen_amd64_regalloc_if.h"
#include
"../ia32/x86_x87.h"
static
unsigned
get_bits_from_insn_mode
(
amd64_insn_mode_t
const
insn_mode
)
{
switch
(
insn_mode
)
{
case
INSN_MODE_8
:
return
8
;
case
INSN_MODE_16
:
return
16
;
case
INSN_MODE_32
:
return
32
;
case
INSN_MODE_64
:
return
64
;
case
INSN_MODE_128
:
return
128
;
case
INSN_MODE_INVALID
:
break
;
}
panic
(
"invalid insn_mode"
);
}
static
void
sim_amd64_fst
(
x87_state
*
const
state
,
ir_node
*
const
node
)
{
amd64_addr_attr_t
const
*
const
attr
=
get_amd64_addr_attr_const
(
node
);
unsigned
const
bits
=
get_bits_from_insn_mode
(
attr
->
insn_mode
);
x86_sim_x87_store
(
state
,
node
,
0
,
bits
);
}
static
void
sim_amd64_fstp
(
x87_state
*
const
state
,
ir_node
*
const
node
)
{
x86_sim_x87_store_pop
(
state
,
node
,
0
);
}
static
void
sim_amd64_fld
(
x87_state
*
const
state
,
ir_node
*
const
node
)
{
ir_node
*
const
value
=
get_Proj_for_pn
(
node
,
pn_amd64_fld_res
);
x86_sim_x87_load
(
state
,
node
,
value
);
}
static
void
prepare_callbacks
(
void
)
{
x86_prepare_x87_callbacks
();
x86_register_x87_sim
(
op_amd64_fld
,
sim_amd64_fld
);
x86_register_x87_sim
(
op_amd64_fst
,
sim_amd64_fst
);
x86_register_x87_sim
(
op_amd64_fstp
,
sim_amd64_fstp
);
x86_register_x87_sim
(
op_amd64_ret
,
x86_sim_x87_ret
);
}
void
amd64_simulate_graph_x87
(
ir_graph
*
irg
)
{
prepare_callbacks
();
const
x87_simulator_config_t
config
=
{
.
regclass
=
&
amd64_reg_classes
[
CLASS_amd64_x87
],
.
new_bd_fdup
=
new_bd_amd64_fdup
,
.
new_bd_fxch
=
new_bd_amd64_fxch
,
.
new_bd_fpop
=
new_bd_amd64_fpop
,
.
get_x87_attr
=
amd64_get_x87_attr
,
};
x86_x87_simulate_graph
(
irg
,
&
config
);
}
ir/be/amd64/bearch_amd64.c
View file @
d54ff09c
...
...
@@ -637,6 +637,8 @@ static void amd64_finish_and_emit(ir_graph *irg)
/* Fix 2-address code constraints. */
amd64_finish_irg
(
irg
);
amd64_simulate_graph_x87
(
irg
);
/* emit code */
be_timer_push
(
T_EMIT
);
amd64_emit_function
(
irg
);
...
...
ir/be/amd64/bearch_amd64_t.h
View file @
d54ff09c
...
...
@@ -38,4 +38,6 @@ void amd64_cconv_init(void);
void
amd64_adjust_pic
(
ir_graph
*
irg
);
void
amd64_simulate_graph_x87
(
ir_graph
*
irg
);
#endif
ir/be/ia32/bearch_ia32.c
View file @
d54ff09c
...
...
@@ -1107,6 +1107,12 @@ static void introduce_prologue_epilogue(ir_graph *const irg)
introduce_prologue
(
irg
);
}
static
x87_attr_t
*
ia32_get_x87_attr
(
ir_node
*
const
node
)
{
ia32_x87_attr_t
*
const
attr
=
get_ia32_x87_attr
(
node
);
return
&
attr
->
x87
;
}
static
void
ia32_emit
(
ir_graph
*
irg
)
{
/*
...
...
@@ -1140,6 +1146,7 @@ static void ia32_emit(ir_graph *irg)
/* we might have to rewrite x87 virtual registers */
ia32_irg_data_t
const
*
const
irg_data
=
ia32_get_irg_data
(
irg
);
if
(
irg_data
->
do_x87_sim
)
{
x86_prepare_x87_callbacks_ia32
();
const
x87_simulator_config_t
config
=
{
.
regclass
=
&
ia32_reg_classes
[
CLASS_ia32_fp
],
.
new_bd_fdup
=
new_bd_ia32_fdup
,
...
...
@@ -1147,6 +1154,7 @@ static void ia32_emit(ir_graph *irg)
.
new_bd_fpop
=
new_bd_ia32_fpop
,
.
new_bd_ffreep
=
ia32_cg_config
.
use_ffreep
?
new_bd_ia32_ffreep
:
NULL
,
.
get_x87_attr
=
ia32_get_x87_attr
,
};
x86_x87_simulate_graph
(
irg
,
&
config
);
}
...
...
ir/be/ia32/x86_x87.c
View file @
d54ff09c
...
...
@@ -68,19 +68,11 @@ typedef struct st_entry {
/**
* The x87 state.
*/
typedef
struct
x87_state
{
struct
x87_state
{
st_entry
st
[
N_X87_REGS
];
/**< the register stack */
unsigned
depth
;
/**< the current stack depth */
x87_simulator
*
sim
;
/**< The simulator. */
}
x87_state
;
/**
* The type of an instruction simulator function.
*
* @param state the x87 state
* @param n the node to be simulated
*/
typedef
void
(
*
sim_func
)(
x87_state
*
state
,
ir_node
*
n
);
};
/**
* A block state: Every block has a x87 state at the beginning and at the end.
...
...
@@ -786,26 +778,29 @@ static void sim_unop(x87_state *state, ir_node *n)
* @param state the x87 state
* @param n the node that should be simulated (and patched)
*/
static
void
sim
_load
(
x87_state
*
state
,
ir_node
*
n
)
void
x86_sim_x87
_load
(
x87_state
*
state
,
ir_node
*
n
,
ir_node
*
value
)
{
assert
((
unsigned
)
pn_ia32_fld_res
==
(
unsigned
)
pn_ia32_fild_res
&&
(
unsigned
)
pn_ia32_fld_res
==
(
unsigned
)
pn_ia32_fld1_res
&&
(
unsigned
)
pn_ia32_fld_res
==
(
unsigned
)
pn_ia32_fldz_res
);
DB
((
dbg
,
LEVEL_1
,
">>> %+F
\n
"
,
n
));
x87_push
(
state
,
get_result_node
(
n
)
);
x87_push
(
state
,
value
);
DB
((
dbg
,
LEVEL_1
,
"<<< %s -> %s
\n
"
,
get_irn_opname
(
n
),
get_st_reg
(
0
)
->
name
));
}
static
void
sim_ia32_x87_load
(
x87_state
*
state
,
ir_node
*
n
)
{
ir_node
*
value
=
get_result_node
(
n
);
x86_sim_x87_load
(
state
,
n
,
value
);
}
/**
* Simulate a virtual Store.
*
* @param state the x87 state
* @param n the node that should be simulated (and patched)
*/
static
void
sim_store
(
x87_state
*
state
,
ir_node
*
n
)
void
x86_sim_x87_store
(
x87_state
*
state
,
ir_node
*
n
,
int
val_pos
,
unsigned
store_bits
)
{
ir_node
*
const
val
=
get_irn_n
(
n
,
n_ia32_fst_val
);
ir_node
*
const
val
=
get_irn_n
(
n
,
val_pos
);
DB
((
dbg
,
LEVEL_1
,
">>> %+F %+F ->
\n
"
,
n
,
val
));
fp_liveness
const
live
=
fp_live_args_after
(
state
->
sim
,
n
,
0
);
...
...
@@ -814,9 +809,7 @@ static void sim_store(x87_state *state, ir_node *n)
move_to_tos
(
state
,
n
,
val
);
goto
do_pop
;
}
else
{
ir_mode
*
const
mode
=
get_ia32_ls_mode
(
n
);
assert
(
!
mode_is_int
(
mode
)
||
get_mode_size_bits
(
mode
)
<=
32
);
if
(
get_mode_size_bits
(
mode
)
>
64
)
{
if
(
store_bits
>
64
)
{
/* Problem: fst doesn't support 80bit modes. Code selection chooses
* an explicit fstp in this case which is fine, however if we create
* an 80bit fst because of a spill we may need some fixup here.
...
...
@@ -838,7 +831,7 @@ do_pop:
ir_node
*
const
mem
=
get_Proj_for_pn
(
n
,
pn_ia32_st_M
);
ir_node
*
const
base
=
get_irn_n
(
n
,
n_ia32_base
);
ir_node
*
const
idx
=
get_irn_n
(
n
,
n_ia32_index
);
ir_node
*
const
vfld
=
new_bd_ia32_fld
(
NULL
,
block
,
base
,
idx
,
mem
,
mode
);
ir_node
*
const
vfld
=
new_bd_ia32_fld
(
NULL
,
block
,
base
,
idx
,
mem
,
x86_
mode
_E
);
/* copy all attributes */
ia32_copy_am_attrs
(
vfld
,
n
);
...
...
@@ -864,7 +857,7 @@ do_pop:
be_ssa_construction_destroy
(
&
env
);
}
get_ia32
_x87_attr
(
n
)
->
x87
.
pop
=
true
;
x87
.
get
_x87_attr
(
n
)
->
pop
=
true
;
}
else
{
/* we can only store the tos to memory */
move_to_tos
(
state
,
n
,
val
);
...
...
@@ -874,26 +867,50 @@ do_pop:
DB
((
dbg
,
LEVEL_1
,
"<<< %s %s ->
\n
"
,
get_irn_opname
(
n
),
get_st_reg
(
0
)
->
name
));
}
/**
* Simulate a virtual fisttp.
*
* @param state the x87 state
* @param n the node that should be simulated (and patched)
*/
static
void
sim_store_pop
(
x87_state
*
state
,
ir_node
*
n
)
static
void
sim_ia32_fst
(
x87_state
*
state
,
ir_node
*
n
)
{
unsigned
bits
=
get_mode_size_bits
(
get_ia32_ls_mode
(
n
));
x86_sim_x87_store
(
state
,
n
,
n_ia32_fst_val
,
bits
);
}
static
void
sim_ia32_fist
(
x87_state
*
state
,
ir_node
*
n
)
{
unsigned
bits
=
get_mode_size_bits
(
get_ia32_ls_mode
(
n
));
x86_sim_x87_store
(
state
,
n
,
n_ia32_fist_val
,
bits
);
}
void
x86_sim_x87_store_pop
(
x87_state
*
const
state
,
ir_node
*
const
node
,
int
const
val_pos
)
{
assert
((
int
)
n_ia32_fisttp_val
==
(
int
)
n_ia32_fistp_val
);
ir_node
*
const
val
=
get_irn_n
(
n
,
n_ia32_fisttp_val
);
DB
((
dbg
,
LEVEL_1
,
">>> %+F %s ->
\n
"
,
n
,
arch_get_irn_register
(
val
)
->
name
));