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
10790875
Commit
10790875
authored
Mar 26, 2013
by
Matthias Braun
Browse files
sparc: add support for more asm constraints
parent
f179d707
Changes
8
Hide whitespace changes
Inline
Side-by-side
ir/be/sparc/bearch_sparc.c
View file @
10790875
...
...
@@ -169,25 +169,6 @@ static sparc_isa_t sparc_isa_template = {
SPARC_FPU_ARCH_FPU
,
/* FPU architecture */
};
static
void
init_asm_constraints
(
void
)
{
asm_constraint_flags
[
'r'
]
=
ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER
;
asm_constraint_flags
[
'e'
]
=
ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER
;
asm_constraint_flags
[
'f'
]
=
ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER
;
asm_constraint_flags
[
'A'
]
=
ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE
;
asm_constraint_flags
[
'I'
]
=
ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE
;
asm_constraint_flags
[
'='
]
=
ASM_CONSTRAINT_FLAG_MODIFIER_WRITE
|
ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ
;
asm_constraint_flags
[
'+'
]
=
ASM_CONSTRAINT_FLAG_MODIFIER_READ
|
ASM_CONSTRAINT_FLAG_MODIFIER_WRITE
;
/* Note there are many more flags in gcc which we can't properly support
* at the moment. see gcc/config/sparc/constraints.md
* Not supported: 'f', 'e', 'c', 'd', 'b', 'h', 'D', 'J', 'K',
* 'L', 'M', 'N', 'O', 'G', 'H', 'Q', 'R', 'S', 'T', 'U', 'W', 'Y' */
}
/**
* rewrite unsigned->float conversion.
* Sparc has no instruction for this so instead we do the following:
...
...
@@ -394,7 +375,7 @@ static void sparc_handle_intrinsics(void)
static
void
sparc_init
(
void
)
{
init_asm_constraints
();
sparc_
init_asm_constraints
();
sparc_register_init
();
sparc_create_opcodes
(
&
sparc_irn_ops
);
sparc_cconv_init
();
...
...
@@ -517,12 +498,6 @@ static const backend_params *sparc_get_backend_params(void)
return
&
p
;
}
static
int
sparc_is_valid_clobber
(
const
char
*
clobber
)
{
(
void
)
clobber
;
return
0
;
}
/* fpu set architectures. */
static
const
lc_opt_enum_int_items_t
sparc_fpu_items
[]
=
{
{
"fpu"
,
SPARC_FPU_ARCH_FPU
},
...
...
ir/be/sparc/sparc_emitter.c
View file @
10790875
...
...
@@ -63,13 +63,9 @@ static void sparc_emit_indent(void)
be_emit_char
(
' '
);
}
static
void
sparc_emit_immediate
(
i
r_node
const
*
const
node
)
static
void
sparc_emit_immediate
(
i
nt32_t
value
,
ir_entity
*
entity
)
{
const
sparc_attr_t
*
attr
=
get_sparc_attr_const
(
node
);
ir_entity
*
entity
=
attr
->
immediate_value_entity
;
if
(
entity
==
NULL
)
{
int32_t
value
=
attr
->
immediate_value
;
assert
(
sparc_is_value_imm_encodeable
(
value
));
be_emit_irprintf
(
"%d"
,
value
);
}
else
{
...
...
@@ -79,8 +75,8 @@ static void sparc_emit_immediate(ir_node const *const node)
be_emit_cstring
(
"%lo("
);
}
be_gas_emit_entity
(
entity
);
if
(
attr
->
immediate_
value
!=
0
)
{
be_emit_irprintf
(
"%+d"
,
attr
->
immediate_
value
);
if
(
value
!=
0
)
{
be_emit_irprintf
(
"%+d"
,
value
);
}
be_emit_char
(
')'
);
}
...
...
@@ -108,18 +104,22 @@ static void sparc_emit_high_immediate(ir_node const *node)
}
}
static
void
sparc_emit_
source_
register
(
ir_node
const
*
node
,
in
t
const
pos
)
static
void
sparc_emit_register
(
const
arch_register_
t
*
const
reg
)
{
const
arch_register_t
*
reg
=
arch_get_irn_register_in
(
node
,
pos
);
be_emit_char
(
'%'
);
be_emit_string
(
reg
->
name
);
}
static
void
sparc_emit_source_register
(
ir_node
const
*
node
,
int
const
pos
)
{
const
arch_register_t
*
reg
=
arch_get_irn_register_in
(
node
,
pos
);
sparc_emit_register
(
reg
);
}
static
void
sparc_emit_dest_register
(
ir_node
const
*
const
node
,
int
const
pos
)
{
const
arch_register_t
*
reg
=
arch_get_irn_register_out
(
node
,
pos
);
be_emit_char
(
'%'
);
be_emit_string
(
reg
->
name
);
sparc_emit_register
(
reg
);
}
/**
...
...
@@ -144,7 +144,8 @@ static void sparc_emit_offset(const ir_node *node, int offset_node_pos)
}
else
if
(
attr
->
base
.
immediate_value
!=
0
||
attr
->
base
.
immediate_value_entity
!=
NULL
)
{
be_emit_char
(
'+'
);
sparc_emit_immediate
(
node
);
sparc_emit_immediate
(
attr
->
base
.
immediate_value
,
attr
->
base
.
immediate_value_entity
);
}
}
...
...
@@ -658,7 +659,9 @@ void sparc_emitf(ir_node const *const node, char const *fmt, ...)
goto
unknown
;
unsigned
const
pos
=
*
fmt
++
-
'0'
;
if
(
imm
&&
arch_get_irn_flags
(
node
)
&
(
arch_irn_flags_t
)
sparc_arch_irn_flag_immediate_form
)
{
sparc_emit_immediate
(
node
);
const
sparc_attr_t
*
const
attr
=
get_sparc_attr_const
(
node
);
sparc_emit_immediate
(
attr
->
immediate_value
,
attr
->
immediate_value_entity
);
}
else
{
sparc_emit_source_register
(
node
,
pos
);
}
...
...
@@ -707,6 +710,59 @@ static void emit_be_IncSP(const ir_node *irn)
sparc_emitf
(
irn
,
"%s %S0, %d, %D0"
,
insn
,
offset
);
}
static
const
char
*
emit_asm_operand
(
const
ir_node
*
node
,
const
char
*
s
)
{
assert
(
*
s
==
'%'
);
char
c
=
*
(
++
s
);
/* parse modifiers */
if
(
c
==
'\0'
)
{
ir_fprintf
(
stderr
,
"Warning: asm text (%+F) ends with %%
\n
"
,
node
);
be_emit_char
(
'%'
);
return
s
;
}
else
if
(
c
==
'%'
)
{
be_emit_char
(
'%'
);
return
s
+
1
;
}
else
if
(
c
<
'0'
||
c
>
'9'
)
{
ir_fprintf
(
stderr
,
"Warning: asm text (%+F) contains unknown modifier '%c' for asm op
\n
"
,
node
,
c
);
return
s
+
1
;
}
/* parse number */
int
num
=
0
;
int
p
=
0
;
sscanf
(
s
,
"%d%n"
,
&
num
,
&
p
);
s
+=
p
;
const
sparc_asm_attr_t
*
const
attr
=
get_sparc_asm_attr_const
(
node
);
const
sparc_asm_operand_t
*
const
operands
=
attr
->
operands
;
if
((
size_t
)
num
>
ARR_LEN
(
operands
))
{
ir_fprintf
(
stderr
,
"Error: Custom assembler references invalid input/output (%+F)
\n
"
,
node
);
return
s
;
}
const
sparc_asm_operand_t
*
const
operand
=
&
operands
[
num
];
const
arch_register_t
*
reg
=
NULL
;
switch
(
operand
->
kind
)
{
case
ASM_OPERAND_IMMEDIATE
:
sparc_emit_immediate
(
operand
->
immediate_value
,
operand
->
immediate_value_entity
);
return
s
;
case
ASM_OPERAND_INPUT_VALUE
:
reg
=
arch_get_irn_register_in
(
node
,
operand
->
pos
);
break
;
case
ASM_OPERAND_OUTPUT_VALUE
:
reg
=
arch_get_irn_register_out
(
node
,
operand
->
pos
);
break
;
}
/* emit the register */
sparc_emit_register
(
reg
);
return
s
;
}
static
void
emit_sparc_ASM
(
const
ir_node
*
node
)
{
be_emit_cstring
(
"#APP
\n
"
);
...
...
@@ -717,7 +773,13 @@ static void emit_sparc_ASM(const ir_node *node)
if
(
s
[
0
]
!=
'\t'
)
be_emit_char
(
'\t'
);
be_emit_string
(
s
);
while
(
*
s
!=
0
)
{
if
(
*
s
==
'%'
)
{
s
=
emit_asm_operand
(
node
,
s
);
}
else
{
be_emit_char
(
*
s
++
);
}
}
be_emit_cstring
(
"
\n
#NO_APP
\n
"
);
be_emit_write_line
();
...
...
ir/be/sparc/sparc_lower64.c
View file @
10790875
...
...
@@ -12,6 +12,7 @@
#include "bearch_sparc_t.h"
#include "error.h"
#include "sparc_nodes_attr.h"
#include "gen_sparc_new_nodes.h"
#include "lower_dw.h"
#include "ircons_t.h"
...
...
ir/be/sparc/sparc_new_nodes.c
View file @
10790875
...
...
@@ -274,10 +274,12 @@ static void init_sparc_switch_jmp_attributes(ir_node *node,
}
}
static
void
init_sparc_asm_attributes
(
ir_node
*
node
,
ident
*
text
)
static
void
init_sparc_asm_attributes
(
ir_node
*
node
,
ident
*
text
,
const
sparc_asm_operand_t
*
operands
)
{
sparc_asm_attr_t
*
attr
=
get_sparc_asm_attr
(
node
);
attr
->
text
=
text
;
attr
->
text
=
text
;
attr
->
operands
=
operands
;
}
/**
...
...
ir/be/sparc/sparc_nodes_attr.h
View file @
10790875
...
...
@@ -81,10 +81,24 @@ struct sparc_switch_jmp_attr_t {
ir_entity
*
table_entity
;
};
typedef
enum
operand_kind_t
{
ASM_OPERAND_INPUT_VALUE
,
ASM_OPERAND_OUTPUT_VALUE
,
ASM_OPERAND_IMMEDIATE
}
operand_kind_t
;
typedef
struct
sparc_asm_operand_t
{
operand_kind_t
kind
;
unsigned
pos
;
int32_t
immediate_value
;
ir_entity
*
immediate_value_entity
;
}
sparc_asm_operand_t
;
typedef
struct
sparc_asm_attr_t
sparc_asm_attr_t
;
struct
sparc_asm_attr_t
{
sparc_attr_t
base
;
ident
*
text
;
sparc_attr_t
base
;
ident
*
text
;
const
sparc_asm_operand_t
*
operands
;
};
enum
n_sparc_Return
{
...
...
ir/be/sparc/sparc_spec.pl
View file @
10790875
...
...
@@ -115,7 +115,7 @@ $default_copy_attr = "sparc_copy_attr";
sparc_fp_conv_attr_t
=>
"
\t
init_sparc_attributes(res, irn_flags_, in_reqs, n_res);
\n
"
.
"
\t
init_sparc_fp_conv_attributes(res, src_mode, dest_mode);
\n
",
sparc_asm_attr_t
=>
"
\t
init_sparc_attributes(res, irn_flags_, in_reqs, n_res);
\n
"
.
"
\t
init_sparc_asm_attributes(res, text);
",
"
\t
init_sparc_asm_attributes(res, text
, operands
);
",
);
%compare_attr
=
(
...
...
@@ -243,10 +243,9 @@ my %float_unop_constructors = (
ASM
=>
{
state
=>
"
exc_pinned
",
reg_req
=>
{
in
=>
[
"
none
"
],
out
=>
[
"
none
"
]
},
ins
=>
[
"
mem
"
],
outs
=>
[
"
M
"
],
attr
=>
"
ident *text
",
arity
=>
"
variable
",
out_arity
=>
"
variable
",
attr
=>
"
ident *text, const sparc_asm_operand_t *operands
",
attr_type
=>
"
sparc_asm_attr_t
",
},
...
...
ir/be/sparc/sparc_transform.c
View file @
10790875
...
...
@@ -220,6 +220,365 @@ static ir_node *skip_downconv(ir_node *node)
return
node
;
}
/**
* An assembler constraint.
*/
typedef
struct
constraint_t
{
const
arch_register_class_t
*
cls
;
char
all_registers_allowed
;
char
immediate_type
;
int
same_as
;
}
constraint_t
;
static
void
parse_asm_constraints
(
constraint_t
*
const
constraint
,
ident
*
const
constraint_text
,
bool
const
is_output
)
{
memset
(
constraint
,
0
,
sizeof
(
constraint
[
0
]));
constraint
->
same_as
=
-
1
;
char
const
*
c
=
get_id_str
(
constraint_text
);
if
(
*
c
==
'\0'
)
{
/* a memory constraint: no need to do anything in backend about it
* (the dependencies are already respected by the memory edge of
* the node) */
return
;
}
char
immediate_type
=
'\0'
;
arch_register_class_t
const
*
cls
=
NULL
;
bool
all_registers_allowed
=
false
;
int
same_as
=
-
1
;
while
(
*
c
!=
0
)
{
arch_register_class_t
const
*
new_cls
=
NULL
;
char
new_imm
=
'\0'
;
switch
(
*
c
)
{
/* Skip spaces, out/in-out marker */
case
' '
:
case
'\t'
:
case
'\n'
:
case
'='
:
case
'+'
:
case
'&'
:
break
;
case
'*'
:
++
c
;
break
;
case
'#'
:
while
(
*
c
!=
0
&&
*
c
!=
','
)
++
c
;
break
;
case
'r'
:
new_cls
=
&
sparc_reg_classes
[
CLASS_sparc_gp
];
all_registers_allowed
=
true
;
break
;
case
'e'
:
case
'f'
:
new_cls
=
&
sparc_reg_classes
[
CLASS_sparc_fp
];
all_registers_allowed
=
true
;
break
;
case
'A'
:
case
'I'
:
new_cls
=
&
sparc_reg_classes
[
CLASS_sparc_gp
];
new_imm
=
*
c
;
break
;
case
'0'
:
case
'1'
:
case
'2'
:
case
'3'
:
case
'4'
:
case
'5'
:
case
'6'
:
case
'7'
:
case
'8'
:
case
'9'
:
{
if
(
is_output
)
panic
(
"can only specify same constraint on input"
);
int
p
;
sscanf
(
c
,
"%d%n"
,
&
same_as
,
&
p
);
if
(
same_as
>=
0
)
{
c
+=
p
;
continue
;
}
break
;
}
default:
panic
(
"unknown asm constraint '%c' found in (%+F)"
,
*
c
,
current_ir_graph
);
}
if
(
new_cls
)
{
if
(
!
cls
)
{
cls
=
new_cls
;
}
else
if
(
cls
!=
new_cls
)
{
panic
(
"multiple register classes not supported"
);
}
}
if
(
new_imm
!=
'\0'
)
{
if
(
immediate_type
==
'\0'
)
{
immediate_type
=
new_imm
;
}
else
if
(
immediate_type
!=
new_imm
)
{
panic
(
"multiple immediate types not supported"
);
}
}
++
c
;
}
if
(
same_as
>=
0
)
{
if
(
cls
!=
NULL
)
panic
(
"same as and register constraint not supported"
);
if
(
immediate_type
!=
'\0'
)
panic
(
"same as and immediate constraint not supported"
);
}
if
(
!
cls
&&
same_as
<
0
)
panic
(
"no constraint specified for assembler input"
);
constraint
->
same_as
=
same_as
;
constraint
->
cls
=
cls
;
constraint
->
all_registers_allowed
=
all_registers_allowed
;
constraint
->
immediate_type
=
immediate_type
;
}
static
const
arch_register_t
*
find_register
(
const
char
*
name
)
{
for
(
size_t
i
=
0
;
i
<
N_SPARC_REGISTERS
;
++
i
)
{
const
arch_register_t
*
const
reg
=
&
sparc_registers
[
i
];
if
(
strcmp
(
reg
->
name
,
name
)
==
0
)
return
reg
;
}
return
NULL
;
}
static
arch_register_req_t
const
*
make_register_req
(
ir_graph
*
const
irg
,
constraint_t
const
*
const
c
,
int
const
n_outs
,
arch_register_req_t
const
**
const
out_reqs
,
int
const
pos
)
{
int
const
same_as
=
c
->
same_as
;
if
(
same_as
>=
0
)
{
if
(
same_as
>=
n_outs
)
panic
(
"invalid output number in same_as constraint"
);
struct
obstack
*
const
obst
=
get_irg_obstack
(
irg
);
arch_register_req_t
*
const
req
=
OALLOC
(
obst
,
arch_register_req_t
);
arch_register_req_t
const
*
const
other
=
out_reqs
[
same_as
];
*
req
=
*
other
;
req
->
type
|=
arch_register_req_type_should_be_same
;
req
->
other_same
=
1U
<<
pos
;
/* Switch constraints. This is because in firm we have same_as
* constraints on the output constraints while in the gcc asm syntax
* they are specified on the input constraints. */
out_reqs
[
same_as
]
=
req
;
return
other
;
}
return
c
->
cls
->
class_req
;
}
void
sparc_init_asm_constraints
(
void
)
{
static
unsigned
char
const
register_flags
[]
=
{
'r'
,
'e'
,
'f'
,
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
};
for
(
size_t
i
=
0
;
i
<
ARRAY_SIZE
(
register_flags
);
++
i
)
{
unsigned
char
const
c
=
register_flags
[
i
];
asm_constraint_flags
[
c
]
=
ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER
;
}
asm_constraint_flags
[
'A'
]
=
ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE
;
asm_constraint_flags
[
'I'
]
=
ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE
;
/* Note there are many more flags in gcc which we can't properly support
* at the moment. see gcc/config/sparc/constraints.md */
}
int
sparc_is_valid_clobber
(
const
char
*
clobber
)
{
return
strcmp
(
clobber
,
"memory"
)
==
0
||
strcmp
(
clobber
,
"cc"
)
==
0
;
}
static
ir_node
*
gen_ASM
(
ir_node
*
node
)
{
int
n_inputs
=
get_ASM_n_inputs
(
node
);
size_t
n_clobbers
=
0
;
ident
**
clobbers
=
get_ASM_clobbers
(
node
);
ir_graph
*
irg
=
get_irn_irg
(
node
);
//unsigned clobber_bits[BITSET_SIZE_ELEMS(N_SPARC_REGISTERS)];
for
(
size_t
c
=
0
;
c
<
get_ASM_n_clobbers
(
node
);
++
c
)
{
const
char
*
const
clobber
=
get_id_str
(
clobbers
[
c
]);
if
(
strcmp
(
clobber
,
"memory"
)
==
0
)
continue
;
if
(
strcmp
(
clobber
,
"cc"
)
==
0
)
{
n_clobbers
+=
2
;
continue
;
}
const
arch_register_t
*
reg
=
find_register
(
clobber
);
if
(
reg
==
NULL
)
panic
(
"invalid clobber in sparc asm"
);
#if 0
rbitset_set(clobber_bits, reg->global_index);
++n_clobbers;
#else
panic
(
"clobbers not correctly supported yet"
);
#endif
}
size_t
n_out_constraints
=
get_ASM_n_output_constraints
(
node
);
size_t
n_outs
=
n_out_constraints
+
n_clobbers
;
const
ir_asm_constraint
*
in_constraints
=
get_ASM_input_constraints
(
node
);
const
ir_asm_constraint
*
out_constraints
=
get_ASM_output_constraints
(
node
);
/* determine number of operands */
unsigned
n_operands
=
0
;
for
(
size_t
out_idx
=
0
;
out_idx
<
n_out_constraints
;
++
out_idx
)
{
const
ir_asm_constraint
*
constraint
=
&
out_constraints
[
out_idx
];
if
(
constraint
->
pos
+
1
>
n_operands
)
n_operands
=
constraint
->
pos
+
1
;
}
for
(
int
i
=
0
;
i
<
n_inputs
;
++
i
)
{
const
ir_asm_constraint
*
constraint
=
&
in_constraints
[
i
];
if
(
constraint
->
pos
+
1
>
n_operands
)
n_operands
=
constraint
->
pos
+
1
;
}
struct
obstack
*
const
obst
=
get_irg_obstack
(
irg
);
sparc_asm_operand_t
*
const
operands
=
NEW_ARR_DZ
(
sparc_asm_operand_t
,
obst
,
n_operands
);
/* construct output constraints */
size_t
out_size
=
n_outs
+
1
;
const
arch_register_req_t
**
out_reg_reqs
=
OALLOCN
(
obst
,
const
arch_register_req_t
*
,
out_size
);
size_t
out_idx
;
for
(
out_idx
=
0
;
out_idx
<
n_out_constraints
;
++
out_idx
)
{
const
ir_asm_constraint
*
constraint
=
&
out_constraints
[
out_idx
];
unsigned
pos
=
constraint
->
pos
;
constraint_t
parsed_constraint
;
parse_asm_constraints
(
&
parsed_constraint
,
constraint
->
constraint
,
true
);
assert
(
parsed_constraint
.
immediate_type
==
0
);
arch_register_req_t
const
*
const
req
=
make_register_req
(
irg
,
&
parsed_constraint
,
n_out_constraints
,
out_reg_reqs
,
out_idx
);
out_reg_reqs
[
out_idx
]
=
req
;
/* TODO: adjust register_req for clobbers */
sparc_asm_operand_t
*
const
operand
=
&
operands
[
pos
];
operand
->
kind
=
ASM_OPERAND_OUTPUT_VALUE
;
operand
->
pos
=
out_idx
;
}
/* inputs + input constraints */
int
max_ins
=
n_inputs
+
1
;
ir_node
**
in
=
ALLOCANZ
(
ir_node
*
,
max_ins
);
const
arch_register_req_t
**
in_reg_reqs
=
OALLOCN
(
obst
,
const
arch_register_req_t
*
,
max_ins
);
int
n_ins
=
0
;
for
(
int
i
=
0
;
i
<
n_inputs
;
++
i
)
{
ir_node
*
pred
=
get_ASM_input
(
node
,
i
);
const
ir_asm_constraint
*
constraint
=
&
in_constraints
[
i
];
unsigned
pos
=
constraint
->
pos
;
constraint_t
parsed_constraint
;
parse_asm_constraints
(
&
parsed_constraint
,
constraint
->
constraint
,
false
);
sparc_asm_operand_t
*
const
operand
=
&
operands
[
pos
];
/* try to use an immediate value */
char
imm_type
=
parsed_constraint
.
immediate_type
;
if
(
imm_type
==
'I'
)
{
if
(
is_imm_encodeable
(
pred
))
{
operand
->
kind
=
ASM_OPERAND_IMMEDIATE
;
operand
->
immediate_value
=
get_tarval_long
(
get_Const_tarval
(
pred
));
continue
;
}
}
else
if
(
imm_type
==
'A'
)
{
/* TODO: match Add(SymConst,Const), ... */
if
(
is_SymConst
(
pred
))
{
operand
->
kind
=
ASM_OPERAND_IMMEDIATE
;
operand
->
immediate_value_entity
=
get_SymConst_entity
(
pred
);
continue
;
}
else
if
(
is_Const
(
pred
))
{
operand
->
kind
=
ASM_OPERAND_IMMEDIATE
;
operand
->
immediate_value
=
get_tarval_long
(
get_Const_tarval
(
pred
));
continue
;
}
}
arch_register_req_t
const
*
const
req
=
make_register_req
(
irg
,
&
parsed_constraint
,
n_out_constraints
,
out_reg_reqs
,
i
);
in_reg_reqs
[
i
]
=
req
;
int
op_pos
=
n_ins
++
;
ir_node
*
new_pred
=
be_transform_node
(
pred
);
in
[
op_pos
]
=
new_pred
;
operand
->
kind
=
ASM_OPERAND_INPUT_VALUE
;
operand
->
pos
=
op_pos
;
}
int
mem_pos
=
n_ins
++
;
ir_node
*
mem
=
get_ASM_mem
(
node
);
in
[
mem_pos
]
=
be_transform_node
(
mem
);
in_reg_reqs
[
mem_pos
]
=
arch_no_register_req
;
/* parse clobbers */
for
(
size_t
c
=
0
;
c
<
get_ASM_n_clobbers
(
node
);
++
c
)
{
const
char
*
const
clobber
=
get_id_str
(
clobbers
[
c
]);
if
(
strcmp
(
clobber
,
"memory"
)
==
0
)
continue
;
if
(
strcmp
(
clobber
,
"cc"
)
==
0
)
{
const
arch_register_t
*
flags_reg
=
&
sparc_registers
[
REG_FLAGS
];
out_reg_reqs
[
out_idx
++
]
=
flags_reg
->
single_req
;
const
arch_register_t
*
fpflags_reg
=
&
sparc_registers
[
REG_FPFLAGS
];
out_reg_reqs
[
out_idx
++
]
=
fpflags_reg
->
single_req
;
continue
;
}
const
arch_register_t
*
reg
=
find_register
(
clobber
);
assert
(
reg
!=
NULL
);
/* otherwise we had a panic earlier */
out_reg_reqs
[
out_idx
++
]
=
reg
->
single_req
;
}
/* append none register requirement for the memory output */
if
(
n_outs
+
1
>=
out_size
)
{
out_size
=
n_outs
+
1
;
const
arch_register_req_t
**
new_out_reg_reqs
=
OALLOCN
(
obst
,
const
arch_register_req_t
*
,
out_size
);
memcpy
(
new_out_reg_reqs
,
out_reg_reqs
,
n_outs
*
sizeof
(
new_out_reg_reqs
[
0
]));
out_reg_reqs
=