Commit a24d3e41 authored by Matthias Braun's avatar Matthias Braun
Browse files

sparc: mostly implement reg+reg address mode

[r27956]
parent 208f6937
......@@ -185,7 +185,7 @@ static void transform_Reload(ir_node *node)
ir_node *sched_point = sched_prev(node);
load = new_bd_sparc_Ld(dbgi, block, ptr, mem, mode, entity, 0, true);
load = new_bd_sparc_Ld_imm(dbgi, block, ptr, mem, mode, entity, 0, true);
sched_add_after(sched_point, load);
sched_remove(node);
......@@ -213,7 +213,7 @@ static void transform_Spill(ir_node *node)
ir_node *store;
sched_point = sched_prev(node);
store = new_bd_sparc_St(dbgi, block, ptr, val, mem, mode, entity, 0, true);
store = new_bd_sparc_St_imm(dbgi, block, val, ptr, mem, mode, entity, 0, true);
sched_remove(node);
sched_add_after(sched_point, store);
......
......@@ -191,11 +191,17 @@ static bool is_stack_pointer_relative(const ir_node *node)
/**
* emit SP offset
*/
void sparc_emit_offset(const ir_node *node)
void sparc_emit_offset(const ir_node *node, int offset_node_pos)
{
const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
if (attr->is_frame_entity) {
if (attr->is_reg_reg) {
assert(!attr->is_frame_entity);
assert(attr->base.immediate_value == 0);
assert(attr->base.immediate_value_entity == NULL);
be_emit_char('+');
sparc_emit_source_register(node, offset_node_pos);
} else if (attr->is_frame_entity) {
int32_t offset = attr->base.immediate_value;
/* bad hack: the real stack stuff is behind the always-there spill
* space for the register window and stack */
......@@ -205,7 +211,8 @@ void sparc_emit_offset(const ir_node *node)
assert(is_valid_immediate(offset));
be_emit_irprintf("%+ld", offset);
}
} else {
} else if (attr->base.immediate_value != 0
|| attr->base.immediate_value_entity != NULL) {
be_emit_char('+');
sparc_emit_immediate(node);
}
......
......@@ -40,7 +40,7 @@ void sparc_emit_mode(const ir_node *node);
void sparc_emit_source_register(const ir_node *node, int pos);
void sparc_emit_reg_or_imm(const ir_node *node, int pos);
void sparc_emit_dest_register(const ir_node *node, int pos);
void sparc_emit_offset(const ir_node *node);
void sparc_emit_offset(const ir_node *node, int offset_node_pos);
void sparc_emit_load_mode(const ir_node *node);
void sparc_emit_store_mode(const ir_node *node);
void sparc_emit_float_load_store_mode(const ir_node *node);
......
......@@ -325,13 +325,15 @@ static void init_sparc_attributes(ir_node *node, arch_irn_flags_t flags,
static void init_sparc_load_store_attributes(ir_node *res, ir_mode *ls_mode,
ir_entity *entity, int32_t offset,
bool is_frame_entity)
bool is_frame_entity,
bool is_reg_reg)
{
sparc_load_store_attr_t *attr = get_sparc_load_store_attr(res);
attr->base.immediate_value_entity = entity;
attr->base.immediate_value = offset;
attr->load_store_mode = ls_mode;
attr->is_frame_entity = is_frame_entity;
attr->is_reg_reg = is_reg_reg;
}
static void init_sparc_save_attributes(ir_node *res, int initial_stacksize)
......
......@@ -79,7 +79,8 @@ typedef struct sparc_load_store_attr_t sparc_load_store_attr_t;
struct sparc_load_store_attr_t {
sparc_attr_t base; /**< generic attribute */
ir_mode *load_store_mode;
bool is_frame_entity;
bool is_frame_entity : 1;
bool is_reg_reg : 1;
};
/**
......
......@@ -137,7 +137,8 @@ $state = 32; # register represents a state
FPM => "${arch}_emit_fp_mode_suffix(node);",
FCONVS => "${arch}_emit_fp_conv_source(node);",
FCONVD => "${arch}_emit_fp_conv_destination(node);",
O => "${arch}_emit_offset(node);",
O2 => "${arch}_emit_offset(node, 1);",
O3 => "${arch}_emit_offset(node, 2);",
);
$default_attr_type = "sparc_attr_t";
......@@ -146,8 +147,7 @@ $default_copy_attr = "sparc_copy_attr";
%init_attr = (
sparc_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
sparc_load_store_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
"\tinit_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity);",
sparc_load_store_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
sparc_jmp_cond_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
sparc_jmp_switch_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
sparc_save_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
......@@ -275,18 +275,23 @@ Ld => {
op_flags => [ "labeled", "fragile" ],
state => "exc_pinned",
constructors => {
"" => {
imm => {
reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
ins => [ "ptr", "mem" ],
attr => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
custominit => "init_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity, false);",
},
d => {
reg_req => { in => [ "gp", "none" ], out => [ "gp:a|2", "none" ] },
reg => {
reg_req => { in => [ "gp", "gp", "none" ], out => [ "gp", "none" ] },
ins => [ "ptr", "ptr2", "mem" ],
attr => "ir_mode *ls_mode",
custominit => "init_sparc_load_store_attributes(res, ls_mode, NULL, 0, false, true);",
},
},
outs => [ "res", "M" ],
ins => [ "ptr", "mem" ],
outs => [ "res", "M" ],
attr_type => "sparc_load_store_attr_t",
attr => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
emit => '. ld%LM [%S1%O], %D1'
emit => '. ld%LM [%S1%O2], %D1'
},
SetHi => {
......@@ -304,18 +309,23 @@ St => {
mode => "mode_M",
state => "exc_pinned",
constructors => {
"" => {
imm => {
reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
ins => [ "val", "ptr", "mem" ],
attr => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
custominit => "init_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity, false);",
},
d => {
reg_req => { in => [ "gp", "gp:a|2", "none" ], out => [ "none" ] },
reg => {
reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "none" ] },
ins => [ "val", "ptr", "ptr2", "mem" ],
attr => "ir_mode *ls_mode",
custominit => "init_sparc_load_store_attributes(res, ls_mode, NULL, 0, false, true);",
},
},
ins => [ "ptr", "val", "mem" ],
ins => [ "val", "ptr", "mem" ],
outs => [ "M" ],
attr_type => "sparc_load_store_attr_t",
attr => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
emit => '. st%SM %S2, [%S1%O]'
emit => '. st%SM %S1, [%S2%O3]'
},
Save => {
......@@ -694,7 +704,8 @@ Ldf => {
outs => [ "res", "M" ],
attr_type => "sparc_load_store_attr_t",
attr => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
emit => '. ld%FLSM [%S1%O], %D1'
custominit => "init_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity, false);",
emit => '. ld%FLSM [%S1%O2], %D1'
},
Stf => {
......@@ -702,20 +713,21 @@ Stf => {
state => "exc_pinned",
constructors => {
s => {
reg_req => { in => [ "gp", "fp", "none" ], out => [ "none" ] },
reg_req => { in => [ "fp", "gp", "none" ], out => [ "none" ] },
},
d => {
reg_req => { in => [ "gp", "fp:a|2", "none" ], out => [ "none" ] },
reg_req => { in => [ "fp:a|2", "gp", "none" ], out => [ "none" ] },
},
q => {
reg_req => { in => [ "gp", "fp:a|4", "none" ], out => [ "none" ] },
reg_req => { in => [ "fp:a|4", "gp", "none" ], out => [ "none" ] },
},
},
ins => [ "ptr", "val", "mem" ],
ins => [ "val", "ptr", "mem" ],
outs => [ "M" ],
attr_type => "sparc_load_store_attr_t",
attr => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
emit => '. st%FLSM %S2, [%S1%O]',
custominit => "init_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity, false);",
emit => '. st%FLSM %S2, [%S1%O2]',
mode => 'mode_M',
},
......
......@@ -278,14 +278,19 @@ static ir_node *get_g0(void)
}
typedef struct address_t {
ir_node *base;
ir_node *ptr;
ir_node *ptr2;
ir_entity *entity;
int32_t offset;
} address_t;
static void match_address(ir_node *ptr, address_t *address)
/**
* Match a load/store address
*/
static void match_address(ir_node *ptr, address_t *address, bool use_ptr2)
{
ir_node *base = ptr;
ir_node *ptr2 = NULL;
int32_t offset = 0;
ir_entity *entity = NULL;
......@@ -308,6 +313,9 @@ static void match_address(ir_node *ptr, address_t *address)
ir_node *new_block = be_transform_node(block);
entity = get_SymConst_entity(base);
base = new_bd_sparc_SetHi(dbgi, new_block, entity, offset);
} else if (use_ptr2 && is_Add(base) && entity == NULL && offset == 0) {
ptr2 = be_transform_node(get_Add_right(base));
base = be_transform_node(get_Add_left(base));
} else {
if (is_value_imm_encodeable(offset)) {
base = be_transform_node(base);
......@@ -317,7 +325,8 @@ static void match_address(ir_node *ptr, address_t *address)
}
}
address->base = base;
address->ptr = base;
address->ptr2 = ptr2;
address->entity = entity;
address->offset = offset;
}
......@@ -351,9 +360,10 @@ static ir_node *gen_Add(ir_node *node)
ir_node *block = be_transform_node(get_nodes_block(node));
address_t address;
match_address(node, &address);
assert(is_sparc_SetHi(address.base));
return new_bd_sparc_Or_imm(dbgi, block, address.base,
/* the value of use_ptr2 shouldn't matter here */
match_address(node, &address, false);
assert(is_sparc_SetHi(address.ptr));
return new_bd_sparc_Or_imm(dbgi, block, address.ptr,
address.entity, address.offset);
}
......@@ -409,22 +419,22 @@ static ir_node *create_ldf(dbg_info *dbgi, ir_node *block, ir_node *ptr,
}
}
static ir_node *create_stf(dbg_info *dbgi, ir_node *block, ir_node *ptr,
ir_node *value, ir_node *mem, ir_mode *mode,
static ir_node *create_stf(dbg_info *dbgi, ir_node *block, ir_node *value,
ir_node *ptr, ir_node *mem, ir_mode *mode,
ir_entity *entity, long offset,
bool is_frame_entity)
{
unsigned bits = get_mode_size_bits(mode);
assert(mode_is_float(mode));
if (bits == 32) {
return new_bd_sparc_Stf_s(dbgi, block, ptr, value, mem, mode, entity,
return new_bd_sparc_Stf_s(dbgi, block, value, ptr, mem, mode, entity,
offset, is_frame_entity);
} else if (bits == 64) {
return new_bd_sparc_Stf_d(dbgi, block, ptr, value, mem, mode, entity,
return new_bd_sparc_Stf_d(dbgi, block, value, ptr, mem, mode, entity,
offset, is_frame_entity);
} else {
assert(bits == 128);
return new_bd_sparc_Stf_q(dbgi, block, ptr, value, mem, mode, entity,
return new_bd_sparc_Stf_q(dbgi, block, value, ptr, mem, mode, entity,
offset, is_frame_entity);
}
}
......@@ -446,14 +456,21 @@ static ir_node *gen_Load(ir_node *node)
ir_node *new_load = NULL;
address_t address;
match_address(ptr, &address);
if (mode_is_float(mode)) {
new_load = create_ldf(dbgi, block, address.base, new_mem, mode,
match_address(ptr, &address, false);
new_load = create_ldf(dbgi, block, address.ptr, new_mem, mode,
address.entity, address.offset, false);
} else {
new_load = new_bd_sparc_Ld(dbgi, block, address.base, new_mem, mode,
address.entity, address.offset, false);
match_address(ptr, &address, true);
if (address.ptr2 != NULL) {
assert(address.entity == NULL && address.offset == 0);
new_load = new_bd_sparc_Ld_reg(dbgi, block, address.ptr,
address.ptr2, new_mem, mode);
} else {
new_load = new_bd_sparc_Ld_imm(dbgi, block, address.ptr, new_mem,
mode, address.entity, address.offset,
false);
}
}
set_irn_pinned(new_load, get_irn_pinned(node));
......@@ -479,15 +496,22 @@ static ir_node *gen_Store(ir_node *node)
ir_node *new_store = NULL;
address_t address;
match_address(ptr, &address);
if (mode_is_float(mode)) {
new_store = create_stf(dbgi, block, address.base, new_val, new_mem,
/* TODO: variants with reg+reg address mode */
match_address(ptr, &address, false);
new_store = create_stf(dbgi, block, new_val, address.ptr, new_mem,
mode, address.entity, address.offset, false);
} else {
new_store = new_bd_sparc_St(dbgi, block, address.base, new_val, new_mem,
mode, address.entity, address.offset,
false);
match_address(ptr, &address, true);
if (address.ptr2 != NULL) {
assert(address.entity == NULL && address.offset == 0);
new_store = new_bd_sparc_St_reg(dbgi, block, new_val, address.ptr,
address.ptr2, new_mem, mode);
} else {
new_store = new_bd_sparc_St_imm(dbgi, block, new_val, address.ptr,
new_mem, mode, address.entity,
address.offset, false);
}
}
set_irn_pinned(new_store, get_irn_pinned(node));
......@@ -1246,16 +1270,16 @@ static ir_node *bitcast_int_to_float(dbg_info *dbgi, ir_node *block,
ir_graph *irg = current_ir_graph;
ir_node *sp = get_irg_frame(irg);
ir_node *nomem = new_NoMem();
ir_node *st = new_bd_sparc_St(dbgi, block, sp, value0, nomem, mode_gp,
NULL, 0, true);
ir_node *st = new_bd_sparc_St_imm(dbgi, block, value0, sp, nomem,
mode_gp, NULL, 0, true);
ir_mode *mode;
ir_node *ldf;
ir_node *mem;
set_irn_pinned(st, op_pin_state_floats);
if (value1 != NULL) {
ir_node *st1 = new_bd_sparc_St(dbgi, block, sp, value1, nomem, mode_gp,
NULL, 4, true);
ir_node *st1 = new_bd_sparc_St_imm(dbgi, block, value1, sp, nomem,
mode_gp, NULL, 4, true);
ir_node *in[2] = { st, st1 };
ir_node *sync = new_r_Sync(block, 2, in);
set_irn_pinned(st1, op_pin_state_floats);
......@@ -1279,18 +1303,18 @@ static void bitcast_float_to_int(dbg_info *dbgi, ir_node *block,
ir_graph *irg = current_ir_graph;
ir_node *stack = get_irg_frame(irg);
ir_node *nomem = new_NoMem();
ir_node *stf = create_stf(dbgi, block, stack, node, nomem, float_mode,
ir_node *stf = create_stf(dbgi, block, node, stack, nomem, float_mode,
NULL, 0, true);
int bits = get_mode_size_bits(float_mode);
ir_node *ld;
set_irn_pinned(stf, op_pin_state_floats);
ld = new_bd_sparc_Ld(dbgi, block, stack, stf, mode_gp, NULL, 0, true);
ld = new_bd_sparc_Ld_imm(dbgi, block, stack, stf, mode_gp, NULL, 0, true);
set_irn_pinned(ld, op_pin_state_floats);
result[0] = new_Proj(ld, mode_gp, pn_sparc_Ld_res);
if (bits == 64) {
ir_node *ld2 = new_bd_sparc_Ld(dbgi, block, stack, stf, mode_gp,
ir_node *ld2 = new_bd_sparc_Ld_imm(dbgi, block, stack, stf, mode_gp,
NULL, 4, true);
set_irn_pinned(ld, op_pin_state_floats);
result[1] = new_Proj(ld2, mode_gp, pn_sparc_Ld_res);
......@@ -1399,11 +1423,11 @@ static ir_node *gen_Call(ir_node *node)
/* create a parameter frame if necessary */
if (mode_is_float(mode)) {
str = create_stf(dbgi, new_block, incsp, new_value, new_mem,
str = create_stf(dbgi, new_block, new_value, incsp, new_mem,
mode, NULL, param->offset, true);
} else {
str = new_bd_sparc_St(dbgi, new_block, incsp, new_value, new_mem,
mode, NULL, param->offset, true);
str = new_bd_sparc_St_imm(dbgi, new_block, new_value, incsp,
new_mem, mode, NULL, param->offset, true);
}
set_irn_pinned(str, op_pin_state_floats);
sync_ins[sync_arity++] = str;
......@@ -1725,7 +1749,7 @@ static ir_node *gen_Proj_Proj_Start(ir_node *node)
} else if (param->entity != NULL) {
ir_node *fp = be_prolog_get_reg_value(abihelper, fp_reg);
ir_node *mem = be_prolog_get_memory(abihelper);
ir_node *ld = new_bd_sparc_Ld(NULL, new_block, fp, mem,
ir_node *ld = new_bd_sparc_Ld_imm(NULL, new_block, fp, mem,
mode_gp, param->entity,
0, true);
value1 = new_Proj(ld, mode_gp, pn_sparc_Ld_res);
......@@ -1748,7 +1772,7 @@ static ir_node *gen_Proj_Proj_Start(ir_node *node)
param->entity, 0, true);
value = new_r_Proj(load, mode_fp, pn_sparc_Ldf_res);
} else {
load = new_bd_sparc_Ld(NULL, new_block, fp, mem, mode,
load = new_bd_sparc_Ld_imm(NULL, new_block, fp, mem, mode,
param->entity, 0, true);
value = new_r_Proj(load, mode_gp, pn_sparc_Ld_res);
}
......
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