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
84d9d910
Commit
84d9d910
authored
Aug 19, 2010
by
Matthias Braun
Browse files
sparc: implement div instructions correctly
[r27952]
parent
efa9475a
Changes
3
Hide whitespace changes
Inline
Side-by-side
ir/be/sparc/sparc_emitter.c
View file @
84d9d910
...
...
@@ -412,7 +412,7 @@ static void emit_sparc_Div(const ir_node *node, bool is_signed)
be_emit_irprintf
(
"
\t
%s "
,
is_signed
?
"sdiv"
:
"udiv"
);
sparc_emit_source_register
(
node
,
1
);
be_emit_cstring
(
", "
);
sparc_emit_
source_register
(
node
,
2
);
sparc_emit_
reg_or_imm
(
node
,
2
);
be_emit_cstring
(
", "
);
sparc_emit_dest_register
(
node
,
0
);
be_emit_finish_line_gas
(
node
);
...
...
@@ -420,11 +420,7 @@ static void emit_sparc_Div(const ir_node *node, bool is_signed)
static
void
emit_sparc_SDiv
(
const
ir_node
*
node
)
{
(
void
)
node
;
/* aehm we would need an aditional register for an sra instruction to
* compute the upper bits... Just panic for now */
//emit_sparc_Div(node, true);
panic
(
"signed div is wrong"
);
emit_sparc_Div
(
node
,
true
);
}
static
void
emit_sparc_UDiv
(
const
ir_node
*
node
)
...
...
ir/be/sparc/sparc_spec.pl
View file @
84d9d910
...
...
@@ -212,6 +212,17 @@ my %binop_operand_constructors = (
},
);
my
%div_operand_constructors
=
(
imm
=>
{
attr
=>
"
ir_entity *immediate_entity, int32_t immediate_value
",
custominit
=>
"
sparc_set_attr_imm(res, immediate_entity, immediate_value);
",
reg_req
=>
{
in
=>
[
"
gp
",
"
gp
"
],
out
=>
[
"
gp
"
]
},
},
reg
=>
{
reg_req
=>
{
in
=>
[
"
gp
",
"
gp
",
"
gp
"
],
out
=>
[
"
gp
"
]
},
},
);
my
%float_binop_constructors
=
(
s => {
reg_req => { in =
>
[
"
fp
",
"
fp
"
],
out
=>
[
"
fp
"
]
},
...
...
@@ -501,24 +512,20 @@ Mulh => {
constructors
=>
\
%binop_operand_constructors
,
},
# The div instructions are kinda hacky. Things to improve:
# * Make high-value input explicitely. Either as a gp at first or ideally
# as an explicit y-register
SDiv
=>
{
irn_flags
=>
[
"
rematerializable
"
],
state
=>
"
exc_pinned
",
ins
=>
[
"
dividend_low
",
"
divisor
"
],
ins
=>
[
"
dividend_high
",
"
dividend_low
",
"
divisor
"
],
outs
=>
[
"
res
",
"
M
"
],
constructors
=>
\
%
binop
_operand_constructors
,
constructors
=>
\
%
div
_operand_constructors
,
},
UDiv
=>
{
irn_flags
=>
[
"
rematerializable
"
],
state
=>
"
exc_pinned
",
ins
=>
[
"
dividend_low
",
"
divisor
"
],
ins
=>
[
"
dividend_high
",
"
dividend_low
",
"
divisor
"
],
outs
=>
[
"
res
",
"
M
"
],
constructors
=>
\
%
binop
_operand_constructors
,
constructors
=>
\
%
div
_operand_constructors
,
},
fcmp
=>
{
...
...
ir/be/sparc/sparc_transform.c
View file @
84d9d910
...
...
@@ -272,6 +272,11 @@ static ir_node *gen_helper_unfpop(ir_node *node, ir_mode *mode,
panic
(
"unsupported mode %+F for float op"
,
mode
);
}
static
ir_node
*
get_g0
(
void
)
{
return
be_prolog_get_reg_value
(
abihelper
,
&
sparc_gp_regs
[
REG_G0
]);
}
typedef
struct
address_t
{
ir_node
*
base
;
ir_entity
*
entity
;
...
...
@@ -531,6 +536,17 @@ static ir_node *gen_Mulh(ir_node *node)
return
proj_res_hi
;
}
static
ir_node
*
gen_sign_extension_value
(
ir_node
*
node
)
{
ir_node
*
block
=
get_nodes_block
(
node
);
ir_node
*
new_block
=
be_transform_node
(
block
);
ir_node
*
new_node
=
be_transform_node
(
node
);
/* TODO: we could do some shortcuts for some value types probably.
* (For constants or other cases where we know the sign bit in
* advance) */
return
new_bd_sparc_Sra_imm
(
NULL
,
new_block
,
new_node
,
NULL
,
31
);
}
/**
* Creates an sparc Div.
*
...
...
@@ -538,17 +554,41 @@ static ir_node *gen_Mulh(ir_node *node)
*/
static
ir_node
*
gen_Div
(
ir_node
*
node
)
{
ir_mode
*
mode
=
get_Div_resmode
(
node
);
ir_node
*
res
;
dbg_info
*
dbgi
=
get_irn_dbg_info
(
node
);
ir_node
*
block
=
get_nodes_block
(
node
);
ir_node
*
new_block
=
be_transform_node
(
block
);
ir_mode
*
mode
=
get_Div_resmode
(
node
);
ir_node
*
left
=
get_Div_left
(
node
);
ir_node
*
left_low
=
be_transform_node
(
left
);
ir_node
*
right
=
get_Div_right
(
node
);
ir_node
*
res
;
assert
(
!
mode_is_float
(
mode
));
if
(
mode_is_signed
(
mode
))
{
res
=
gen_helper_binop
(
node
,
0
,
new_bd_sparc_SDiv_reg
,
new_bd_sparc_SDiv_imm
);
ir_node
*
left_high
=
gen_sign_extension_value
(
left
);
if
(
is_imm_encodeable
(
right
))
{
int32_t
immediate
=
get_tarval_long
(
get_Const_tarval
(
right
));
res
=
new_bd_sparc_SDiv_imm
(
dbgi
,
new_block
,
left_high
,
left_low
,
NULL
,
immediate
);
}
else
{
ir_node
*
new_right
=
be_transform_node
(
right
);
res
=
new_bd_sparc_SDiv_reg
(
dbgi
,
new_block
,
left_high
,
left_low
,
new_right
);
}
}
else
{
res
=
gen_helper_binop
(
node
,
0
,
new_bd_sparc_UDiv_reg
,
new_bd_sparc_UDiv_imm
);
ir_node
*
left_high
=
get_g0
();
if
(
is_imm_encodeable
(
right
))
{
int32_t
immediate
=
get_tarval_long
(
get_Const_tarval
(
right
));
res
=
new_bd_sparc_UDiv_imm
(
dbgi
,
new_block
,
left_high
,
left_low
,
NULL
,
immediate
);
}
else
{
ir_node
*
new_right
=
be_transform_node
(
right
);
res
=
new_bd_sparc_UDiv_reg
(
dbgi
,
new_block
,
left_high
,
left_low
,
new_right
);
}
}
return
res
;
}
...
...
@@ -579,11 +619,6 @@ static ir_node *gen_Abs(ir_node *node)
}
}
static
ir_node
*
get_g0
(
void
)
{
return
be_prolog_get_reg_value
(
abihelper
,
&
sparc_gp_regs
[
REG_G0
]);
}
/**
* Transforms a Not node.
*
...
...
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