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
a10617f2
Commit
a10617f2
authored
Sep 20, 2006
by
Matthias Braun
Browse files
- Properly support AM for push and pop nodes
- Fix Projs returning wrong register requirements for in positions
parent
657d38c5
Changes
7
Hide whitespace changes
Inline
Side-by-side
ir/be/ia32/bearch_ia32.c
View file @
a10617f2
...
...
@@ -112,6 +112,11 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_re
DBG
((
mod
,
LEVEL_1
,
"get requirements at pos %d for %+F ... "
,
pos
,
irn
));
if
(
is_Proj
(
irn
))
{
if
(
pos
>=
0
)
{
DBG
((
mod
,
LEVEL_1
,
"ignoring request IN requirements for node %+F
\n
"
,
irn
));
return
NULL
;
}
if
(
pos
==
-
1
)
{
node_pos
=
ia32_translate_proj_pos
(
irn
);
}
...
...
@@ -381,10 +386,11 @@ static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap
ir_node
*
bl
=
get_irg_start_block
(
env
->
irg
);
ir_node
*
curr_sp
=
be_abi_reg_map_get
(
reg_map
,
env
->
isa
->
sp
);
ir_node
*
curr_bp
=
be_abi_reg_map_get
(
reg_map
,
env
->
isa
->
bp
);
ir_node
*
noreg
=
be_abi_reg_map_get
(
reg_map
,
&
ia32_gp_regs
[
REG_GP_NOREG
]);
ir_node
*
push
;
/* push ebp */
push
=
new_rd_ia32_Push
(
NULL
,
env
->
irg
,
bl
,
curr_
s
p
,
curr_
b
p
,
*
mem
);
push
=
new_rd_ia32_Push
(
NULL
,
env
->
irg
,
bl
,
noreg
,
noreg
,
curr_
b
p
,
curr_
s
p
,
*
mem
);
curr_sp
=
new_r_Proj
(
env
->
irg
,
bl
,
push
,
get_irn_mode
(
curr_sp
),
pn_ia32_Push_stack
);
*
mem
=
new_r_Proj
(
env
->
irg
,
bl
,
push
,
mode_M
,
pn_ia32_Push_M
);
...
...
@@ -450,13 +456,14 @@ static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_
*
mem
=
new_r_Proj
(
current_ir_graph
,
bl
,
leave
,
mode_M
,
pn_ia32_Leave_M
);
}
else
{
ir_node
*
noreg
=
be_abi_reg_map_get
(
reg_map
,
&
ia32_gp_regs
[
REG_GP_NOREG
]);
ir_node
*
pop
;
/* copy ebp to esp */
curr_sp
=
be_new_SetSP
(
env
->
isa
->
sp
,
env
->
irg
,
bl
,
curr_sp
,
curr_bp
,
*
mem
);
/* pop ebp */
pop
=
new_rd_ia32_Pop
(
NULL
,
env
->
irg
,
bl
,
curr_sp
,
*
mem
);
pop
=
new_rd_ia32_Pop
(
NULL
,
env
->
irg
,
bl
,
noreg
,
noreg
,
curr_sp
,
*
mem
);
set_ia32_flags
(
pop
,
arch_irn_flags_ignore
);
curr_bp
=
new_r_Proj
(
current_ir_graph
,
bl
,
pop
,
mode_bp
,
pn_ia32_Pop_res
);
curr_sp
=
new_r_Proj
(
current_ir_graph
,
bl
,
pop
,
get_irn_mode
(
curr_sp
),
pn_ia32_Pop_stack
);
...
...
@@ -1084,42 +1091,42 @@ static void transform_to_Store(ia32_transform_env_t *env) {
exchange
(
irn
,
proj
);
}
static
ir_node
*
create_push
(
ia32_transform_env_t
*
env
,
ir_node
*
schedpoint
,
ir_node
*
sp
,
ir_node
*
mem
,
entity
*
ent
,
const
char
*
offset
)
{
static
ir_node
*
create_push
(
ia32_transform_env_t
*
env
,
ir_node
*
schedpoint
,
ir_node
*
sp
,
ir_node
*
mem
,
entity
*
ent
)
{
ir_node
*
noreg
=
ia32_new_NoReg_gp
(
env
->
cg
);
ir_node
*
frame
=
get_irg_frame
(
env
->
irg
);
ir_node
*
push
=
new_rd_ia32_Push
(
env
->
dbg
,
env
->
irg
,
env
->
block
,
sp
,
noreg
,
mem
);
ir_node
*
push
=
new_rd_ia32_Push
(
env
->
dbg
,
env
->
irg
,
env
->
block
,
frame
,
noreg
,
noreg
,
sp
,
mem
);
set_ia32_frame_ent
(
push
,
ent
);
set_ia32_use_frame
(
push
);
set_ia32_op_type
(
push
,
ia32_AddrModeS
);
set_ia32_am_flavour
(
push
,
ia32_B
);
set_ia32_ls_mode
(
push
,
mode_Is
);
if
(
offset
!=
NULL
)
add_ia32_am_offs
(
push
,
offset
);
sched_add_before
(
schedpoint
,
push
);
return
push
;
}
static
ir_node
*
create_pop
(
ia32_transform_env_t
*
env
,
ir_node
*
schedpoint
,
ir_node
*
sp
,
entity
*
ent
,
const
char
*
offset
)
{
ir_node
*
pop
=
new_rd_ia32_Pop
(
env
->
dbg
,
env
->
irg
,
env
->
block
,
sp
,
new_NoMem
());
static
ir_node
*
create_pop
(
ia32_transform_env_t
*
env
,
ir_node
*
schedpoint
,
ir_node
*
sp
,
entity
*
ent
)
{
ir_node
*
noreg
=
ia32_new_NoReg_gp
(
env
->
cg
);
ir_node
*
frame
=
get_irg_frame
(
env
->
irg
);
ir_node
*
pop
=
new_rd_ia32_Pop
(
env
->
dbg
,
env
->
irg
,
env
->
block
,
frame
,
noreg
,
sp
,
new_NoMem
());
set_ia32_frame_ent
(
pop
,
ent
);
set_ia32_use_frame
(
pop
);
set_ia32_op_type
(
pop
,
ia32_AddrModeD
);
set_ia32_am_flavour
(
pop
,
ia32_B
);
set_ia32_ls_mode
(
pop
,
mode_Is
);
if
(
offset
!=
NULL
)
add_ia32_am_offs
(
pop
,
offset
);
sched_add_before
(
schedpoint
,
pop
);
return
pop
;
}
static
ir_node
*
create_spproj
(
ia32_transform_env_t
*
env
,
ir_node
*
pred
,
int
pos
,
ir_node
*
schedpoint
,
const
ir_node
*
oldsp
)
{
ir_mode
*
spmode
=
get_irn_mode
(
oldsp
)
;
const
arch_register_t
*
spreg
=
arch_get_irn_register
(
env
->
cg
->
arch_env
,
oldsp
)
;
static
ir_node
*
create_spproj
(
ia32_transform_env_t
*
env
,
ir_node
*
pred
,
int
pos
,
ir_node
*
schedpoint
)
{
ir_mode
*
spmode
=
mode_Iu
;
const
arch_register_t
*
spreg
=
&
ia32_gp_regs
[
REG_ESP
]
;
ir_node
*
sp
;
sp
=
new_rd_Proj
(
env
->
dbg
,
env
->
irg
,
env
->
block
,
pred
,
spmode
,
pos
);
...
...
@@ -1129,15 +1136,15 @@ static ir_node* create_spproj(ia32_transform_env_t *env, ir_node *pred, int pos,
return
sp
;
}
/**
* Transform memperm, currently we do this the ugly way and produce
* push/pop into/from memory cascades. This is possible without using
* any registers.
*/
static
void
transform_MemPerm
(
ia32_transform_env_t
*
env
)
{
/*
* Transform memperm, currently we do this the ugly way and produce
* push/pop into/from memory cascades. This is possible without using
* any registers.
*/
ir_node
*
node
=
env
->
irn
;
int
i
,
arity
;
ir_node
*
sp
=
get_irn_n
(
node
,
0
);
ir_node
*
sp
=
be_abi_get_ignore_irn
(
env
->
cg
->
birg
->
abi
,
&
ia32_gp_regs
[
REG_ESP
]
);
const
ir_edge_t
*
edge
;
const
ir_edge_t
*
next
;
ir_node
**
pops
;
...
...
@@ -1155,12 +1162,13 @@ static void transform_MemPerm(ia32_transform_env_t *env) {
assert
(
(
entbits
==
32
||
entbits
==
64
)
&&
"spillslot on x86 should be 32 or 64 bit"
);
push
=
create_push
(
env
,
node
,
sp
,
mem
,
ent
,
NULL
);
sp
=
create_spproj
(
env
,
push
,
0
,
node
,
sp
);
push
=
create_push
(
env
,
node
,
sp
,
mem
,
ent
);
sp
=
create_spproj
(
env
,
push
,
0
,
node
);
if
(
entbits
==
64
)
{
// add another push after the first one
push
=
create_push
(
env
,
node
,
sp
,
mem
,
ent
,
"4"
);
sp
=
create_spproj
(
env
,
push
,
0
,
node
,
sp
);
push
=
create_push
(
env
,
node
,
sp
,
mem
,
ent
);
add_ia32_am_offs_int
(
push
,
4
);
sp
=
create_spproj
(
env
,
push
,
0
,
node
);
}
set_irn_n
(
node
,
i
,
new_Bad
());
...
...
@@ -1176,15 +1184,14 @@ static void transform_MemPerm(ia32_transform_env_t *env) {
assert
(
(
entbits
==
32
||
entbits
==
64
)
&&
"spillslot on x86 should be 32 or 64 bit"
);
pop
=
create_pop
(
env
,
node
,
sp
,
ent
,
NULL
);
pop
=
create_pop
(
env
,
node
,
sp
,
ent
);
if
(
entbits
==
64
)
{
// add another pop after the first one
sp
=
create_spproj
(
env
,
pop
,
1
,
node
,
sp
);
pop
=
create_pop
(
env
,
node
,
sp
,
ent
,
"4"
);
sp
=
create_spproj
(
env
,
pop
,
1
,
node
);
pop
=
create_pop
(
env
,
node
,
sp
,
ent
);
add_ia32_am_offs_int
(
pop
,
4
);
}
//if(i != 0) {
sp
=
create_spproj
(
env
,
pop
,
1
,
node
,
sp
);
//}
sp
=
create_spproj
(
env
,
pop
,
1
,
node
);
pops
[
i
]
=
pop
;
}
...
...
ir/be/ia32/ia32_emitter.c
View file @
a10617f2
...
...
@@ -558,19 +558,25 @@ const char *ia32_emit_unop(const ir_node *n, ia32_emit_env_t *env) {
switch
(
get_ia32_op_type
(
n
))
{
case
ia32_Normal
:
if
(
is_ia32_ImmConst
(
n
)
||
is_ia32_ImmSymConst
(
n
)
)
{
if
(
is_ia32_ImmConst
(
n
))
{
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"%C"
,
n
);
}
else
if
(
is_ia32_ImmSymConst
(
n
))
{
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"OFFSET FLAT:%C"
,
n
);
}
else
{
if
(
is_ia32_MulS
(
n
)
||
is_ia32_Mulh
(
n
))
{
/* MulS and Mulh implicitly multiply by EAX */
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"%4S"
,
n
);
}
else
}
else
if
(
is_ia32_Push
(
n
))
{
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"%3S"
,
n
);
}
else
{
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"%1D"
,
n
);
}
}
break
;
case
ia32_AddrModeD
:
assert
(
!
is_ia32_Push
(
n
));
snprintf
(
buf
,
SNPRINTF_BUF_LEN
,
"%s"
,
ia32_emit_am
(
n
,
env
));
break
;
case
ia32_AddrModeS
:
...
...
@@ -578,7 +584,7 @@ const char *ia32_emit_unop(const ir_node *n, ia32_emit_env_t *env) {
Mulh is emitted via emit_unop
imul [MEM] means EDX:EAX <- EAX * [MEM]
*/
assert
((
is_ia32_Mulh
(
n
)
||
is_ia32_MulS
(
n
))
&&
"Only MulS and Mulh can have AM source as unop"
);
assert
((
is_ia32_Mulh
(
n
)
||
is_ia32_MulS
(
n
)
||
is_ia32_Push
(
n
)
)
&&
"Only MulS and Mulh can have AM source as unop"
);
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"%s"
,
ia32_emit_am
(
n
,
env
));
break
;
default:
...
...
ir/be/ia32/ia32_new_nodes.c
View file @
a10617f2
...
...
@@ -544,7 +544,7 @@ char *get_ia32_am_offs(const ir_node *node) {
ia32_attr_t
*
attr
=
get_ia32_attr
(
node
);
static
char
res
[
64
];
snprintf
(
res
,
sizeof
(
res
),
"%+
l
d"
,
attr
->
am_offs
);
snprintf
(
res
,
sizeof
(
res
),
"%+d"
,
attr
->
am_offs
);
return
res
;
}
...
...
@@ -552,7 +552,7 @@ char *get_ia32_am_offs(const ir_node *node) {
/**
* Gets the addressmode offset as long.
*/
long
get_ia32_am_offs_
long
(
const
ir_node
*
node
)
{
int
get_ia32_am_offs_
int
(
const
ir_node
*
node
)
{
ia32_attr_t
*
attr
=
get_ia32_attr
(
node
);
return
attr
->
am_offs
;
}
...
...
@@ -564,10 +564,13 @@ static void extend_ia32_am_offs(ir_node *node, char *offset, char op) {
ia32_attr_t
*
attr
=
get_ia32_attr
(
node
);
int
res
,
o
;
if
(
!
offset
||
strlen
(
offset
)
<
1
)
if
(
offset
==
NULL
||
offset
[
0
]
==
'\0'
)
return
;
res
=
sscanf
(
offset
,
"%d"
,
&
o
);
if
(
offset
[
0
]
==
'-'
)
res
=
sscanf
(
offset
,
"%d"
,
&
o
);
else
res
=
sscanf
(
offset
,
"%u"
,
&
o
);
assert
(
res
==
1
);
if
(
op
==
'-'
)
...
...
@@ -585,6 +588,11 @@ void add_ia32_am_offs(ir_node *node, const char *offset) {
extend_ia32_am_offs
(
node
,
(
char
*
)
offset
,
'+'
);
}
void
add_ia32_am_offs_int
(
ir_node
*
node
,
int
offset
)
{
ia32_attr_t
*
attr
=
get_ia32_attr
(
node
);
attr
->
am_offs
+=
offset
;
}
/**
* Sub an offset for addrmode.
*/
...
...
ir/be/ia32/ia32_new_nodes.h
View file @
a10617f2
...
...
@@ -74,13 +74,15 @@ char *get_ia32_am_offs(const ir_node *node);
/**
* Gets the addressmode offset as long.
*/
long
get_ia32_am_offs_
long
(
const
ir_node
*
node
);
int
get_ia32_am_offs_
int
(
const
ir_node
*
node
);
/**
* Adds an offset for addrmode.
*/
void
add_ia32_am_offs
(
ir_node
*
node
,
const
char
*
offset
);
void
add_ia32_am_offs_int
(
ir_node
*
node
,
int
offset
);
/**
* Subs an offset for addrmode.
*/
...
...
ir/be/ia32/ia32_nodes_attr.h
View file @
a10617f2
...
...
@@ -101,7 +101,7 @@ typedef struct _ia32_attr_t {
unsigned
n_res
:
6
;
/**< number of results produced by this node */
}
data
;
long
am_offs
;
/**< offsets for AddrMode */
int
am_offs
;
/**< offsets for AddrMode */
ident
*
am_sc
;
/**< SymConst for AddrMode */
union
{
...
...
ir/be/ia32/ia32_optimize.c
View file @
a10617f2
...
...
@@ -241,7 +241,7 @@ static void ia32_transform_const(ir_node *irn, void *env) {
tenv
.
irn
=
irn
;
DEBUG_ONLY
(
tenv
.
mod
=
cg
->
mod
;)
#if
1
#if
0
/* place const either in the smallest dominator of all its users or the original block */
if (cg->opt & IA32_OPT_PLACECNST)
tenv.block = node_users_smallest_common_dominator(irn, 1);
...
...
@@ -562,6 +562,7 @@ static void ia32_create_Pushs(ir_node *irn, ia32_code_gen_t *cg) {
ir_node
*
push
;
ir_node
*
val
,
*
mem
;
ir_node
*
store
=
stores
[
i
];
ir_node
*
noreg
=
ia32_new_NoReg_gp
(
cg
);
if
(
store
==
NULL
||
is_Bad
(
store
))
break
;
...
...
@@ -571,7 +572,7 @@ static void ia32_create_Pushs(ir_node *irn, ia32_code_gen_t *cg) {
spreg
=
arch_get_irn_register
(
cg
->
arch_env
,
curr_sp
);
// create a push
push
=
new_rd_ia32_Push
(
NULL
,
irg
,
block
,
curr_sp
,
val
,
mem
);
push
=
new_rd_ia32_Push
(
NULL
,
irg
,
block
,
noreg
,
noreg
,
val
,
curr_sp
,
mem
);
if
(
get_ia32_immop_type
(
store
)
!=
ia32_ImmNone
)
{
copy_ia32_Immop_attr
(
push
,
store
);
}
...
...
ir/be/ia32/ia32_spec.pl
View file @
a10617f2
...
...
@@ -416,7 +416,7 @@ $comment_string = "/*";
"
irn_flags
"
=>
"
R
",
"
comment
"
=>
"
construct Shl: Shl(a, b) = a << b
",
"
cmp_attr
"
=>
"
return ia32_compare_immop_attr(attr_a, attr_b);
\n
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
gp
",
"
ecx
",
"
none
"
],
"
out
"
=>
[
"
in_r3 !in_r4
"
]
},
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
gp
",
"
ecx
gp_NOREG
",
"
none
"
],
"
out
"
=>
[
"
in_r3 !in_r4
"
]
},
"
emit
"
=>
'
. shl %ia32_emit_binop /* Shl(%A1, %A2) -> %D1 */
',
"
outs
"
=>
[
"
res
",
"
M
"
],
},
...
...
@@ -465,7 +465,7 @@ else {
"
irn_flags
"
=>
"
R
",
"
comment
"
=>
"
construct Shr: Shr(a, b) = a >> b
",
"
cmp_attr
"
=>
"
return ia32_compare_immop_attr(attr_a, attr_b);
\n
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
gp
",
"
ecx
",
"
none
"
],
"
out
"
=>
[
"
in_r3 !in_r4
"
]
},
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
gp
",
"
ecx
gp_NOREG
",
"
none
"
],
"
out
"
=>
[
"
in_r3 !in_r4
"
]
},
"
emit
"
=>
'
. shr %ia32_emit_binop /* Shr(%A1, %A2) -> %D1 */
',
"
outs
"
=>
[
"
res
",
"
M
"
],
},
...
...
@@ -514,7 +514,7 @@ else {
"
irn_flags
"
=>
"
R
",
"
comment
"
=>
"
construct Shrs: Shrs(a, b) = a >> b
",
"
cmp_attr
"
=>
"
return ia32_compare_immop_attr(attr_a, attr_b);
\n
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
gp
",
"
ecx
",
"
none
"
],
"
out
"
=>
[
"
in_r3 !in_r4
"
]
},
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
gp
",
"
ecx
gp_NOREG
",
"
none
"
],
"
out
"
=>
[
"
in_r3 !in_r4
"
]
},
"
emit
"
=>
'
. sar %ia32_emit_binop /* Shrs(%A1, %A2) -> %D1 */
',
"
outs
"
=>
[
"
res
",
"
M
"
],
},
...
...
@@ -700,7 +700,7 @@ else {
"
state
"
=>
"
exc_pinned
",
"
comment
"
=>
"
construct 8Bit Store: Store(ptr, val, mem) = ST ptr,val
",
"
cmp_attr
"
=>
"
return ia32_compare_immop_attr(attr_a, attr_b);
\n
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
eax ebx ecx edx
",
"
none
"
]
},
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
eax ebx ecx edx
gp_NOREG
",
"
none
"
]
},
"
emit
"
=>
'
. mov %ia32_emit_binop /* Store(%A3) -> (%A1) */
',
"
outs
"
=>
[
"
M
"
],
"
latency
"
=>
3
,
...
...
@@ -717,23 +717,9 @@ else {
"
Push
"
=>
{
# We don't set class modify_stack here (but we will do this on proj 0)
"
comment
"
=>
"
push a gp register on the stack
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
esp
",
"
gp
",
"
none
"
],
"
out
"
=>
[
"
esp
"
]
},
"
emit
"
=>
'
if (get_ia32_id_cnst(n)) {
if (get_ia32_immop_type(n) == ia32_ImmConst) {
4. push %C /* Push const on stack */
} else {
4. push OFFSET FLAT:%C /* Push symconst on stack */
}
}
else if (get_ia32_op_type(n) == ia32_Normal) {
2. push %S2 /* Push(%A2) */
}
else {
2. push %ia32_emit_am /* Push memory to stack */
};
',
"
comment
"
=>
"
push on the stack
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
gp
",
"
esp
",
"
none
"
],
"
out
"
=>
[
"
esp
"
]
},
"
emit
"
=>
'
. push %ia32_emit_unop /* PUSH(%A1) */
',
"
outs
"
=>
[
"
stack
",
"
M
"
],
"
latency
"
=>
3
,
},
...
...
@@ -741,15 +727,8 @@ else {
"
Pop
"
=>
{
# We don't set class modify stack here (but we will do this on proj 1)
"
comment
"
=>
"
pop a gp register from the stack
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
esp
",
"
none
"
],
"
out
"
=>
[
"
gp
",
"
esp
"
]
},
"
emit
"
=>
'
if (get_ia32_op_type(n) == ia32_Normal) {
2. pop %D1 /* Pop from stack into %D1 */
}
else {
2. pop %ia32_emit_am /* Pop from stack into memory */
}
',
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
esp
",
"
none
"
],
"
out
"
=>
[
"
gp
",
"
esp
"
]
},
"
emit
"
=>
'
. pop %ia32_emit_unop /* POP(%A1) */
',
"
outs
"
=>
[
"
res
",
"
stack
",
"
M
"
],
"
latency
"
=>
4
,
},
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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