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
df437344
Commit
df437344
authored
Feb 27, 2007
by
Matthias Braun
Browse files
fix Mulh, Div, IDiv handling
parent
4b56e387
Changes
3
Hide whitespace changes
Inline
Side-by-side
ir/be/ia32/ia32_emitter.c
View file @
df437344
...
...
@@ -343,7 +343,7 @@ void ia32_emit_x87_name(ia32_emit_env_t *env, const ir_node *node, int pos)
{
ia32_attr_t
*
attr
=
get_ia32_attr
(
node
);
assert
(
pos
<
7
);
assert
(
pos
<
3
);
ia32_emit_char
(
env
,
'%'
);
ia32_emit_string
(
env
,
attr
->
x87
[
pos
]
->
name
);
}
...
...
@@ -515,11 +515,10 @@ void ia32_emit_unop(ia32_emit_env_t *env, const ir_node *node) {
ia32_emit_char
(
env
,
'$'
);
ia32_emit_immediate
(
env
,
node
);
}
else
{
if
(
is_ia32_IMul
(
node
)
||
is_ia32_Mulh
(
node
))
{
/* MulS and Mulh implicitly multiply by EAX */
if
(
is_ia32_Mul
(
node
)
||
is_ia32_IMul1OP
(
node
))
{
ia32_emit_source_register
(
env
,
node
,
3
);
}
else
if
(
is_ia32_IDiv
(
node
))
{
ia32_emit_source_register
(
env
,
node
,
1
);
}
else
if
(
is_ia32_IDiv
(
node
)
||
is_ia32_Div
(
node
)
)
{
ia32_emit_source_register
(
env
,
node
,
4
);
}
else
if
(
is_ia32_Push
(
node
))
{
ia32_emit_source_register
(
env
,
node
,
2
);
}
else
if
(
is_ia32_Pop
(
node
))
{
...
...
ir/be/ia32/ia32_spec.pl
View file @
df437344
...
...
@@ -114,7 +114,7 @@ $arch = "ia32";
{
"
name
"
=>
"
ebp
",
"
type
"
=>
2
},
{
"
name
"
=>
"
esp
",
"
type
"
=>
4
},
{
"
name
"
=>
"
gp_NOREG
",
"
type
"
=>
4
|
8
|
16
},
# we need a dummy register for NoReg nodes
{
"
name
"
=>
"
gp_UKNWN
",
"
type
"
=>
4
|
8
|
16
},
# we need a dummy register for Unknown nodes
{
"
name
"
=>
"
gp_UKNWN
",
"
type
"
=>
4
|
8
|
16
},
# we need a dummy register for Unknown nodes
{
"
mode
"
=>
"
mode_Iu
"
}
],
"
xmm
"
=>
[
...
...
@@ -127,7 +127,7 @@ $arch = "ia32";
{
"
name
"
=>
"
xmm6
",
"
type
"
=>
1
},
{
"
name
"
=>
"
xmm7
",
"
type
"
=>
1
},
{
"
name
"
=>
"
xmm_NOREG
",
"
type
"
=>
4
|
8
|
16
},
# we need a dummy register for NoReg nodes
{
"
name
"
=>
"
xmm_UKNWN
",
"
type
"
=>
4
|
8
|
16
},
# we need a dummy register for Unknown nodes
{
"
name
"
=>
"
xmm_UKNWN
",
"
type
"
=>
4
|
8
|
16
},
# we need a dummy register for Unknown nodes
{
"
mode
"
=>
"
mode_E
"
}
],
"
vfp
"
=>
[
...
...
@@ -140,7 +140,7 @@ $arch = "ia32";
{
"
name
"
=>
"
vf6
",
"
type
"
=>
1
|
16
},
{
"
name
"
=>
"
vf7
",
"
type
"
=>
1
|
16
},
{
"
name
"
=>
"
vfp_NOREG
",
"
type
"
=>
4
|
8
|
16
},
# we need a dummy register for NoReg nodes
{
"
name
"
=>
"
vfp_UKNWN
",
"
type
"
=>
4
|
8
|
16
},
# we need a dummy register for Unknown nodes
{
"
name
"
=>
"
vfp_UKNWN
",
"
type
"
=>
4
|
8
|
16
},
# we need a dummy register for Unknown nodes
{
"
mode
"
=>
"
mode_E
"
}
],
"
st
"
=>
[
...
...
@@ -323,6 +323,16 @@ $default_cmp_attr = "return ia32_compare_attr(attr_a, attr_b);";
"
mode
"
=>
"
mode_Iu
",
},
"
IMul1OP
"
=>
{
"
irn_flags
"
=>
"
R
",
"
comment
"
=>
"
construct Mul (1 operand format): Mul(a, b) = Mul(b, a) = a * b
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
eax
",
"
gp
",
"
none
"
],
"
out
"
=>
[
"
eax
",
"
edx
",
"
none
"
]
},
"
emit
"
=>
'
. imull %unop
',
"
outs
"
=>
[
"
EAX
",
"
EDX
",
"
M
"
],
"
latency
"
=>
5
,
"
units
"
=>
[
"
GP
"
],
},
"
l_IMul
"
=>
{
"
op_flags
"
=>
"
C
",
"
cmp_attr
"
=>
"
return 1;
",
...
...
@@ -330,20 +340,6 @@ $default_cmp_attr = "return ia32_compare_attr(attr_a, attr_b);";
"
arity
"
=>
2
},
# Mulh is an exception from the 4 INs with AM because the target is always EAX:EDX
# Matze: It's not clear to me why we have a separate Mulh node and not just use
# the IMul node...
"
Mulh
"
=>
{
# we should not rematrialize this node. It produces 2 results and has
# very strict constrains
"
comment
"
=>
"
construct Mul: Mul(a, b) = Mul(b, a) = a * b
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
eax
",
"
gp
",
"
none
"
],
"
out
"
=>
[
"
eax
",
"
edx
"
]
},
"
emit
"
=>
'
. imull %unop
',
"
outs
"
=>
[
"
EAX
",
"
EDX
",
"
M
"
],
"
latency
"
=>
5
,
"
units
"
=>
[
"
GP
"
],
},
"
And
"
=>
{
"
irn_flags
"
=>
"
R
",
"
comment
"
=>
"
construct And: And(a, b) = And(b, a) = a AND b
",
...
...
@@ -428,7 +424,7 @@ $default_cmp_attr = "return ia32_compare_attr(attr_a, attr_b);";
"
IDiv
"
=>
{
"
op_flags
"
=>
"
F|L
",
"
state
"
=>
"
exc_pinned
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
eax
",
"
gp
",
"
e
dx
",
"
none
"
],
"
out
"
=>
[
"
eax
",
"
edx
",
"
none
"
]
},
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
e
ax
",
"
edx
",
"
gp
",
"
none
"
],
"
out
"
=>
[
"
eax
",
"
edx
",
"
none
"
]
},
"
attr
"
=>
"
ia32_op_flavour_t dm_flav
",
"
init_attr
"
=>
"
attr->data.op_flav = dm_flav;
",
"
emit
"
=>
"
. idivl %unop
",
...
...
@@ -440,7 +436,7 @@ $default_cmp_attr = "return ia32_compare_attr(attr_a, attr_b);";
"
Div
"
=>
{
"
op_flags
"
=>
"
F|L
",
"
state
"
=>
"
exc_pinned
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
eax
",
"
gp
",
"
e
dx
",
"
none
"
],
"
out
"
=>
[
"
eax
",
"
edx
",
"
none
"
]
},
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
e
ax
",
"
edx
",
"
gp
",
"
none
"
],
"
out
"
=>
[
"
eax
",
"
edx
",
"
none
"
]
},
"
attr
"
=>
"
ia32_op_flavour_t dm_flav
",
"
init_attr
"
=>
"
attr->data.op_flav = dm_flav;
",
"
emit
"
=>
"
. divl %unop
",
...
...
@@ -1125,7 +1121,7 @@ if (get_ia32_immop_type(node) == ia32_ImmNone) {
"
state
"
=>
"
exc_pinned
",
"
comment
"
=>
"
store ST0 onto stack
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
none
"
]
},
"
emit
"
=>
'
. fstp%M %AM
',
"
emit
"
=>
'
. fstp%
X
M %AM
',
"
latency
"
=>
4
,
"
units
"
=>
[
"
SSE
"
],
"
mode
"
=>
"
mode_M
",
...
...
@@ -1726,7 +1722,7 @@ if (get_ia32_immop_type(node) == ia32_ImmNone) {
"
state
"
=>
"
exc_pinned
",
"
comment
"
=>
"
x87 fp Load: Load(ptr, mem) = LD ptr -> reg
",
"
reg_req
"
=>
{
},
"
emit
"
=>
'
. fld%M %AM
',
"
emit
"
=>
'
. fld%
X
M %AM
',
},
"
fst
"
=>
{
...
...
@@ -1735,7 +1731,7 @@ if (get_ia32_immop_type(node) == ia32_ImmNone) {
"
state
"
=>
"
exc_pinned
",
"
comment
"
=>
"
x87 fp Store: Store(ptr, val, mem) = ST ptr,val
",
"
reg_req
"
=>
{
},
"
emit
"
=>
'
. fst%M %AM
',
"
emit
"
=>
'
. fst%
X
M %AM
',
"
mode
"
=>
"
mode_M
",
},
...
...
@@ -1745,7 +1741,7 @@ if (get_ia32_immop_type(node) == ia32_ImmNone) {
"
state
"
=>
"
exc_pinned
",
"
comment
"
=>
"
x87 fp Store: Store(ptr, val, mem) = ST ptr,val
",
"
reg_req
"
=>
{
},
"
emit
"
=>
'
. fstp%M %AM
',
"
emit
"
=>
'
. fstp%
X
M %AM
',
"
mode
"
=>
"
mode_M
",
},
...
...
@@ -1756,7 +1752,7 @@ if (get_ia32_immop_type(node) == ia32_ImmNone) {
"
rd_constructor
"
=>
"
NONE
",
"
comment
"
=>
"
x87 fp integer Load: Load(ptr, mem) = iLD ptr -> reg
",
"
reg_req
"
=>
{
},
"
emit
"
=>
'
. fild%M %AM
',
"
emit
"
=>
'
. fild%
X
M %AM
',
},
"
fist
"
=>
{
...
...
ir/be/ia32/ia32_transform.c
View file @
df437344
...
...
@@ -521,7 +521,7 @@ static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *node,
ir_node
*
new_op2
=
transform_node
(
env
,
op2
);
new_node
=
func
(
dbg
,
irg
,
block
,
noreg_gp
,
noreg_gp
,
new_op1
,
new_op2
,
nomem
);
if
(
func
==
new_rd_ia32_Mul
)
{
if
(
func
==
new_rd_ia32_
I
Mul
)
{
set_ia32_am_support
(
new_node
,
ia32_am_Source
);
}
else
{
set_ia32_am_support
(
new_node
,
ia32_am_Full
);
...
...
@@ -884,18 +884,24 @@ static ir_node *gen_Mulh(ia32_transform_env_t *env, ir_node *node) {
ir_node
*
new_op1
=
transform_node
(
env
,
op1
);
ir_node
*
new_op2
=
transform_node
(
env
,
op2
);
ir_node
*
noreg
=
ia32_new_NoReg_gp
(
env
->
cg
);
ir_node
*
proj_EAX
,
*
proj_EDX
,
*
mulh
;
ir_node
*
proj_EAX
,
*
proj_EDX
,
*
res
;
ir_mode
*
mode
=
get_irn_mode
(
node
);
ir_node
*
in
[
1
];
assert
(
!
mode_is_float
(
mode
)
&&
"Mulh with float not supported"
);
mulh
=
new_rd_ia32_Mulh
(
dbg
,
irg
,
block
,
noreg
,
noreg
,
new_op1
,
new_op2
,
new_NoMem
());
set_ia32_commutative
(
mulh
);
set_ia32_am_support
(
mulh
,
ia32_am_Source
);
if
(
mode_is_signed
(
mode
))
{
res
=
new_rd_ia32_IMul1OP
(
dbg
,
irg
,
block
,
noreg
,
noreg
,
new_op1
,
new_op2
,
new_NoMem
());
}
else
{
res
=
new_rd_ia32_Mul
(
dbg
,
irg
,
block
,
noreg
,
noreg
,
new_op1
,
new_op2
,
new_NoMem
());
}
/* imediates are not supported, so no fold_immediate */
proj_EAX
=
new_rd_Proj
(
dbg
,
irg
,
block
,
mulh
,
mode_Iu
,
pn_EAX
);
proj_EDX
=
new_rd_Proj
(
dbg
,
irg
,
block
,
mulh
,
mode_Iu
,
pn_EDX
);
set_ia32_commutative
(
res
);
set_ia32_am_support
(
res
,
ia32_am_Source
);
set_ia32_am_support
(
res
,
ia32_am_Source
);
proj_EAX
=
new_rd_Proj
(
dbg
,
irg
,
block
,
res
,
mode_Iu
,
pn_EAX
);
proj_EDX
=
new_rd_Proj
(
dbg
,
irg
,
block
,
res
,
mode_Iu
,
pn_EDX
);
/* keep EAX */
in
[
0
]
=
proj_EAX
;
...
...
@@ -1196,6 +1202,7 @@ static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *node,
ir_node
*
in_keep
[
1
];
ir_node
*
mem
,
*
new_mem
;
ir_node
*
projs
[
pn_DivMod_max
];
ir_node
*
noreg
=
ia32_new_NoReg_gp
(
env
->
cg
);
ir_node
*
new_dividend
=
transform_node
(
env
,
dividend
);
ir_node
*
new_divisor
=
transform_node
(
env
,
divisor
);
...
...
@@ -1233,10 +1240,17 @@ static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *node,
}
if
(
mode_is_signed
(
mode
))
{
res
=
new_rd_ia32_IDiv
(
dbg
,
irg
,
block
,
new_dividend
,
new_divisor
,
edx_node
,
new_mem
,
dm_flav
);
res
=
new_rd_ia32_IDiv
(
dbg
,
irg
,
block
,
noreg
,
noreg
,
new_dividend
,
edx_node
,
new_divisor
,
new_mem
,
dm_flav
);
}
else
{
res
=
new_rd_ia32_Div
(
dbg
,
irg
,
block
,
new_dividend
,
new_divisor
,
edx_node
,
new_mem
,
dm_flav
);
res
=
new_rd_ia32_Div
(
dbg
,
irg
,
block
,
noreg
,
noreg
,
new_dividend
,
edx_node
,
new_divisor
,
new_mem
,
dm_flav
);
}
/* Matze: code can't handle this at the moment... */
#if 0
/* set AM support */
set_ia32_am_support(res, ia32_am_Source);
#endif
set_ia32_n_res
(
res
,
2
);
/* Only one proj is used -> We must add a second proj and */
...
...
@@ -3387,7 +3401,7 @@ static ir_node *gen_Proj_be_AddSP(ia32_transform_env_t *env, ir_node *node) {
dbg_info
*
dbg
=
get_irn_dbg_info
(
node
);
ir_node
*
pred
=
get_Proj_pred
(
node
);
ir_node
*
new_pred
=
transform_node
(
env
,
pred
);
int
proj
=
get_Proj_proj
(
node
);
long
proj
=
get_Proj_proj
(
node
);
if
(
proj
==
pn_be_AddSP_res
)
{
ir_node
*
res
=
new_rd_Proj
(
dbg
,
irg
,
block
,
new_pred
,
mode_Iu
,
pn_ia32_AddSP_stack
);
...
...
@@ -3407,7 +3421,7 @@ static ir_node *gen_Proj_be_SubSP(ia32_transform_env_t *env, ir_node *node) {
dbg_info
*
dbg
=
get_irn_dbg_info
(
node
);
ir_node
*
pred
=
get_Proj_pred
(
node
);
ir_node
*
new_pred
=
transform_node
(
env
,
pred
);
int
proj
=
get_Proj_proj
(
node
);
long
proj
=
get_Proj_proj
(
node
);
if
(
proj
==
pn_be_SubSP_res
)
{
ir_node
*
res
=
new_rd_Proj
(
dbg
,
irg
,
block
,
new_pred
,
mode_Iu
,
pn_ia32_AddSP_stack
);
...
...
@@ -3427,7 +3441,7 @@ static ir_node *gen_Proj_Load(ia32_transform_env_t *env, ir_node *node) {
dbg_info
*
dbg
=
get_irn_dbg_info
(
node
);
ir_node
*
pred
=
get_Proj_pred
(
node
);
ir_node
*
new_pred
=
transform_node
(
env
,
pred
);
int
proj
=
get_Proj_proj
(
node
);
long
proj
=
get_Proj_proj
(
node
);
/* renumber the proj */
if
(
is_ia32_Load
(
new_pred
))
{
...
...
@@ -3462,7 +3476,7 @@ static ir_node *gen_Proj_DivMod(ia32_transform_env_t *env, ir_node *node) {
ir_node
*
pred
=
get_Proj_pred
(
node
);
ir_node
*
new_pred
=
transform_node
(
env
,
pred
);
int
proj
=
get_Proj_proj
(
node
);
long
proj
=
get_Proj_proj
(
node
);
assert
(
is_ia32_Div
(
new_pred
)
||
is_ia32_IDiv
(
new_pred
));
...
...
@@ -3516,7 +3530,7 @@ static ir_node *gen_Proj_CopyB(ia32_transform_env_t *env, ir_node *node)
ir_node
*
pred
=
get_Proj_pred
(
node
);
ir_node
*
new_pred
=
transform_node
(
env
,
pred
);
int
proj
=
get_Proj_proj
(
node
);
long
proj
=
get_Proj_proj
(
node
);
switch
(
proj
)
{
case
pn_CopyB_M_regular
:
...
...
@@ -3545,7 +3559,7 @@ static ir_node *gen_Proj_l_vfdiv(ia32_transform_env_t *env, ir_node *node)
ir_node
*
pred
=
get_Proj_pred
(
node
);
ir_node
*
new_pred
=
transform_node
(
env
,
pred
);
int
proj
=
get_Proj_proj
(
node
);
long
proj
=
get_Proj_proj
(
node
);
switch
(
proj
)
{
case
pn_ia32_l_vfdiv_M
:
...
...
@@ -3568,7 +3582,7 @@ static ir_node *gen_Proj_Quot(ia32_transform_env_t *env, ir_node *node)
ir_node
*
pred
=
get_Proj_pred
(
node
);
ir_node
*
new_pred
=
transform_node
(
env
,
pred
);
int
proj
=
get_Proj_proj
(
node
);
long
proj
=
get_Proj_proj
(
node
);
switch
(
proj
)
{
case
pn_Quot_M
:
...
...
@@ -3607,11 +3621,30 @@ static ir_node *gen_Proj_tls(ia32_transform_env_t *env, ir_node *node) {
return
res
;
}
static
ir_node
*
gen_Proj_be_Call
(
ia32_transform_env_t
*
env
,
ir_node
*
node
)
{
ir_graph
*
irg
=
env
->
irg
;
dbg_info
*
dbg
=
get_irn_dbg_info
(
node
);
ir_node
*
pred
=
get_Proj_pred
(
node
);
long
proj
=
get_Proj_proj
(
node
);
ir_mode
*
mode
=
get_irn_mode
(
node
);
ir_node
*
block
=
transform_node
(
env
,
get_nodes_block
(
node
));
ir_node
*
new_pred
=
transform_node
(
env
,
pred
);
/* transform call modes to the mode_Iu or mode_E */
if
(
mode_is_float
(
mode
))
{
mode
=
mode_E
;
}
else
if
(
mode
!=
mode_M
)
{
mode
=
mode_Iu
;
}
return
new_rd_Proj
(
dbg
,
irg
,
block
,
new_pred
,
mode
,
proj
);
}
static
ir_node
*
gen_Proj
(
ia32_transform_env_t
*
env
,
ir_node
*
node
)
{
ir_graph
*
irg
=
env
->
irg
;
dbg_info
*
dbg
=
get_irn_dbg_info
(
node
);
ir_node
*
pred
=
get_Proj_pred
(
node
);
int
proj
=
get_Proj_proj
(
node
);
long
proj
=
get_Proj_proj
(
node
);
if
(
is_Store
(
pred
)
||
be_is_FrameStore
(
pred
))
{
if
(
proj
==
pn_Store_M
)
{
...
...
@@ -3634,6 +3667,8 @@ static ir_node *gen_Proj(ia32_transform_env_t *env, ir_node *node) {
return
gen_Proj_be_SubSP
(
env
,
node
);
}
else
if
(
be_is_AddSP
(
pred
))
{
return
gen_Proj_be_AddSP
(
env
,
node
);
}
else
if
(
be_is_Call
(
pred
))
{
return
gen_Proj_be_Call
(
env
,
node
);
}
else
if
(
get_irn_op
(
pred
)
==
op_Start
)
{
if
(
proj
==
pn_Start_X_initial_exec
)
{
ir_node
*
block
=
get_nodes_block
(
pred
);
...
...
Write
Preview
Supports
Markdown
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