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
0fc6b01e
Commit
0fc6b01e
authored
Jul 24, 2012
by
Christoph Mallon
Browse files
Add and use amd64_emitf().
parent
a993becf
Changes
3
Hide whitespace changes
Inline
Side-by-side
ir/be/amd64/amd64_emitter.c
View file @
0fc6b01e
...
...
@@ -58,47 +58,128 @@
* |_| |_|
*************************************************************/
void
amd64_emit_register
(
const
arch_register_t
*
reg
)
/**
* Returns the target block for a control flow node.
*/
static
ir_node
*
get_cfop_target_block
(
const
ir_node
*
irn
)
{
be_emit_char
(
'%'
);
be_emit_string
(
arch_register_get_name
(
reg
));
return
(
ir_node
*
)
get_irn_link
(
irn
);
}
void
amd64_emit
_immediate
(
const
ir_
node
*
node
)
void
amd64_emit
f
(
ir_node
const
*
const
node
,
char
const
*
fmt
,
...
)
{
const
amd64_attr_t
*
attr
=
get_amd64_attr_const
(
node
);
be_emit_char
(
'$'
);
be_emit_irprintf
(
"0x%X"
,
attr
->
ext
.
imm_value
);
}
va_list
ap
;
va_start
(
ap
,
fmt
);
void
amd64_emit_fp_offset
(
const
ir_node
*
node
)
{
const
amd64_SymConst_attr_t
*
attr
=
get_amd64_SymConst_attr_const
(
node
);
if
(
attr
->
fp_offset
)
be_emit_irprintf
(
"%d"
,
attr
->
fp_offset
);
}
be_emit_char
(
'\t'
);
for
(;;)
{
char
const
*
start
=
fmt
;
void
amd64_emit_source_register
(
const
ir_node
*
node
,
int
pos
)
{
amd64_emit_register
(
arch_get_irn_register_in
(
node
,
pos
));
}
while
(
*
fmt
!=
'%'
&&
*
fmt
!=
'\n'
&&
*
fmt
!=
'\0'
)
++
fmt
;
if
(
fmt
!=
start
)
{
be_emit_string_len
(
start
,
fmt
-
start
);
}
void
amd64_emit_dest_register
(
const
ir_node
*
node
,
int
pos
)
{
amd64_emit_register
(
arch_get_irn_register_out
(
node
,
pos
));
}
if
(
*
fmt
==
'\n'
)
{
be_emit_char
(
'\n'
);
be_emit_write_line
();
be_emit_char
(
'\t'
);
++
fmt
;
continue
;
}
/**
* Returns the target label for a control flow node.
*/
/*
static void amd64_emit_cfop_target(const ir_node *node)
{
ir_node *block = get_irn_link(node);
if
(
*
fmt
==
'\0'
)
break
;
++
fmt
;
switch
(
*
fmt
++
)
{
arch_register_t
const
*
reg
;
case
'%'
:
be_emit_char
(
'%'
);
break
;
case
'C'
:
{
amd64_attr_t
const
*
const
attr
=
get_amd64_attr_const
(
node
);
be_emit_irprintf
(
"$0x%X"
,
attr
->
ext
.
imm_value
);
break
;
}
case
'D'
:
if
(
*
fmt
<
'0'
||
'9'
<=
*
fmt
)
goto
unknown
;
reg
=
arch_get_irn_register_out
(
node
,
*
fmt
++
-
'0'
);
goto
emit_R
;
case
'E'
:
{
ir_entity
const
*
const
ent
=
va_arg
(
ap
,
ir_entity
const
*
);
be_gas_emit_entity
(
ent
);
break
;
}
case
'L'
:
{
ir_node
*
const
block
=
get_cfop_target_block
(
node
);
be_gas_emit_block_name
(
block
);
break
;
}
case
'O'
:
{
amd64_SymConst_attr_t
const
*
const
attr
=
get_amd64_SymConst_attr_const
(
node
);
if
(
attr
->
fp_offset
)
be_emit_irprintf
(
"%d"
,
attr
->
fp_offset
);
break
;
}
case
'R'
:
reg
=
va_arg
(
ap
,
arch_register_t
const
*
);
emit_R:
be_emit_char
(
'%'
);
be_emit_string
(
arch_register_get_name
(
reg
));
break
;
case
'S'
:
{
int
pos
;
if
(
'0'
<=
*
fmt
&&
*
fmt
<=
'9'
)
{
pos
=
*
fmt
++
-
'0'
;
}
else
if
(
*
fmt
==
'*'
)
{
++
fmt
;
pos
=
va_arg
(
ap
,
int
);
}
else
{
goto
unknown
;
}
reg
=
arch_get_irn_register_in
(
node
,
pos
);
goto
emit_R
;
}
case
'd'
:
{
int
const
num
=
va_arg
(
ap
,
int
);
be_emit_irprintf
(
"%d"
,
num
);
break
;
}
case
's'
:
{
char
const
*
const
str
=
va_arg
(
ap
,
char
const
*
);
be_emit_string
(
str
);
break
;
}
case
'u'
:
{
unsigned
const
num
=
va_arg
(
ap
,
unsigned
);
be_emit_irprintf
(
"%u"
,
num
);
break
;
}
default:
unknown:
panic
(
"unknown format conversion"
);
}
}
be_emit_irprintf("BLOCK_%ld", get_irn_node_nr(block));
be_emit_finish_line_gas
(
node
);
va_end
(
ap
);
}
*/
/***********************************************************************************
* _ __ _
...
...
@@ -139,11 +220,7 @@ static void emit_amd64_SymConst(const ir_node *irn)
label = entry->label;
#endif
be_emit_cstring
(
"
\t
mov $"
);
be_gas_emit_entity
(
attr
->
entity
);
be_emit_cstring
(
", "
);
amd64_emit_dest_register
(
irn
,
0
);
be_emit_finish_line_gas
(
irn
);
amd64_emitf
(
irn
,
"mov $%E, %D0"
,
attr
->
entity
);
}
/**
...
...
@@ -151,11 +228,7 @@ static void emit_amd64_SymConst(const ir_node *irn)
*/
static
void
emit_amd64_Conv
(
const
ir_node
*
irn
)
{
be_emit_cstring
(
"
\t
mov "
);
amd64_emit_source_register
(
irn
,
0
);
be_emit_cstring
(
", "
);
amd64_emit_dest_register
(
irn
,
0
);
be_emit_finish_line_gas
(
irn
);
amd64_emitf
(
irn
,
"mov %S0, %D0"
);
}
...
...
@@ -167,24 +240,6 @@ static ir_node *sched_next_block(const ir_node *block)
return
(
ir_node
*
)
get_irn_link
(
block
);
}
/**
* Returns the target block for a control flow node.
*/
static
ir_node
*
get_cfop_target_block
(
const
ir_node
*
irn
)
{
return
(
ir_node
*
)
get_irn_link
(
irn
);
}
/**
* Emit the target label for a control flow node.
*/
static
void
amd64_emit_cfop_target
(
const
ir_node
*
irn
)
{
ir_node
*
block
=
get_cfop_target_block
(
irn
);
be_gas_emit_block_name
(
block
);
}
/**
* Emit a Jmp.
*/
...
...
@@ -198,16 +253,10 @@ static void emit_amd64_Jmp(const ir_node *node)
/* we have a block schedule */
next_block
=
sched_next_block
(
block
);
if
(
get_cfop_target_block
(
node
)
!=
next_block
)
{
be_emit_cstring
(
"
\t
jmp "
);
amd64_emit_cfop_target
(
node
);
}
else
{
if
(
be_options
.
verbose_asm
)
{
be_emit_cstring
(
"
\t
/* fallthrough to "
);
amd64_emit_cfop_target
(
node
);
be_emit_cstring
(
" */"
);
}
amd64_emitf
(
node
,
"jmp %L"
);
}
else
if
(
be_options
.
verbose_asm
)
{
amd64_emitf
(
node
,
"/* fallthrough to %L */"
);
}
be_emit_finish_line_gas
(
node
);
}
/**
...
...
@@ -272,21 +321,12 @@ static void emit_amd64_Jcc(const ir_node *irn)
}
/* emit the true proj */
be_emit_irprintf
(
"
\t
j%s "
,
suffix
);
amd64_emit_cfop_target
(
proj_true
);
be_emit_finish_line_gas
(
proj_true
);
if
(
get_cfop_target_block
(
proj_false
)
==
next_block
)
{
if
(
be_options
.
verbose_asm
)
{
be_emit_cstring
(
"
\t
/* fallthrough to "
);
amd64_emit_cfop_target
(
proj_false
);
be_emit_cstring
(
" */"
);
be_emit_finish_line_gas
(
proj_false
);
}
}
else
{
be_emit_cstring
(
"
\t
jmp "
);
amd64_emit_cfop_target
(
proj_false
);
be_emit_finish_line_gas
(
proj_false
);
amd64_emitf
(
proj_true
,
"j%s %L"
,
suffix
);
if
(
get_cfop_target_block
(
proj_false
)
!=
next_block
)
{
amd64_emitf
(
proj_false
,
"jmp %L"
);
}
else
if
(
be_options
.
verbose_asm
)
{
amd64_emitf
(
proj_false
,
"/* fallthrough to %L */"
);
}
}
...
...
@@ -301,14 +341,11 @@ static void emit_be_Call(const ir_node *node)
* variable argument counts */
if
(
get_method_variadicity
(
be_Call_get_type
((
ir_node
*
)
node
)))
{
/* But this still is a hack... */
be_emit_cstring
(
"
\t
xor %rax, %rax"
);
be_emit_finish_line_gas
(
node
);
amd64_emitf
(
node
,
"xor %%rax, %%rax"
);
}
if
(
entity
)
{
be_emit_cstring
(
"
\t
call "
);
be_gas_emit_entity
(
be_Call_get_entity
(
node
));
be_emit_finish_line_gas
(
node
);
amd64_emitf
(
node
,
"call %E"
,
entity
);
}
else
{
be_emit_pad_comment
();
be_emit_cstring
(
"/* FIXME: call NULL entity?! */
\n
"
);
...
...
@@ -330,11 +367,7 @@ static void emit_be_Copy(const ir_node *irn)
if
(
mode_is_float
(
mode
))
{
panic
(
"move not supported for FP"
);
}
else
if
(
mode_is_data
(
mode
))
{
be_emit_cstring
(
"
\t
mov "
);
amd64_emit_source_register
(
irn
,
0
);
be_emit_cstring
(
", "
);
amd64_emit_dest_register
(
irn
,
0
);
be_emit_finish_line_gas
(
irn
);
amd64_emitf
(
irn
,
"mov %S0, %D0"
);
}
else
{
panic
(
"move not supported for this mode"
);
}
...
...
@@ -353,11 +386,7 @@ static void emit_be_Perm(const ir_node *node)
assert
(
cls0
==
cls1
&&
"Register class mismatch at Perm"
);
be_emit_cstring
(
"
\t
xchg "
);
amd64_emit_register
(
in0
);
be_emit_cstring
(
", "
);
amd64_emit_register
(
in1
);
be_emit_finish_line_gas
(
node
);
amd64_emitf
(
node
,
"xchg %R, %R"
,
in0
,
in1
);
if
(
cls0
!=
&
amd64_reg_classes
[
CLASS_amd64_gp
])
{
panic
(
"unexpected register class in be_Perm (%+F)"
,
node
);
...
...
@@ -369,17 +398,8 @@ static void emit_amd64_FrameAddr(const ir_node *irn)
const
amd64_SymConst_attr_t
*
attr
=
(
const
amd64_SymConst_attr_t
*
)
get_amd64_attr_const
(
irn
);
be_emit_cstring
(
"
\t
mov "
);
amd64_emit_source_register
(
irn
,
0
);
be_emit_cstring
(
", "
);
amd64_emit_dest_register
(
irn
,
0
);
be_emit_finish_line_gas
(
irn
);
be_emit_cstring
(
"
\t
add "
);
be_emit_irprintf
(
"$0x%X"
,
attr
->
fp_offset
);
be_emit_cstring
(
", "
);
amd64_emit_dest_register
(
irn
,
0
);
be_emit_finish_line_gas
(
irn
);
amd64_emitf
(
irn
,
"mov %S0, %D0"
);
amd64_emitf
(
irn
,
"add $%u, %D0"
,
attr
->
fp_offset
);
}
/**
...
...
@@ -393,15 +413,9 @@ static void emit_be_IncSP(const ir_node *node)
return
;
if
(
offs
>
0
)
{
be_emit_irprintf
(
"
\t
sub "
);
be_emit_irprintf
(
"$%u, "
,
offs
);
amd64_emit_dest_register
(
node
,
0
);
be_emit_finish_line_gas
(
node
);
amd64_emitf
(
node
,
"sub, $%d, %D0"
,
offs
);
}
else
{
be_emit_irprintf
(
"
\t
add "
);
be_emit_irprintf
(
"$%u, "
,
-
offs
);
amd64_emit_dest_register
(
node
,
0
);
be_emit_finish_line_gas
(
node
);
amd64_emitf
(
node
,
"add, $%d, %D0"
,
-
offs
);
}
}
...
...
@@ -418,23 +432,11 @@ static void emit_be_Return(const ir_node *node)
static
void
emit_amd64_binop_op
(
const
ir_node
*
irn
,
int
second_op
)
{
if
(
irn
->
op
==
op_amd64_Add
)
{
be_emit_cstring
(
"
\t
add "
);
amd64_emit_source_register
(
irn
,
second_op
);
be_emit_cstring
(
", "
);
amd64_emit_dest_register
(
irn
,
0
);
be_emit_finish_line_gas
(
irn
);
amd64_emitf
(
irn
,
"add %S*, %D0"
,
second_op
);
}
else
if
(
irn
->
op
==
op_amd64_Sub
)
{
be_emit_cstring
(
"
\t
neg "
);
amd64_emit_source_register
(
irn
,
second_op
);
be_emit_finish_line_gas
(
irn
);
be_emit_cstring
(
"
\t
add "
);
amd64_emit_source_register
(
irn
,
second_op
);
be_emit_cstring
(
", "
);
amd64_emit_dest_register
(
irn
,
0
);
be_emit_finish_line_gas
(
irn
);
be_emit_cstring
(
"
\t
neg "
);
amd64_emit_source_register
(
irn
,
second_op
);
be_emit_finish_line_gas
(
irn
);
amd64_emitf
(
irn
,
"neg %S*"
,
second_op
);
amd64_emitf
(
irn
,
"add %S*, %D0"
,
second_op
);
amd64_emitf
(
irn
,
"neg %S*"
,
second_op
);
}
}
...
...
@@ -451,16 +453,10 @@ static void emit_amd64_binop(const ir_node *irn)
int
second_op
=
0
;
if
(
reg_d1
!=
reg_s1
&&
reg_d1
!=
reg_s2
)
{
be_emit_cstring
(
"
\t
mov "
);
amd64_emit_register
(
reg_s1
);
be_emit_cstring
(
", "
);
amd64_emit_register
(
reg_d1
);
be_emit_finish_line_gas
(
irn
);
amd64_emitf
(
irn
,
"mov %R, %R"
,
reg_s1
,
reg_d1
);
second_op
=
1
;
}
else
if
(
reg_d1
==
reg_s2
&&
reg_d1
!=
reg_s1
)
{
second_op
=
0
;
}
emit_amd64_binop_op
(
irn
,
second_op
);
...
...
ir/be/amd64/amd64_emitter.h
View file @
0fc6b01e
...
...
@@ -33,14 +33,25 @@
#include "bearch_amd64_t.h"
void
amd64_emit_register
(
const
arch_register_t
*
reg
);
void
amd64_emit_source_register
(
const
ir_node
*
node
,
int
pos
);
void
amd64_emit_dest_register
(
const
ir_node
*
node
,
int
pos
);
void
amd64_emit_immediate
(
const
ir_node
*
node
);
void
amd64_emit_fp_offset
(
const
ir_node
*
node
);
int
get_amd64_reg_nr
(
ir_node
*
irn
,
int
posi
,
int
in_out
);
const
char
*
get_amd64_in_reg_name
(
ir_node
*
irn
,
int
pos
);
/**
* fmt parameter output
* ---- ---------------------- ---------------------------------------------
* %% %
* %C <node> immediate value
* %Dx <node> destination register x
* %E ir_entity const* entity
* %L <node> control flow target
* %O <node> offset
* %R arch_register_t const* register
* %Sx <node> source register x
* %S* <node>, int source register
* %d signed int signed int
* %s char const* string
* %u unsigned int unsigned int
*
* x starts at 0
*/
void
amd64_emitf
(
ir_node
const
*
node
,
char
const
*
fmt
,
...);
void
amd64_gen_routine
(
ir_graph
*
irg
);
...
...
ir/be/amd64/amd64_spec.pl
View file @
0fc6b01e
...
...
@@ -121,23 +121,6 @@ $custom_init_attr_func = \&amd64_custom_init_attr;
$default_copy_attr
=
"
amd64_copy_attr
";
%emit_templates
=
(
S1
=>
"
${arch}
_emit_source_register(node, 0);
",
S2
=>
"
${arch}
_emit_source_register(node, 1);
",
S3
=>
"
${arch}
_emit_source_register(node, 2);
",
S4
=>
"
${arch}
_emit_source_register(node, 3);
",
S5
=>
"
${arch}
_emit_source_register(node, 4);
",
S6
=>
"
${arch}
_emit_source_register(node, 5);
",
D1
=>
"
${arch}
_emit_dest_register(node, 0);
",
D2
=>
"
${arch}
_emit_dest_register(node, 1);
",
D3
=>
"
${arch}
_emit_dest_register(node, 2);
",
D4
=>
"
${arch}
_emit_dest_register(node, 3);
",
D5
=>
"
${arch}
_emit_dest_register(node, 4);
",
D6
=>
"
${arch}
_emit_dest_register(node, 5);
",
C
=>
"
${arch}
_emit_immediate(node);
",
O
=>
"
${arch}
_emit_fp_offset(node);
",
);
%init_attr
=
(
amd64_attr_t
=>
"
\t
init_amd64_attributes(res, irn_flags_, in_reqs, n_res);
",
...
...
@@ -160,7 +143,7 @@ Push => {
state
=>
"
exc_pinned
",
reg_req
=>
{
in
=>
[
"
gp
",
"
gp
",
"
none
",
"
gp
",
"
rsp
"
],
out
=>
[
"
rsp:I|S
",
"
none
"
]
},
ins
=>
[
"
base
",
"
index
",
"
mem
",
"
val
",
"
stack
"
],
emit
=>
'
.
push %S
1
',
emit
=>
'
push %S
0
',
outs
=>
[
"
stack
",
"
M
"
],
am
=>
"
source,unary
",
latency
=>
2
,
...
...
@@ -186,7 +169,7 @@ Mul => {
reg_req
=>
{
in
=>
[
"
rax
",
"
gp
"
],
out
=>
[
"
rax rdx
"
]
},
ins
=>
[
"
left
",
"
right
"
],
emit
=>
'
.
mul %S
2
',
emit
=>
'
mul %S
1
',
outs
=>
[
"
res
"
],
mode
=>
$mode_gp
,
am
=>
"
source,binary
",
...
...
@@ -208,7 +191,7 @@ Neg => {
irn_flags
=>
[
"
rematerializable
"
],
reg_req
=>
{
in
=>
[
"
gp
"
],
out
=>
[
"
in_r1
",
"
flags
"
]
},
emit
=>
'
.
neg %S
1
',
emit
=>
'
neg %S
0
',
ins
=>
[
"
val
"
],
outs
=>
[
"
res
",
"
flags
"
],
mode
=>
$mode_gp
,
...
...
@@ -220,7 +203,7 @@ Immediate => {
attr
=>
"
unsigned imm_value
",
init_attr
=>
"
attr->ext.imm_value = imm_value;
",
reg_req
=>
{
out
=>
[
"
gp
"
]
},
emit
=>
'
.
mov %C, %D
1
',
emit
=>
'
mov %C, %D
0
',
mode
=>
$mode_gp
,
},
...
...
@@ -258,7 +241,7 @@ Cmp => {
out
=>
[
"
flags
"
]
},
ins
=>
[
"
left
",
"
right
"
],
outs
=>
[
"
eflags
"
],
emit
=>
'
.
cmp %S
1
, %S
2
',
emit
=>
'
cmp %S
0
, %S
1
',
attr
=>
"
int ins_permuted, int cmp_unsigned
",
init_attr
=>
"
attr->data.ins_permuted = ins_permuted;
\n
"
.
"
\t
attr->data.cmp_unsigned = cmp_unsigned;
\n
",
...
...
@@ -286,7 +269,7 @@ Load => {
outs
=>
[
"
res
",
"
M
"
],
attr
=>
"
ir_entity *entity
",
attr_type
=>
"
amd64_SymConst_attr_t
",
emit
=>
"
.
mov %O(%S
1
), %D
1
"
emit
=>
"
mov %O(%S
0
), %D
0
"
},
FrameAddr
=>
{
...
...
@@ -308,7 +291,7 @@ Store => {
attr
=>
"
ir_entity *entity
",
attr_type
=>
"
amd64_SymConst_attr_t
",
mode
=>
"
mode_M
",
emit
=>
"
.
mov %S
2
, %O(%S
1
)
"
emit
=>
"
mov %S
1
, %O(%S
0
)
"
},
#NoReg_GP => {
...
...
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