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
da230f5e
Commit
da230f5e
authored
Sep 10, 2007
by
Christoph Mallon
Browse files
Add magic for better code emission of 64bit minus.
[r15730]
parent
cec4e902
Changes
3
Hide whitespace changes
Inline
Side-by-side
ir/be/ia32/ia32_emitter.c
View file @
da230f5e
...
...
@@ -1920,6 +1920,121 @@ void emit_ia32_LdTls(ia32_emit_env_t *env, const ir_node *node) {
be_emit_finish_line_gas
(
env
,
node
);
}
/* helper function for emit_ia32_Minus64Bit */
static
void
emit_mov
(
ia32_emit_env_t
*
env
,
const
ir_node
*
node
,
const
arch_register_t
*
src
,
const
arch_register_t
*
dst
)
{
be_emit_cstring
(
env
,
"
\t
movl "
);
ia32_emit_register
(
env
,
src
);
be_emit_cstring
(
env
,
", "
);
ia32_emit_register
(
env
,
dst
);
be_emit_finish_line_gas
(
env
,
node
);
}
/* helper function for emit_ia32_Minus64Bit */
static
void
emit_neg
(
ia32_emit_env_t
*
env
,
const
ir_node
*
node
,
const
arch_register_t
*
reg
)
{
be_emit_cstring
(
env
,
"
\t
negl "
);
ia32_emit_register
(
env
,
reg
);
be_emit_finish_line_gas
(
env
,
node
);
}
/* helper function for emit_ia32_Minus64Bit */
static
void
emit_sbb0
(
ia32_emit_env_t
*
env
,
const
ir_node
*
node
,
const
arch_register_t
*
reg
)
{
be_emit_cstring
(
env
,
"
\t
sbbl $0, "
);
ia32_emit_register
(
env
,
reg
);
be_emit_finish_line_gas
(
env
,
node
);
}
/* helper function for emit_ia32_Minus64Bit */
static
void
emit_sbb
(
ia32_emit_env_t
*
env
,
const
ir_node
*
node
,
const
arch_register_t
*
src
,
const
arch_register_t
*
dst
)
{
be_emit_cstring
(
env
,
"
\t
sbbl "
);
ia32_emit_register
(
env
,
src
);
be_emit_cstring
(
env
,
", "
);
ia32_emit_register
(
env
,
dst
);
be_emit_finish_line_gas
(
env
,
node
);
}
/* helper function for emit_ia32_Minus64Bit */
static
void
emit_xchg
(
ia32_emit_env_t
*
env
,
const
ir_node
*
node
,
const
arch_register_t
*
src
,
const
arch_register_t
*
dst
)
{
be_emit_cstring
(
env
,
"
\t
xchgl "
);
ia32_emit_register
(
env
,
src
);
be_emit_cstring
(
env
,
", "
);
ia32_emit_register
(
env
,
dst
);
be_emit_finish_line_gas
(
env
,
node
);
}
/* helper function for emit_ia32_Minus64Bit */
static
void
emit_zero
(
ia32_emit_env_t
*
env
,
const
ir_node
*
node
,
const
arch_register_t
*
reg
)
{
if
(
env
->
isa
->
opt_arch
==
arch_pentium_4
)
{
/* P4 prefers sub r, r, others xor r, r */
be_emit_cstring
(
env
,
"
\t
subl "
);
}
else
{
be_emit_cstring
(
env
,
"
\t
xorl "
);
}
ia32_emit_register
(
env
,
reg
);
be_emit_cstring
(
env
,
", "
);
ia32_emit_register
(
env
,
reg
);
be_emit_finish_line_gas
(
env
,
node
);
}
static
void
emit_ia32_Minus64Bit
(
ia32_emit_env_t
*
env
,
const
ir_node
*
node
)
{
const
arch_register_t
*
in_lo
=
get_in_reg
(
env
,
node
,
0
);
const
arch_register_t
*
in_hi
=
get_in_reg
(
env
,
node
,
1
);
const
arch_register_t
*
out_lo
=
get_out_reg
(
env
,
node
,
0
);
const
arch_register_t
*
out_hi
=
get_out_reg
(
env
,
node
,
1
);
if
(
out_lo
==
in_lo
)
{
if
(
out_hi
!=
in_hi
)
{
/* a -> a, b -> d */
goto
zero_neg
;
}
else
{
/* a -> a, b -> b */
goto
normal_neg
;
}
}
else
if
(
out_lo
==
in_hi
)
{
if
(
out_hi
==
in_lo
)
{
/* a -> b, b -> a */
emit_xchg
(
env
,
node
,
in_lo
,
in_hi
);
goto
normal_neg
;
}
else
{
/* a -> b, b -> d */
emit_mov
(
env
,
node
,
in_hi
,
out_hi
);
emit_mov
(
env
,
node
,
in_lo
,
out_lo
);
goto
normal_neg
;
}
}
else
{
if
(
out_hi
==
in_lo
)
{
/* a -> c, b -> a */
emit_mov
(
env
,
node
,
in_lo
,
out_lo
);
goto
zero_neg
;
}
else
if
(
out_hi
==
in_hi
)
{
/* a -> c, b -> b */
emit_mov
(
env
,
node
,
in_lo
,
out_lo
);
goto
normal_neg
;
}
else
{
/* a -> c, b -> d */
emit_mov
(
env
,
node
,
in_lo
,
out_lo
);
goto
zero_neg
;
}
}
normal_neg:
emit_neg
(
env
,
node
,
out_hi
);
emit_neg
(
env
,
node
,
out_lo
);
emit_sbb0
(
env
,
node
,
out_hi
);
return
;
zero_neg:
emit_zero
(
env
,
node
,
out_hi
);
emit_neg
(
env
,
node
,
out_lo
);
emit_sbb
(
env
,
node
,
in_hi
,
out_hi
);
}
static
void
emit_be_Return
(
ia32_emit_env_t
*
env
,
const
ir_node
*
node
)
{
...
...
@@ -1989,6 +2104,7 @@ void ia32_register_emitters(void) {
IA32_EMIT
(
Conv_I2I8Bit
);
IA32_EMIT
(
Const
);
IA32_EMIT
(
LdTls
);
IA32_EMIT
(
Minus64Bit
);
IA32_EMIT
(
xCmp
);
IA32_EMIT
(
xCmpSet
);
IA32_EMIT
(
xCmpCMov
);
...
...
ir/be/ia32/ia32_intrinsics.c
View file @
da230f5e
...
...
@@ -477,18 +477,12 @@ static int map_Minus(ir_node *call, void *ctx) {
ir_node
*
a_l
=
params
[
BINOP_Left_Low
];
ir_node
*
a_h
=
params
[
BINOP_Left_High
];
ir_mode
*
l_mode
=
get_type_mode
(
get_method_res_type
(
method
,
0
));
ir_node
*
l_res
,
*
h_res
,
*
cnst
,
*
res
;
ir_node
*
l_res
,
*
h_res
,
*
res
;
(
void
)
ctx
;
assert
(
l_mode
==
get_type_mode
(
get_method_res_type
(
method
,
1
))
&&
"64bit lowered into different modes"
);
/* too bad: we need 0 in a register here */
cnst
=
new_Const_long
(
l_mode
,
0
);
/* l_res = 0 - a_l */
/* h_res = 0 - a_h - carry */
res
=
new_rd_ia32_Minus64Bit
(
dbg
,
irg
,
block
,
cnst
,
a_l
,
a_h
);
res
=
new_rd_ia32_Minus64Bit
(
dbg
,
irg
,
block
,
a_l
,
a_h
);
l_res
=
new_r_Proj
(
irg
,
block
,
res
,
l_mode
,
pn_ia32_Minus64Bit_low_res
);
h_res
=
new_r_Proj
(
irg
,
block
,
res
,
l_mode
,
pn_ia32_Minus64Bit_high_res
);
...
...
ir/be/ia32/ia32_spec.pl
View file @
da230f5e
...
...
@@ -873,13 +873,7 @@ NegMem => {
Minus64Bit
=>
{
irn_flags
=>
"
R
",
reg_req
=>
{
in
=>
[
"
gp
",
"
gp
",
"
gp
"
],
out
=>
[
"
!in
",
"
!in
"
]
},
emit
=>
'
. movl %S0, %D0
. movl %S0, %D1
. subl %S1, %D0
. sbbl %S2, %D1
',
reg_req
=>
{
in
=>
[
"
gp
",
"
gp
"
],
out
=>
[
"
in_r1
",
"
gp
"
]
},
outs
=>
[
"
low_res
",
"
high_res
"
],
units
=>
[
"
GP
"
],
modified_flags
=>
$status_flags
...
...
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