Commit 70b9a908 authored by Hannes Rapp's avatar Hannes Rapp
Browse files

- SPEC gzip laeuft

- Code soweit bereinigt

[r27734]
parent 2e33d052
......@@ -51,6 +51,8 @@
#include "gen_sparc_emitter.h"
#include "sparc_nodes_attr.h"
#include "sparc_new_nodes.h"
#include "gen_sparc_regalloc_if.h"
#define SNPRINTF_BUF_LEN 128
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
......@@ -129,11 +131,8 @@ static const arch_register_t *get_out_reg(const ir_node *node, int pos)
void sparc_emit_immediate(const ir_node *node)
{
// TODO: make sure it's a valid simm13 ?
const sparc_attr_t *attr = get_sparc_attr_const(node);
assert(!(attr->immediate_value < -4096 || attr->immediate_value > 4096));
be_emit_irprintf("%d", attr->immediate_value);
}
......@@ -221,6 +220,75 @@ void sparc_emit_store_mode(const ir_node *node)
}
}
/**
* emit integer signed/unsigned prefix char
*/
void sparc_emit_mode_sign_prefix(const ir_node *node)
{
ir_mode *mode = get_irn_mode(node);
bool is_signed = mode_is_signed(mode);
be_emit_string(is_signed ? "s" : "u");
}
/**
* emit FP load mode char
*/
void sparc_emit_fp_load_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));
if (bits == 32) {
be_emit_string("f");
} else if (bits == 64) {
be_emit_string("df");
} else {
panic("FP load mode > 64bits not implemented yet");
}
}
/**
* emit FP store mode char
*/
void sparc_emit_fp_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));
if (bits == 32) {
be_emit_string("f");
} else if (bits == 64) {
be_emit_string("df");
} else {
panic("FP store mode > 64bits not implemented yet");
}
}
/**
* emits the FP mode suffix char
*/
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");
}
}
/**
* Returns the target label for a control flow node.
*/
......@@ -275,8 +343,7 @@ static void emit_be_IncSP(const ir_node *irn)
}
/**
* emits code for save instruction
* and sets the current save_attr pointer
* emits code for save instruction with min. required stack space
*/
static void emit_sparc_Save(const ir_node *irn)
{
......@@ -313,6 +380,65 @@ 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
*/
static void emit_sparc_Mulh(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);
// our result is in the y register now
// we just copy it to the assigned target reg
be_emit_cstring("\tmov ");
be_emit_char('%');
be_emit_string(arch_register_get_name(&sparc_flags_regs[REG_Y]));
be_emit_cstring(", ");
sparc_emit_dest_register(irn, 0);
be_emit_finish_line_gas(irn);
}
/**
* Emits code for return node
......@@ -350,7 +476,7 @@ static void emit_be_Call(const ir_node *irn)
}
/**
* TODO: check if this is correct
* Emit code for Perm node
*/
static void emit_be_Perm(const ir_node *irn)
{
......@@ -379,6 +505,54 @@ static void emit_be_Perm(const ir_node *irn)
be_emit_finish_line_gas(irn);
}
/**
* TODO: not really tested but seems to work with memperm_arity == 1
*/
static void emit_be_MemPerm(const ir_node *node)
{
int i;
int memperm_arity;
int sp_change = 0;
/* TODO: this implementation is slower than necessary.
The longterm goal is however to avoid the memperm node completely */
memperm_arity = be_get_MemPerm_entity_arity(node);
// we use our local registers - so this is limited to 8 inputs !
if (memperm_arity > 8)
panic("memperm with more than 8 inputs not supported yet");
for (i = 0; i < memperm_arity; ++i) {
int offset;
ir_entity *entity = be_get_MemPerm_in_entity(node, i);
/* spill register */
sp_change += 4;
be_emit_irprintf("\tst %%l%d, [%%sp-%d]", i, sp_change);
be_emit_finish_line_gas(node);
/* load from entity */
offset = get_entity_offset(entity) + sp_change;
be_emit_irprintf("\tld [%%sp+%d], %%l%d", offset, i);
be_emit_finish_line_gas(node);
}
for (i = memperm_arity-1; i >= 0; --i) {
int offset;
ir_entity *entity = be_get_MemPerm_out_entity(node, i);
/* store to new entity */
offset = get_entity_offset(entity) + sp_change;
be_emit_irprintf("\tst %%l%d, [%%sp+%d]", i, offset);
be_emit_finish_line_gas(node);
/* restore register */
be_emit_irprintf("\tld [%%sp-%d], %%l%d", sp_change, i);
sp_change -= 4;
be_emit_finish_line_gas(node);
}
assert(sp_change == 0);
}
/**
* Emit a SymConst.
*/
......@@ -405,7 +579,6 @@ static void emit_sparc_SymConst(const ir_node *irn)
be_emit_finish_line_gas(irn);
}
/**
* Emits code for FrameAddr fix
*/
......@@ -605,22 +778,26 @@ static void sparc_register_emitters(void)
sparc_register_spec_emitters();
/* custom emitter */
set_emitter(op_be_IncSP, emit_be_IncSP);
set_emitter(op_be_Return, emit_be_Return);
set_emitter(op_be_Call, emit_be_Call);
set_emitter(op_sparc_FrameAddr, emit_sparc_FrameAddr);
set_emitter(op_sparc_Branch, emit_sparc_Branch);
set_emitter(op_sparc_SymConst, emit_sparc_SymConst);
set_emitter(op_sparc_Jmp, emit_sparc_Jmp);
set_emitter(op_sparc_Save, emit_sparc_Save);
set_emitter(op_sparc_HiImm, emit_sparc_HiImm);
set_emitter(op_sparc_LoImm, emit_sparc_LoImm);
set_emitter(op_be_Copy, emit_be_Copy);
set_emitter(op_be_CopyKeep, emit_be_Copy);
set_emitter(op_be_Perm, emit_be_Perm);
set_emitter(op_be_IncSP, emit_be_IncSP);
set_emitter(op_be_Return, emit_be_Return);
set_emitter(op_be_Call, emit_be_Call);
set_emitter(op_sparc_FrameAddr, emit_sparc_FrameAddr);
set_emitter(op_sparc_Branch, emit_sparc_Branch);
set_emitter(op_sparc_SymConst, emit_sparc_SymConst);
set_emitter(op_sparc_Jmp, emit_sparc_Jmp);
set_emitter(op_sparc_Save, emit_sparc_Save);
set_emitter(op_sparc_HiImm, emit_sparc_HiImm);
set_emitter(op_sparc_LoImm, emit_sparc_LoImm);
set_emitter(op_sparc_Div, emit_sparc_Div);
set_emitter(op_sparc_Mul, emit_sparc_Mul);
set_emitter(op_sparc_Mulh, emit_sparc_Mulh);
set_emitter(op_be_Copy, emit_be_Copy);
set_emitter(op_be_CopyKeep, emit_be_Copy);
set_emitter(op_be_Perm, emit_be_Perm);
set_emitter(op_be_MemPerm, emit_be_MemPerm);
/*
set_emitter(op_arm_B, emit_arm_B);
......@@ -629,7 +806,6 @@ static void sparc_register_emitters(void)
set_emitter(op_arm_fpaDbl2GP, emit_arm_fpaDbl2GP);
set_emitter(op_arm_LdTls, emit_arm_LdTls);
set_emitter(op_arm_SwitchJmp, emit_arm_SwitchJmp);
set_emitter(op_be_MemPerm, emit_be_MemPerm);
*/
/* no need to emit anything for the following nodes */
......
......@@ -45,6 +45,10 @@ 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_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_gen_routine(const sparc_code_gen_t *cg, ir_graph *irg);
......
......@@ -154,8 +154,6 @@ const sparc_attr_t *get_sparc_attr_const(const ir_node *node)
return (const sparc_attr_t *)get_irn_generic_attr_const(node);
}
sparc_load_store_attr_t *get_sparc_load_store_attr(ir_node *node)
{
assert(is_sparc_irn(node) && "need sparc node to get attributes");
......
......@@ -62,7 +62,6 @@ const sparc_cmp_attr_t *get_sparc_cmp_attr_const(const ir_node *node);
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);
/**
* Returns the argument register requirements of an sparc node.
*/
......
......@@ -40,6 +40,14 @@ struct sparc_attr_t
bool is_load_store;
};
/**
* attribute for FP immediate instruction
*/
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 */
};
/**
* attribute for save instruction
......
......@@ -221,6 +221,10 @@ $mode_fp = "mode_D";
C => "${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);",
O => "${arch}_emit_offset(node);",
);
......@@ -576,16 +580,24 @@ Xor => {
constructors => \%binop_operand_constructors,
},
UMul => {
Mul => {
state => "exc_pinned",
comment => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
reg_req => { in => [ "gp", "gp" ], out => [ "gp", "flags" ] },
outs => [ "low", "high" ],
constructors => \%binop_operand_constructors,
emit =>'. umul %S1, %R2I, %D1'
# emit =>'. mul %S1, %R2I, %D1'
},
UDiv => {
Mulh => {
state => "exc_pinned",
comment => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
outs => [ "low", "high" ],
constructors => \%binop_operand_constructors,
},
Div => {
irn_flags => "R",
state => "exc_pinned",
# mode => $mode_gp,
......@@ -593,7 +605,7 @@ UDiv => {
reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
outs => [ "res" ],
constructors => \%binop_operand_constructors,
emit =>'. udiv %S1, %R2I, %D1'
# emit =>'. div %S1, %R2I, %D1'
},
Minus => {
......@@ -613,6 +625,12 @@ Not => {
emit => '. xnor %S1, %%g0, %D1'
},
Nop => {
op_flags => "K",
reg_req => { in => [], out => [ "none" ] },
emit => '. nop',
},
#Mul_i => {
# irn_flags => "R",
# comment => "construct Mul: Mul(a, const) = Mul(const, a) = a * const",
......@@ -755,22 +773,71 @@ Not => {
# |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
#--------------------------------------------------------#
# commutative operations
fAdd => {
op_flags => "C",
irn_flags => "R",
comment => "construct FP Add: Add(a, b) = Add(b, a) = a + b",
reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
emit => '. fadd%FPM %S1, %S2, %D1'
},
fMul => {
op_flags => "C",
comment => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b",
reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
emit =>'. fmul%FPM %S1, %S2, %D1'
},
fsMuld => {
op_flags => "C",
comment => "construct FP single to double precision Mul: Mul(a, b) = Mul(b, a) = a * b",
reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
emit =>'. fsmuld %S1, %S2, %D1'
},
FpSToFpD => {
irn_flags => "R",
comment => "convert FP (single) to FP (double)",
reg_req => { in => [ "fp" ], out => [ "fp" ] },
emit =>'. FsTOd %S1, %D1'
},
FpDToFpS => {
irn_flags => "R",
comment => "convert FP (double) to FP (single)",
reg_req => { in => [ "fp" ], out => [ "fp" ] },
emit =>'. FdTOs %S1, %D1'
},
FpSToInt => {
irn_flags => "R",
comment => "convert integer to FP",
reg_req => { in => [ "fp" ], out => [ "gp" ] },
emit =>'. FiTOs %S1, %D1'
},
FpDToInt => {
irn_flags => "R",
comment => "convert integer to FP",
reg_req => { in => [ "fp" ], out => [ "gp" ] },
emit =>'. FiTOd %S1, %D1'
},
IntToFpS => {
irn_flags => "R",
comment => "convert FP (single) to integer",
reg_req => { in => [ "gp" ], out => [ "fp" ] },
emit =>'. FsTOi %S1, %D1'
},
IntToFpD => {
irn_flags => "R",
comment => "convert FP (double) to integer",
reg_req => { in => [ "gp" ], out => [ "fp" ] },
emit =>'. FdTOi %S1, %D1'
},
#fAdd => {
# op_flags => "C",
# irn_flags => "R",
# comment => "construct FP Add: Add(a, b) = Add(b, a) = a + b",
# reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
# emit => '. fadd %S1, %S2, %D1'
#},
#
#fMul => {
# op_flags => "C",
# comment => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b",
# reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
# emit =>'. fmul %S1, %S2, %D1'
#},
#
#fMax => {
# op_flags => "C",
......
......@@ -57,6 +57,9 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
static sparc_code_gen_t *env_cg;
static ir_node *gen_SymConst(ir_node *node);
static inline int mode_needs_gp_reg(ir_mode *mode)
{
return mode_is_int(mode) || mode_is_reference(mode);
......@@ -170,6 +173,15 @@ static ir_node *create_const_graph(ir_node *irn, ir_node *block)
return create_const_graph_value(dbgi, block, value);
}
/**
* create a DAG to load fp constant. sparc only supports loading from global memory
*/
static ir_node *create_fp_const_graph(ir_node *irn, ir_node *block)
{
(void) block;
panic("FP constants not implemented");
}
typedef enum {
MATCH_NONE = 0,
......@@ -178,6 +190,7 @@ typedef enum {
} match_flags_t;
typedef ir_node* (*new_binop_reg_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2);
typedef ir_node* (*new_binop_fp_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode);
typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, int simm13);
/**
......@@ -188,6 +201,8 @@ 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;
......@@ -236,6 +251,23 @@ static ir_node *gen_helper_binop(ir_node *node, match_flags_t flags,
return new_reg(dbgi, block, new_op1, new_op2);
}
/**
* helper function for FP binop operations
*/
static ir_node *gen_helper_binfpop(ir_node *node, new_binop_fp_func new_reg)
{
ir_node *block = be_transform_node(get_nodes_block(node));
ir_node *op1 = get_binop_left(node);
ir_node *new_op1;
ir_node *op2 = get_binop_right(node);
ir_node *new_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));
}
/**
* Creates an sparc Add.
*
......@@ -348,15 +380,16 @@ static ir_node *gen_Mul(ir_node *node) {
ir_node *mul;
ir_node *proj_res_low;
if (mode_is_float(mode))
panic("FP not supported yet");
if (mode_is_float(mode)) {
mul = gen_helper_binfpop(node, new_bd_sparc_fMul);
return mul;
}
assert(mode_is_data(mode));
mul = gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, new_bd_sparc_UMul_reg, new_bd_sparc_UMul_imm);
mul = gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, new_bd_sparc_Mul_reg, new_bd_sparc_Mul_imm);
arch_irn_add_flags(mul, arch_irn_flags_modify_flags);
proj_res_low = new_rd_Proj(dbgi, mul, mode_Iu, pn_sparc_UMul_low);
proj_res_low = new_rd_Proj(dbgi, mul, mode_Iu, pn_sparc_Mul_low);
return proj_res_low;
}
......@@ -378,11 +411,9 @@ static ir_node *gen_Mulh(ir_node *node) {
assert(mode_is_data(mode));
mul = gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, new_bd_sparc_UMul_reg, new_bd_sparc_UMul_imm);
arch_irn_add_flags(mul, arch_irn_flags_modify_flags);
proj_res_hi = new_rd_Proj(dbgi, mul, mode_Iu, pn_sparc_UMul_low); // TODO: this actually should be pn_sparc_UMul_high !
//arch_set_irn_register(proj_res_hi, &sparc_flags_regs[REG_Y]);
mul = gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, new_bd_sparc_Mulh_reg, new_bd_sparc_Mulh_imm);
//arch_irn_add_flags(mul, arch_irn_flags_modify_flags);
proj_res_hi = new_rd_Proj(dbgi, mul, mode_Iu, pn_sparc_Mulh_low);
return proj_res_hi;
}
......@@ -401,7 +432,7 @@ static ir_node *gen_Div(ir_node *node) {
panic("FP not supported yet");
//assert(mode_is_data(mode));
div = gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_UDiv_reg, new_bd_sparc_UDiv_imm);
div = gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_Div_reg, new_bd_sparc_Div_imm);
return div;
}
......@@ -481,6 +512,21 @@ static ir_node *gen_Or(ir_node *node)
return gen_helper_binop(node, MATCH_COMMUTATIVE, new_bd_sparc_Or_reg, new_bd_sparc_Or_imm);
}
static ir_node *gen_Xor(ir_node *node)
{
ir_mode *mode = get_irn_mode(node);
ir_node *block = be_transform_node(get_nodes_block(node));
dbg_info *dbgi = get_irn_dbg_info(node);
(void) block;
(void) dbgi;
if (mode_is_float(mode))
panic("FP not implemented yet");
return gen_helper_binop(node, MATCH_COMMUTATIVE, new_bd_sparc_Xor_reg, new_bd_sparc_Xor_imm);
}
static ir_node *gen_Shl(ir_node *node)
{
return gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_ShiftLL_reg, new_bd_sparc_ShiftLL_imm);
......@@ -521,7 +567,7 @@ static ir_node *gen_Minus(ir_node *node)
/**
* Transforms a Const node.
*
* @param node the ir Store node
* @param node the ir Const node
* @return The transformed sparc node.
*/
static ir_node *gen_Const(ir_node *node)