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

first implementation of floatingpoint arithmetic operations

[r27825]
parent 9099772e
......@@ -222,44 +222,32 @@ void sparc_emit_mode_sign_prefix(const ir_node *node)
be_emit_string(is_signed ? "s" : "u");
}
/**
* emit FP load mode char
*/
void sparc_emit_fp_load_mode(const ir_node *node)
static void emit_fp_suffix(const ir_mode *mode)
{
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);
unsigned bits = get_mode_size_bits(mode);
assert(mode_is_float(mode));
if (bits == 32) {
be_emit_string("f");
be_emit_char('s');
} else if (bits == 64) {
be_emit_string("df");
be_emit_char('d');
} else if (bits == 128) {
be_emit_char('q');
} else {
panic("FP load mode > 64bits not implemented yet");
panic("invalid FP mode");
}
}
/**
* emit FP store mode char
*/
void sparc_emit_fp_store_mode(const ir_node *node)
void sparc_emit_fp_conv_source(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));
const sparc_fp_conv_attr_t *attr = get_sparc_fp_conv_attr_const(node);
emit_fp_suffix(attr->src_mode);
}
if (bits == 32) {
be_emit_string("f");
} else if (bits == 64) {
be_emit_string("df");
} else {
panic("FP store mode > 64bits not implemented yet");
}
void sparc_emit_fp_conv_destination(const ir_node *node)
{
const sparc_fp_conv_attr_t *attr = get_sparc_fp_conv_attr_const(node);
emit_fp_suffix(attr->dest_mode);
}
/**
......@@ -267,18 +255,8 @@ void sparc_emit_fp_store_mode(const ir_node *node)
*/
void sparc_emit_fp_mode_suffix(const ir_node *node)
{
ir_mode *mode = get_irn_mode(node);
int bits = get_mode_size_bits(mode);
assert(mode_is_float(mode));
if (bits == 32) {
be_emit_string("s");
} else if (bits == 64) {
be_emit_string("d");
} else {
panic("FP mode > 64bits not implemented yet");
}
const sparc_fp_attr_t *attr = get_sparc_fp_attr_const(node);
emit_fp_suffix(attr->fp_mode);
}
/**
......@@ -361,40 +339,6 @@ static void emit_sparc_LoImm(const ir_node *irn)
be_emit_finish_line_gas(irn);
}
/**
* emit code for div with the correct sign prefix
*/
static void emit_sparc_Div(const ir_node *irn)
{
be_emit_cstring("\t");
sparc_emit_mode_sign_prefix(irn);
be_emit_cstring("div ");
sparc_emit_source_register(irn, 0);
be_emit_cstring(", ");
sparc_emit_reg_or_imm(irn, 1);
be_emit_cstring(", ");
sparc_emit_dest_register(irn, 0);
be_emit_finish_line_gas(irn);
}
/**
* emit code for mul with the correct sign prefix
*/
static void emit_sparc_Mul(const ir_node *irn)
{
be_emit_cstring("\t");
sparc_emit_mode_sign_prefix(irn);
be_emit_cstring("mul ");
sparc_emit_source_register(irn, 0);
be_emit_cstring(", ");
sparc_emit_reg_or_imm(irn, 1);
be_emit_cstring(", ");
sparc_emit_dest_register(irn, 0);
be_emit_finish_line_gas(irn);
}
/**
* emits code for mulh
*/
......@@ -781,12 +725,10 @@ static void sparc_register_emitters(void)
set_emitter(op_be_Return, emit_be_Return);
set_emitter(op_sparc_BXX, emit_sparc_BXX);
set_emitter(op_sparc_Call, emit_sparc_Call);
set_emitter(op_sparc_Div, emit_sparc_Div);
set_emitter(op_sparc_FrameAddr, emit_sparc_FrameAddr);
set_emitter(op_sparc_HiImm, emit_sparc_HiImm);
set_emitter(op_sparc_Ba, emit_sparc_Ba);
set_emitter(op_sparc_LoImm, emit_sparc_LoImm);
set_emitter(op_sparc_Mul, emit_sparc_Mul);
set_emitter(op_sparc_Mulh, emit_sparc_Mulh);
set_emitter(op_sparc_Save, emit_sparc_Save);
set_emitter(op_sparc_SymConst, emit_sparc_SymConst);
......
......@@ -44,8 +44,8 @@ void sparc_emit_load_mode(const ir_node *node);
void sparc_emit_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_load_mode(const ir_node *node);
void sparc_emit_fp_store_mode(const ir_node *node);
void sparc_emit_fp_conv_source(const ir_node *node);
void sparc_emit_fp_conv_destination(const ir_node *node);
void sparc_gen_routine(const sparc_code_gen_t *cg, ir_graph *irg);
......
......@@ -71,6 +71,19 @@ static bool has_save_attr(const ir_node *node)
return is_sparc_Save(node);
}
static bool has_fp_attr(const ir_node *node)
{
return is_sparc_fadd(node) || is_sparc_fsub(node)
|| is_sparc_fmul(node) || is_sparc_fdiv(node)
|| is_sparc_fftoi(node) || is_sparc_fitof(node)
|| is_sparc_fneg(node);
}
static bool has_fp_conv_attr(const ir_node *node)
{
return is_sparc_fftof(node);
}
/**
* Dumper interface for dumping sparc nodes in vcg.
* @param F the output file
......@@ -120,6 +133,15 @@ static void sparc_dump_node(FILE *F, ir_node *n, dump_reason_t reason)
fprintf(F, "n projs: %d\n", attr->n_projs);
fprintf(F, "default proj: %ld\n", attr->default_proj_num);
}
if (has_fp_attr(n)) {
const sparc_fp_attr_t *attr = get_sparc_fp_attr_const(n);
ir_fprintf(F, "fp_mode: %+F\n", attr->fp_mode);
}
if (has_fp_conv_attr(n)) {
const sparc_fp_conv_attr_t *attr = get_sparc_fp_conv_attr_const(n);
ir_fprintf(F, "conv from: %+F\n", attr->src_mode);
ir_fprintf(F, "conv to: %+F\n", attr->dest_mode);
}
break;
case dump_node_nodeattr_txt:
......@@ -239,6 +261,30 @@ const sparc_save_attr_t *get_sparc_save_attr_const(const ir_node *node)
return (const sparc_save_attr_t*) get_irn_generic_attr_const(node);
}
sparc_fp_attr_t *get_sparc_fp_attr(ir_node *node)
{
assert(has_fp_attr(node));
return (sparc_fp_attr_t*) get_irn_generic_attr(node);
}
const sparc_fp_attr_t *get_sparc_fp_attr_const(const ir_node *node)
{
assert(has_fp_attr(node));
return (const sparc_fp_attr_t*) get_irn_generic_attr_const(node);
}
sparc_fp_conv_attr_t *get_sparc_fp_conv_attr(ir_node *node)
{
assert(has_fp_conv_attr(node));
return (sparc_fp_conv_attr_t*) get_irn_generic_attr(node);
}
const sparc_fp_conv_attr_t *get_sparc_fp_conv_attr_const(const ir_node *node)
{
assert(has_fp_conv_attr(node));
return (const sparc_fp_conv_attr_t*) get_irn_generic_attr_const(node);
}
/**
* Returns the argument register requirements of a sparc node.
*/
......@@ -295,7 +341,6 @@ static void init_sparc_attributes(ir_node *node, arch_irn_flags_t flags,
memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
}
/* CUSTOM ATTRIBUTE INIT FUNCTIONS */
static void init_sparc_load_store_attributes(ir_node *res, ir_mode *ls_mode,
ir_entity *entity,
int entity_sign, long offset,
......@@ -317,12 +362,26 @@ static void init_sparc_symconst_attributes(ir_node *res, ir_entity *entity)
attr->fp_offset = 0;
}
static void init_sparc_save_attr(ir_node *res, int initial_stacksize)
static void init_sparc_save_attributes(ir_node *res, int initial_stacksize)
{
sparc_save_attr_t *attr = get_sparc_save_attr(res);
attr->initial_stacksize = initial_stacksize;
}
static void init_sparc_fp_attributes(ir_node *res, ir_mode *fp_mode)
{
sparc_fp_attr_t *attr = get_sparc_fp_attr(res);
attr->fp_mode = fp_mode;
}
static void init_sparc_fp_conv_attributes(ir_node *res, ir_mode *src_mode,
ir_mode *dest_mode)
{
sparc_fp_conv_attr_t *attr = get_sparc_fp_conv_attr(res);
attr->src_mode = src_mode;
attr->dest_mode = dest_mode;
}
/**
* copies sparc attributes of node
*/
......@@ -354,8 +413,6 @@ static int cmp_attr_sparc(ir_node *a, ir_node *b)
|| attr_a->is_load_store != attr_b->is_load_store;
}
/* CUSTOM ATTRIBUTE CMP FUNCTIONS */
static int cmp_attr_sparc_load_store(ir_node *a, ir_node *b)
{
const sparc_load_store_attr_t *attr_a = get_sparc_load_store_attr_const(a);
......@@ -418,5 +475,28 @@ static int cmp_attr_sparc_save(ir_node *a, ir_node *b)
return attr_a->initial_stacksize != attr_b->initial_stacksize;
}
static int cmp_attr_sparc_fp(ir_node *a, ir_node *b)
{
const sparc_fp_attr_t *attr_a = get_sparc_fp_attr_const(a);
const sparc_fp_attr_t *attr_b = get_sparc_fp_attr_const(b);
if (cmp_attr_sparc(a, b))
return 1;
return attr_a->fp_mode != attr_b->fp_mode;
}
static int cmp_attr_sparc_fp_conv(ir_node *a, ir_node *b)
{
const sparc_fp_conv_attr_t *attr_a = get_sparc_fp_conv_attr_const(a);
const sparc_fp_conv_attr_t *attr_b = get_sparc_fp_conv_attr_const(b);
if (cmp_attr_sparc(a, b))
return 1;
return attr_a->src_mode != attr_b->src_mode
|| attr_a->dest_mode != attr_b->dest_mode;;
}
/* Include the generated constructor functions */
#include "gen_sparc_new_nodes.c.inl"
......@@ -48,6 +48,12 @@ const sparc_jmp_switch_attr_t *get_sparc_jmp_switch_attr_const(const ir_node *no
sparc_save_attr_t *get_sparc_save_attr(ir_node *node);
const sparc_save_attr_t *get_sparc_save_attr_const(const ir_node *node);
sparc_fp_attr_t *get_sparc_fp_attr(ir_node *node);
const sparc_fp_attr_t *get_sparc_fp_attr_const(const ir_node *node);
sparc_fp_conv_attr_t *get_sparc_fp_conv_attr(ir_node *node);
const sparc_fp_conv_attr_t *get_sparc_fp_conv_attr_const(const ir_node *node);
/**
* Returns the argument register requirements of an sparc node.
*/
......
......@@ -48,7 +48,14 @@ struct sparc_attr_t
typedef struct sparc_fp_attr_t sparc_fp_attr_t;
struct sparc_fp_attr_t {
sparc_attr_t base; /**< generic attribute */
double fp_immediate; /* the FP immediate value */
ir_mode *fp_mode;
};
typedef struct sparc_fp_conv_attr_t sparc_fp_conv_attr_t;
struct sparc_fp_conv_attr_t {
sparc_attr_t base;
ir_mode *src_mode;
ir_mode *dest_mode;
};
/**
......
......@@ -121,10 +121,9 @@ $state = 32; # register represents a state
IM => "${arch}_emit_immediate(node);",
LM => "${arch}_emit_load_mode(node);",
SM => "${arch}_emit_store_mode(node);",
EXTPREF => "${arch}_emit_mode_sign_prefix(node);",
FPM => "${arch}_emit_fp_mode_suffix(node);",
FPLM => "${arch}_emit_fp_load_mode(node);",
FPSM => "${arch}_emit_fp_store_mode(node);",
FCONVS => "${arch}_emit_fp_conv_source(node);",
FCONVD => "${arch}_emit_fp_conv_destination(node);",
O => "${arch}_emit_offset(node);",
);
......@@ -141,7 +140,10 @@ $default_copy_attr = "sparc_copy_attr";
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);",
sparc_fp_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
"\tinit_sparc_fp_attributes(res, fp_mode);\n",
sparc_fp_conv_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);".
"\tinit_sparc_fp_conv_attributes(res, src_mode, dest_mode);\n",
);
%compare_attr = (
......@@ -151,6 +153,8 @@ $default_copy_attr = "sparc_copy_attr";
sparc_jmp_cond_attr_t => "cmp_attr_sparc_jmp_cond",
sparc_jmp_switch_attr_t => "cmp_attr_sparc_jmp_switch",
sparc_save_attr_t => "cmp_attr_sparc_save",
sparc_fp_attr_t => "cmp_attr_sparc_fp",
sparc_fp_conv_attr_t => "cmp_attr_sparc_fp_conv",
);
# addressing modes: imm, reg, reg +/- imm, reg + reg
......@@ -273,7 +277,7 @@ Save => {
outs => [ "stack", "frame", "mem" ],
attr => "int initial_stacksize",
attr_type => "sparc_save_attr_t",
init_attr => "\tinit_sparc_save_attr(res, initial_stacksize);",
init_attr => "\tinit_sparc_save_attributes(res, initial_stacksize);",
},
SubSP => {
......@@ -421,15 +425,13 @@ Xor => {
},
Mul => {
state => "exc_pinned",
reg_req => { in => [ "gp", "gp" ], out => [ "gp", "flags" ] },
outs => [ "low", "high" ],
reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
constructors => \%binop_operand_constructors,
#emit =>'. mul %S1, %R2I, %D1'
emit => '. mul %S1, %R2I, %D1',
mode => $mode_gp,
},
Mulh => {
state => "exc_pinned",
reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
outs => [ "low", "high" ],
constructors => \%binop_operand_constructors,
......@@ -438,11 +440,10 @@ Mulh => {
Div => {
irn_flags => [ "rematerializable" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
outs => [ "res" ],
reg_req => { in => [ "gp", "gp" ], out => [ "gp", "none" ] },
outs => [ "res", "M" ],
constructors => \%binop_operand_constructors,
#mode => $mode_gp,
#emit =>'. div %S1, %R2I, %D1'
emit => '. div %S1, %R2I, %D1',
},
Minus => {
......@@ -465,59 +466,87 @@ Nop => {
emit => '. nop',
},
fAdd => {
fadd => {
op_flags => [ "commutative" ],
irn_flags => [ "rematerializable" ],
reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
emit => '. fadd%FPM %S1, %S2, %D1'
emit => '. fadd%FPM %S1, %S2, %D1',
attr_type => "sparc_fp_attr_t",
attr => "ir_mode *fp_mode",
mode => $mode_fp,
},
fMul => {
op_flags => [ "commutative" ],
fsub => {
irn_flags => [ "rematerializable" ],
reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
emit =>'. fmul%FPM %S1, %S2, %D1'
emit => '. fsub%FPM %S1, %S2, %D1',
attr_type => "sparc_fp_attr_t",
attr => "ir_mode *fp_mode",
mode => $mode_fp,
},
fsMuld => {
fmul => {
irn_flags => [ "rematerializable" ],
op_flags => [ "commutative" ],
reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
emit =>'. fsmuld %S1, %S2, %D1'
emit =>'. fmul%FPM %S1, %S2, %D1',
attr_type => "sparc_fp_attr_t",
attr => "ir_mode *fp_mode",
mode => $mode_fp,
},
FsTOd => {
fdiv => {
irn_flags => [ "rematerializable" ],
reg_req => { in => [ "fp" ], out => [ "fp" ] },
emit =>'. FsTOd %S1, %D1'
reg_req => { in => [ "fp", "fp" ], out => [ "fp", "none" ] },
emit => '. fdiv%FPM %S1, %S2, %D1',
attr_type => "sparc_fp_attr_t",
attr => "ir_mode *fp_mode",
outs => [ "res", "M" ],
},
FdTOs => {
fneg => {
irn_flags => [ "rematerializable" ],
reg_req => { in => [ "fp" ], out => [ "fp" ] },
emit =>'. FdTOs %S1, %D1'
emit => '. fneg%FPM %S1, %D1',
attr_type => "sparc_fp_attr_t",
attr => "ir_mode *fp_mode",
mode => $mode_fp,
},
FiTOs => {
"fabs" => {
irn_flags => [ "rematerializable" ],
reg_req => { in => [ "gp" ], out => [ "fp" ] },
emit =>'. FiTOs %S1, %D1'
reg_req => { in => [ "fp" ], out => [ "fp" ] },
emit => '. fabs%FPM %S1, %D1',
attr_type => "sparc_fp_attr_t",
attr => "ir_mode *fp_mode",
mode => $mode_fp,
},
FiTOd => {
fftof => {
irn_flags => [ "rematerializable" ],
reg_req => { in => [ "gp" ], out => [ "fp" ] },
emit =>'. FiTOd %S1, %D1'
reg_req => { in => [ "fp" ], out => [ "fp" ] },
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,
},
FsTOi => {
fitof => {
irn_flags => [ "rematerializable" ],
reg_req => { in => [ "fp" ], out => [ "gp" ] },
emit =>'. FsTOi %S1, %D1'
reg_req => { in => [ "gp" ], out => [ "fp" ] },
emit => '. fito%FPM %S1, %D1',
attr_type => "sparc_fp_attr_t",
attr => "ir_mode *fp_mode",
mode => $mode_fp,
},
FdTOi => {
fftoi => {
irn_flags => [ "rematerializable" ],
reg_req => { in => [ "fp" ], out => [ "gp" ] },
emit =>'. FdTOi %S1, %D1'
emit => '. f%FPM.toi %S1, %D1',
attr_type => "sparc_fp_attr_t",
attr => "ir_mode *fp_mode",
mode => $mode_gp,
},
Ldf => {
......
......@@ -148,7 +148,6 @@ static ir_node *gen_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
}
}
/**
* Creates a possible DAG for a constant.
*/
......@@ -170,7 +169,6 @@ static ir_node *create_const_graph_value(dbg_info *dbgi, ir_node *block,
return result;
}
/**
* Create a DAG constructing a given Const.
*
......@@ -257,18 +255,17 @@ 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, new_binop_fp_func new_reg)
static ir_node *gen_helper_binfpop(ir_node *node, ir_mode *mode,
new_binop_fp_func new_func)
{
ir_node *block = be_transform_node(get_nodes_block(node));
ir_node *op1 = get_binop_left(node);
ir_node *new_op1;
ir_node *new_op1 = be_transform_node(op1);
ir_node *op2 = get_binop_right(node);
ir_node *new_op2;
ir_node *new_op2 = be_transform_node(op2);
dbg_info *dbgi = get_irn_dbg_info(node);
new_op2 = be_transform_node(op2);
new_op1 = be_transform_node(op1);
return new_reg(dbgi, block, new_op1, new_op2, get_irn_mode(node));
return new_func(dbgi, block, new_op1, new_op2, mode);
}
/**
......@@ -281,13 +278,13 @@ static ir_node *gen_Add(ir_node *node)
{
ir_mode *mode = get_irn_mode(node);
if (mode_is_float(mode))
panic("FP not implemented yet");
if (mode_is_float(mode)) {
return gen_helper_binfpop(node, mode, new_bd_sparc_fadd);
}
return gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, new_bd_sparc_Add_reg, new_bd_sparc_Add_imm);
}
/**
* Creates an sparc Sub.
*
......@@ -297,13 +294,14 @@ static ir_node *gen_Add(ir_node *node)
static ir_node *gen_Sub(ir_node *node)
{
ir_mode *mode = get_irn_mode(node);
if (mode_is_float(mode))
panic("FP not implemented yet");
if (mode_is_float(mode)) {
return gen_helper_binfpop(node, mode, new_bd_sparc_fsub);
}
return gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_Sub_reg, new_bd_sparc_Sub_imm);
}
/**
* Transforms a Load.
*
......@@ -321,17 +319,16 @@ static ir_node *gen_Load(ir_node *node)
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *new_load = NULL;
if (mode_is_float(mode))
panic("SPARC: no fp implementation yet");
if (mode_is_float(mode)) {
new_load = new_bd_sparc_Ldf(dbgi, block, new_ptr, new_mem, mode, NULL, 0, 0, false);
} else {
new_load = new_bd_sparc_Ld(dbgi, block, new_ptr, new_mem, mode, NULL, 0, 0, false);
}
set_irn_pinned(new_load, get_irn_pinned(node));
return new_load;
}
/**
* Transforms a Store.
*
......@@ -351,10 +348,12 @@ static ir_node *gen_Store(ir_node *node)
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *new_store = NULL;
if (mode_is_float(mode))
panic("SPARC: no fp implementation yet");
if (mode_is_float(mode)) {
new_store = new_bd_sparc_Stf(dbgi, block, new_ptr, new_val, new_mem, mode, NULL, 0, 0, false);
} else {
new_store = new_bd_sparc_St(dbgi, block, new_ptr, new_val, new_mem, mode, NULL, 0, 0, false);
}
set_irn_pinned(new_store, get_irn_pinned(node));
return new_store;
}
......@@ -365,22 +364,16 @@ static ir_node *gen_Store(ir_node *node)
*
* @return the created sparc Mul node
*/