Commit 762a36f9 authored by Christoph Mallon's avatar Christoph Mallon
Browse files

sparc: Implement computed goto.

This fixes C/gnu99/combo_load_mode.c, C/gnu99/computed_goto.c, C/gnu99/ijmp.c, C/gnu99/vlabel2.c and C/gnu99/vlabel3.c.
parent 13884ff6
......@@ -34,6 +34,7 @@ libFirm 1.22.1 (2016-01-07)
* ir: Slightly improve preservation of debug info during transformations
* amd64: Improve use of `lea` in instruction selection
* sparc: Support the asm constaint `K`
* sparc: Support computed goto
* Bugfixes
libFirm 1.22.0 (2015-12-31)
......
......@@ -617,10 +617,12 @@ void sparc_emitf(ir_node const *const node, char const *fmt, ...)
if (!is_digit(*fmt))
goto unknown;
unsigned const pos = *fmt++ - '0';
be_emit_char('[');
if (!plus)
be_emit_char('[');
sparc_emit_source_register(node, pos);
sparc_emit_offset(node, pos + 1);
be_emit_char(']');
if (!plus)
be_emit_char(']');
break;
case 'R': {
......@@ -1238,6 +1240,12 @@ static void emit_jumptable_target(ir_entity const *const table,
sparc_emit_cfop_target(proj_x);
}
static void emit_sparc_IJmp(ir_node const *const node)
{
sparc_emitf(node, "jmp %+O0");
fill_delay_slot(node);
}
static void emit_sparc_SwitchJmp(const ir_node *node)
{
const sparc_switch_jmp_attr_t *attr = get_sparc_switch_jmp_attr_const(node);
......@@ -1312,6 +1320,7 @@ static void sparc_register_emitters(void)
be_set_emitter(op_sparc_Call, emit_sparc_Call);
be_set_emitter(op_sparc_Cas, emit_sparc_Cas);
be_set_emitter(op_sparc_FrameAddr, emit_sparc_FrameAddr);
be_set_emitter(op_sparc_IJmp, emit_sparc_IJmp);
be_set_emitter(op_sparc_Restore, emit_sparc_Restore);
be_set_emitter(op_sparc_Return, emit_sparc_Return);
be_set_emitter(op_sparc_SDiv, emit_sparc_SDiv);
......
......@@ -33,7 +33,7 @@
bool sparc_has_load_store_attr(const ir_node *node)
{
return is_sparc_Ld(node) || is_sparc_St(node) || is_sparc_Ldf(node)
|| is_sparc_Stf(node);
|| is_sparc_Stf(node) || is_sparc_IJmp(node);
}
static bool has_jmp_cond_attr(const ir_node *node)
......
......@@ -540,6 +540,28 @@ Cmp => { # aka SubccZero
emit => "cmp %S0, %SI1",
},
IJmp => {
op_flags => [ "cfopcode", "forking" ],
irn_flags => [ "has_delay_slot" ],
state => "pinned",
constructors => {
imm => {
in_reqs => [ "gp" ],
ins => [ "ptr" ],
attr => "ir_entity *entity, int32_t offset, bool is_frame_entity",
init => "init_sparc_load_store_attributes(res, NULL, entity, offset, is_frame_entity, false);",
},
reg => {
in_reqs => [ "gp", "gp" ],
ins => [ "ptr", "ptr2" ],
init => "init_sparc_load_store_attributes(res, NULL, NULL, 0, false, true);",
},
},
out_reqs => [ "exec" ],
outs => [ "jmp" ],
attr_type => "sparc_load_store_attr_t",
},
SwitchJmp => {
op_flags => [ "cfopcode", "forking" ],
irn_flags => [ "has_delay_slot" ],
......
......@@ -2358,6 +2358,21 @@ static ir_node *gen_Proj_Proj(ir_node *node)
panic("code selection didn't expect Proj(Proj) after %+F", pred_pred);
}
static ir_node *gen_IJmp(ir_node *node)
{
dbg_info *const dbgi = get_irn_dbg_info(node);
ir_node *const block = be_transform_nodes_block(node);
ir_node *const op = get_IJmp_target(node);
address_t address;
match_address(op, &address, true);
if (address.ptr2) {
assert(!address.entity && address.offset == 0);
return new_bd_sparc_IJmp_reg(dbgi, block, address.ptr, address.ptr2);
} else {
return new_bd_sparc_IJmp_imm(dbgi, block, address.ptr, address.entity, address.offset, false);
}
}
/**
* transform a Jmp
*/
......@@ -2391,6 +2406,7 @@ static void sparc_register_transformers(void)
be_set_transform_function(op_Div, gen_Div);
be_set_transform_function(op_Eor, gen_Eor);
be_set_transform_function(op_Free, gen_Free);
be_set_transform_function(op_IJmp, gen_IJmp);
be_set_transform_function(op_Jmp, gen_Jmp);
be_set_transform_function(op_Load, gen_Load);
be_set_transform_function(op_Member, gen_Member);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment