Commit 5b17692e authored by Matthias Braun's avatar Matthias Braun
Browse files

use new double wide register requirements; implement calling convention for sparc 64bit floats

[r27846]
parent 2abb418b
......@@ -85,7 +85,7 @@ typedef enum arch_register_req_type_t {
/** The register must be unequal from some other at the node. */
arch_register_req_type_must_be_different = 1U << 3,
/** The registernumber should be aligned (in case of multiregister values)*/
arch_register_req_type_must_be_aligned = 1U << 4,
arch_register_req_type_aligned = 1U << 4,
/** ignore while allocating registers */
arch_register_req_type_ignore = 1U << 5,
/** the output produces a new value for the stack pointer
......
......@@ -1263,6 +1263,7 @@ sub generate_requirements {
my $idx = shift;
my $is_in = shift;
my $class = "";
my $width = 1;
my $result;
my @req_type_mask;
......@@ -1272,6 +1273,10 @@ sub generate_requirements {
push(@req_type_mask, "arch_register_req_type_ignore");
} elsif ($f eq "S") {
push(@req_type_mask, "arch_register_req_type_produces_sp");
} elsif ($f eq "a") {
push(@req_type_mask, "arch_register_req_type_aligned");
} elsif ($f eq "2" or $f eq "4" or $f eq "8") {
$width = int($f);
}
}
}
......@@ -1300,7 +1305,7 @@ EOF
NULL, /* limit bitset */
0, /* same pos */
0, /* different pos */
1 /* width */
$width /* width */
};
EOF
......@@ -1336,7 +1341,7 @@ EOF
${limit_bitset},
${same_pos}, /* same pos */
${different_pos}, /* different pos */
1 /* width */
$width /* width */
};
EOF
......
......@@ -263,11 +263,13 @@ static void sparc_collect_frame_entity_nodes(ir_node *node, void *data)
attr = get_sparc_load_store_attr_const(node);
entity = attr->entity;
mode = attr->load_store_mode;
align = get_mode_size_bytes(mode);
if (entity != NULL)
return;
if (!attr->is_frame_entity)
return;
if (arch_irn_get_flags(node) & sparc_arch_irn_flag_needs_64bit_spillslot)
mode = mode_Lu;
align = get_mode_size_bytes(mode);
be_node_needs_frame_entity(env, node, mode, align);
}
......
......@@ -71,7 +71,6 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type,
ir_mode *mode = get_type_mode(param_type);
int bits = get_mode_size_bits(mode);
reg_or_stackslot_t *param = &params[i];
param->type = param_type;
if (regnum < n_param_regs) {
const arch_register_t *reg = param_regs[regnum++];
......@@ -79,6 +78,7 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type,
reg = map_i_to_o_reg(reg);
param->reg0 = reg;
} else {
param->type = param_type;
param->offset = stack_offset;
/* increase offset 4 bytes so everything is aligned */
stack_offset += bits > 32 ? bits/8 : 4;
......
......@@ -170,6 +170,21 @@ void sparc_emit_offset(const ir_node *node)
}
}
void sparc_emit_float_load_store_mode(const ir_node *node)
{
const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
ir_mode *mode = attr->load_store_mode;
int bits = get_mode_size_bits(mode);
assert(mode_is_float(mode));
switch (bits) {
case 32: return;
case 64: be_emit_char('d'); return;
case 128: be_emit_char('q'); return;
}
panic("invalid flaot load/store mode %+F", mode);
}
/**
* Emit load mode char
......@@ -186,7 +201,7 @@ void sparc_emit_load_mode(const ir_node *node)
} else if (bits == 8) {
be_emit_string(is_signed ? "sb" : "ub");
} else if (bits == 64) {
be_emit_string("d");
be_emit_char('d');
} else {
assert(bits == 32);
}
......@@ -206,7 +221,7 @@ void sparc_emit_store_mode(const ir_node *node)
} else if (bits == 8) {
be_emit_string("b");
} else if (bits == 64) {
be_emit_string("d");
be_emit_char('d');
} else {
assert(bits == 32);
}
......
......@@ -42,6 +42,7 @@ void sparc_emit_dest_register(const ir_node *node, int pos);
void sparc_emit_offset(const ir_node *node);
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);
void sparc_emit_mode_sign_prefix(const ir_node *node);
void sparc_emit_fp_mode_suffix(const ir_node *node);
void sparc_emit_fp_conv_source(const ir_node *node);
......
......@@ -43,8 +43,9 @@ struct sparc_attr_t
};
enum sparc_arch_irn_flags_t {
sparc_arch_irn_flag_modifies_flags = arch_irn_flags_backend << 0,
sparc_arch_irn_flag_modifies_fp_flags = arch_irn_flags_backend << 1,
sparc_arch_irn_flag_modifies_flags = arch_irn_flags_backend << 0,
sparc_arch_irn_flag_modifies_fp_flags = arch_irn_flags_backend << 1,
sparc_arch_irn_flag_needs_64bit_spillslot = arch_irn_flags_backend << 2,
};
/**
......
......@@ -6,7 +6,9 @@ $arch = "sparc";
$mode_gp = "mode_Iu";
$mode_flags = "mode_Bu";
$mode_fpflags = "mode_Bu";
$mode_fp = "mode_D";
$mode_fp = "mode_F";
$mode_fp2 = "mode_D";
$mode_fp4 = "mode_E"; # not correct, we need to register a new mode
$normal = 0; # no special type
$caller_save = 1; # caller save (register must be saved by the caller of a function)
......@@ -130,6 +132,7 @@ $state = 32; # register represents a state
IM => "${arch}_emit_immediate(node);",
LM => "${arch}_emit_load_mode(node);",
SM => "${arch}_emit_store_mode(node);",
FLSM => "${arch}_emit_float_load_store_mode(node);",
FPM => "${arch}_emit_fp_mode_suffix(node);",
FCONVS => "${arch}_emit_fp_conv_source(node);",
FCONVD => "${arch}_emit_fp_conv_destination(node);",
......@@ -211,6 +214,24 @@ my %binop_operand_constructors = (
},
);
my %float_binop_constructors = (
s => {
reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
ins => [ "left", "right" ],
mode => $mode_fp,
},
d => {
reg_req => { in => [ "fp:a|2", "fp:a|2" ], out => [ "fp:a|2" ] },
ins => [ "left", "right" ],
mode => $mode_fp2,
},
q => {
reg_req => { in => [ "fp:a|4", "fp:a|4" ], out => [ "fp:a|4" ] },
ins => [ "left", "right" ],
mode => $mode_fp4,
}
);
%nodes = (
Add => {
......@@ -233,9 +254,16 @@ Sub => {
Ld => {
op_flags => [ "labeled", "fragile" ],
state => "exc_pinned",
ins => [ "ptr", "mem" ],
constructors => {
"" => {
reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
},
d => {
reg_req => { in => [ "gp", "none" ], out => [ "gp:a|2", "none" ] },
},
},
outs => [ "res", "M" ],
reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
ins => [ "ptr", "mem" ],
attr_type => "sparc_load_store_attr_t",
attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
emit => '. ld%LM [%S1%O], %D1'
......@@ -264,11 +292,18 @@ LoImm => {
St => {
op_flags => [ "labeled", "fragile" ],
mode => "mode_M",
mode => "mode_M",
state => "exc_pinned",
constructors => {
"" => {
reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
},
d => {
reg_req => { in => [ "gp", "gp:a|2", "none" ], out => [ "none" ] },
},
},
ins => [ "ptr", "val", "mem" ],
outs => [ "M" ],
reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
attr_type => "sparc_load_store_attr_t",
attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
emit => '. st%SM %S2, [%S1%O]'
......@@ -522,7 +557,7 @@ fadd => {
emit => '. fadd%FPM %S1, %S2, %D1',
attr_type => "sparc_fp_attr_t",
attr => "ir_mode *fp_mode",
mode => $mode_fp,
constructors => \%float_binop_constructors,
},
fsub => {
......@@ -531,7 +566,7 @@ fsub => {
emit => '. fsub%FPM %S1, %S2, %D1',
attr_type => "sparc_fp_attr_t",
attr => "ir_mode *fp_mode",
mode => $mode_fp,
constructors => \%float_binop_constructors,
},
fmul => {
......@@ -541,7 +576,7 @@ fmul => {
emit =>'. fmul%FPM %S1, %S2, %D1',
attr_type => "sparc_fp_attr_t",
attr => "ir_mode *fp_mode",
mode => $mode_fp,
constructors => \%float_binop_constructors,
},
fdiv => {
......@@ -551,6 +586,7 @@ fdiv => {
attr_type => "sparc_fp_attr_t",
attr => "ir_mode *fp_mode",
outs => [ "res", "M" ],
constructors => \%float_binop_constructors,
},
fneg => {
......@@ -568,13 +604,13 @@ fneg => {
emit => '. fabs%FPM %S1, %D1',
attr_type => "sparc_fp_attr_t",
attr => "ir_mode *fp_mode",
mode => $mode_fp,
constructors => \%float_binop_constructors,
},
fftof => {
irn_flags => [ "rematerializable" ],
reg_req => { in => [ "fp" ], out => [ "fp" ] },
emit => '. f%FCONVS.to%FCONVD %S1, %D1',
emit => '. f%FCONVS%.to%FCONVD %S1, %D1',
attr_type => "sparc_fp_conv_attr_t",
attr => "ir_mode *src_mode, ir_mode *dest_mode",
mode => $mode_fp,
......@@ -606,7 +642,7 @@ Ldf => {
reg_req => { in => [ "gp", "none" ], out => [ "fp", "none" ] },
attr_type => "sparc_load_store_attr_t",
attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
emit => '. ld [%S1%O], %D1'
emit => '. ld%FLSM [%S1%O], %D1'
},
Stf => {
......@@ -617,7 +653,7 @@ Stf => {
reg_req => { in => [ "gp", "fp", "none" ], out => [ "none" ] },
attr_type => "sparc_load_store_attr_t",
attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
emit => '. st %S2, [%S1%O]',
emit => '. st%FLSM %S2, [%S1%O]',
mode => 'mode_M',
},
......
......@@ -62,6 +62,8 @@ static const arch_register_t *fp_reg = &sparc_gp_regs[REG_FRAME_POINTER];
static calling_convention_t *cconv = NULL;
static ir_mode *mode_gp;
static ir_mode *mode_fp;
static ir_mode *mode_fp2;
//static ir_mode *mode_fp4;
static pmap *node_to_stack;
static ir_node *gen_SymConst(ir_node *node);
......@@ -208,8 +210,6 @@ static bool is_imm_encodeable(const ir_node *node)
{
long val;
//assert(mode_is_float_vector(get_irn_mode(node)));
if (!is_Const(node))
return false;
......@@ -254,7 +254,9 @@ static ir_node *gen_helper_binop(ir_node *node, match_flags_t flags,
* helper function for FP binop operations
*/
static ir_node *gen_helper_binfpop(ir_node *node, ir_mode *mode,
new_binop_fp_func new_func)
new_binop_fp_func new_func_single,
new_binop_fp_func new_func_double,
new_binop_fp_func new_func_quad)
{
ir_node *block = be_transform_node(get_nodes_block(node));
ir_node *op1 = get_binop_left(node);
......@@ -262,8 +264,19 @@ static ir_node *gen_helper_binfpop(ir_node *node, ir_mode *mode,
ir_node *op2 = get_binop_right(node);
ir_node *new_op2 = be_transform_node(op2);
dbg_info *dbgi = get_irn_dbg_info(node);
return new_func(dbgi, block, new_op1, new_op2, mode);
unsigned bits = get_mode_size_bits(mode);
switch (bits) {
case 32:
return new_func_single(dbgi, block, new_op1, new_op2, mode);
case 64:
return new_func_double(dbgi, block, new_op1, new_op2, mode);
case 128:
return new_func_quad(dbgi, block, new_op1, new_op2, mode);
default:
break;
}
panic("unsupported mode %+F for float op", mode);
}
/**
......@@ -277,7 +290,8 @@ static ir_node *gen_Add(ir_node *node)
ir_mode *mode = get_irn_mode(node);
if (mode_is_float(mode)) {
return gen_helper_binfpop(node, mode, new_bd_sparc_fadd);
return gen_helper_binfpop(node, mode, new_bd_sparc_fadd_s,
new_bd_sparc_fadd_d, new_bd_sparc_fadd_q);
}
return gen_helper_binop(node, MATCH_COMMUTATIVE, new_bd_sparc_Add_reg, new_bd_sparc_Add_imm);
......@@ -294,7 +308,8 @@ static ir_node *gen_Sub(ir_node *node)
ir_mode *mode = get_irn_mode(node);
if (mode_is_float(mode)) {
return gen_helper_binfpop(node, mode, new_bd_sparc_fsub);
return gen_helper_binfpop(node, mode, new_bd_sparc_fsub_s,
new_bd_sparc_fsub_d, new_bd_sparc_fsub_q);
}
return gen_helper_binop(node, MATCH_NONE, new_bd_sparc_Sub_reg, new_bd_sparc_Sub_imm);
......@@ -366,7 +381,8 @@ static ir_node *gen_Mul(ir_node *node)
{
ir_mode *mode = get_irn_mode(node);
if (mode_is_float(mode)) {
return gen_helper_binfpop(node, mode, new_bd_sparc_fmul);
return gen_helper_binfpop(node, mode, new_bd_sparc_fmul_s,
new_bd_sparc_fmul_d, new_bd_sparc_fmul_q);
}
assert(mode_is_data(mode));
......@@ -422,7 +438,8 @@ static ir_node *gen_Quot(ir_node *node)
{
ir_mode *mode = get_Quot_resmode(node);
assert(mode_is_float(mode));
return gen_helper_binfpop(node, mode, new_bd_sparc_fdiv);
return gen_helper_binfpop(node, mode, new_bd_sparc_fdiv_s,
new_bd_sparc_fdiv_d, new_bd_sparc_fdiv_q);
}
/**
......@@ -442,8 +459,10 @@ static ir_node *gen_Abs(ir_node *node) {
ir_node *mov, *sra, *xor, *sub, *new_op;
if (mode_is_float(mode))
panic("FP not supported yet");
if (mode_is_float(mode)) {
return gen_helper_binfpop(node, mode, new_bd_sparc_fabs_s,
new_bd_sparc_fdiv_d, new_bd_sparc_fdiv_q);
}
new_op = be_transform_node(op);
......@@ -1071,37 +1090,66 @@ static ir_node *gen_Return(ir_node *node)
}
static ir_node *bitcast_int_to_float(dbg_info *dbgi, ir_node *block,
ir_node *node)
ir_node *value0, ir_node *value1)
{
ir_graph *irg = current_ir_graph;
ir_node *stack = get_irg_frame(irg);
ir_node *sp = get_irg_frame(irg);
ir_node *nomem = new_NoMem();
ir_node *st = new_bd_sparc_St(dbgi, block, stack, node, nomem, mode_gp,
ir_node *st = new_bd_sparc_St(dbgi, block, sp, value0, nomem, mode_gp,
NULL, 0, 0, true);
ir_mode *mode;
ir_node *ldf;
ir_node *mem;
set_irn_pinned(st, op_pin_state_floats);
ldf = new_bd_sparc_Ldf(dbgi, block, stack, st, mode_fp, NULL, 0, 0, true);
if (value1 != NULL) {
ir_node *st1 = new_bd_sparc_St(dbgi, block, sp, value1, nomem, mode_gp,
NULL, 0, 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);
mem = sync;
mode = mode_fp2;
} else {
mem = st;
mode = mode_fp;
}
ldf = new_bd_sparc_Ldf(dbgi, block, sp, mem, mode, NULL, 0, 0, true);
set_irn_pinned(ldf, op_pin_state_floats);
return new_Proj(ldf, mode_fp, pn_sparc_Ldf_res);
return new_Proj(ldf, mode, pn_sparc_Ldf_res);
}
static ir_node *bitcast_float_to_int(dbg_info *dbgi, ir_node *block,
ir_node *node)
static void bitcast_float_to_int(dbg_info *dbgi, ir_node *block,
ir_node *node, ir_mode *float_mode,
ir_node **result)
{
ir_graph *irg = current_ir_graph;
ir_node *stack = get_irg_frame(irg);
ir_node *nomem = new_NoMem();
ir_node *stf = new_bd_sparc_Stf(dbgi, block, stack, node, nomem, mode_fp,
NULL, 0, 0, true);
ir_node *stf = new_bd_sparc_Stf(dbgi, block, stack, node, nomem,
float_mode, NULL, 0, 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, 0, true);
set_irn_pinned(ld, op_pin_state_floats);
result[0] = new_Proj(ld, mode_gp, pn_sparc_Ld_res);
return new_Proj(ld, mode_fp, pn_sparc_Ld_res);
if (bits == 64) {
ir_node *ld2 = new_bd_sparc_Ld(dbgi, block, stack, stf, mode_gp,
NULL, 0, 4, true);
set_irn_pinned(ld, op_pin_state_floats);
result[1] = new_Proj(ld2, mode_gp, pn_sparc_Ld_res);
arch_irn_add_flags(ld, sparc_arch_irn_flag_needs_64bit_spillslot);
arch_irn_add_flags(ld2, sparc_arch_irn_flag_needs_64bit_spillslot);
} else {
assert(bits == 32);
result[1] = NULL;
}
}
static ir_node *gen_Call(ir_node *node)
......@@ -1161,37 +1209,40 @@ static ir_node *gen_Call(ir_node *node)
for (p = 0; p < n_params; ++p) {
ir_node *value = get_Call_param(node, p);
ir_node *new_value = be_transform_node(value);
ir_node *new_value1 = NULL;
const reg_or_stackslot_t *param = &cconv->parameters[p];
ir_type *param_type = get_method_param_type(type, p);
ir_mode *mode = get_type_mode(param_type);
ir_node *new_values[2];
ir_node *str;
if (mode_is_float(mode) && param->reg0 != NULL) {
unsigned size_bits = get_mode_size_bits(mode);
assert(size_bits == 32);
new_value = bitcast_float_to_int(dbgi, new_block, new_value);
assert(size_bits <= 64);
bitcast_float_to_int(dbgi, new_block, new_value, mode, new_values);
} else {
new_values[0] = new_value;
new_values[1] = NULL;
}
/* put value into registers */
if (param->reg0 != NULL) {
in[in_arity] = new_value;
in[in_arity] = new_values[0];
in_req[in_arity] = param->reg0->single_req;
++in_arity;
if (new_value1 == NULL)
if (new_values[1] == NULL)
continue;
}
if (param->reg1 != NULL) {
assert(new_value1 != NULL);
in[in_arity] = new_value1;
assert(new_values[1] != NULL);
in[in_arity] = new_values[1];
in_req[in_arity] = param->reg1->single_req;
++in_arity;
continue;
}
/* we need a store if we're here */
if (new_value1 != NULL) {
new_value = new_value1;
if (new_values[1] != NULL) {
new_value = new_values[1];
mode = mode_gp;
}
......@@ -1471,8 +1522,21 @@ static ir_node *gen_Proj_Proj_Start(ir_node *node)
ir_node *value = be_prolog_get_reg_value(abihelper, reg);
if (mode_is_float(mode)) {
ir_node *value1 = NULL;
if (param->reg1 != NULL) {
value1 = be_prolog_get_reg_value(abihelper, param->reg1);
} 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,
mode_gp, param->entity,
0, 0, true);
value1 = new_Proj(ld, mode_gp, pn_sparc_Ld_res);
}
/* convert integer value to float */
value = bitcast_int_to_float(NULL, new_block, value);
value = bitcast_int_to_float(NULL, new_block, value, value1);
}
return value;
} else {
......@@ -1690,8 +1754,10 @@ void sparc_transform_graph(sparc_code_gen_t *cg)
node_to_stack = pmap_create();
mode_gp = mode_Iu;
mode_fp = mode_F;
mode_gp = mode_Iu;
mode_fp = mode_F;
mode_fp2 = mode_D;
//mode_fp4 = ?
abihelper = be_abihelper_prepare(irg);
be_collect_stacknodes(abihelper);
......
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