Commit 36a16c27 authored by Hannes Rapp's avatar Hannes Rapp
Browse files

- restliche ops implementiert: div, mod, and, or etc

- optest.c kompiliert

[r27627]
parent 0ab34ea9
......@@ -345,6 +345,79 @@ static sparc_isa_t sparc_isa_template = {
NULL /* current code generator */
};
static void sparc_handle_intrinsics(void)
{
ir_type *tp, *int_tp, *uint_tp;
i_record records[8];
int n_records = 0;
runtime_rt rt_iMod, rt_uMod;
#define ID(x) new_id_from_chars(x, sizeof(x)-1)
int_tp = new_type_primitive(mode_Is);
uint_tp = new_type_primitive(mode_Iu);
/* SPARC has no signed mod instruction ... */
{
i_instr_record *map_Mod = &records[n_records++].i_instr;
tp = new_type_method(2, 1);
set_method_param_type(tp, 0, int_tp);
set_method_param_type(tp, 1, int_tp);
set_method_res_type(tp, 0, int_tp);
rt_iMod.ent = new_entity(get_glob_type(), ID(".rem"), tp);
set_entity_ld_ident(rt_iMod.ent, ID(".rem"));
rt_iMod.mode = mode_T;
rt_iMod.res_mode = mode_Is;
rt_iMod.mem_proj_nr = pn_Mod_M;
rt_iMod.regular_proj_nr = pn_Mod_X_regular;
rt_iMod.exc_proj_nr = pn_Mod_X_except;
rt_iMod.exc_mem_proj_nr = pn_Mod_M;
rt_iMod.res_proj_nr = pn_Mod_res;
set_entity_visibility(rt_iMod.ent, ir_visibility_external);
map_Mod->kind = INTRINSIC_INSTR;
map_Mod->op = op_Mod;
map_Mod->i_mapper = (i_mapper_func)i_mapper_RuntimeCall;
map_Mod->ctx = &rt_iMod;
}
/* ... nor an unsigned mod. */
{
i_instr_record *map_Mod = &records[n_records++].i_instr;
tp = new_type_method(2, 1);
set_method_param_type(tp, 0, uint_tp);
set_method_param_type(tp, 1, uint_tp);
set_method_res_type(tp, 0, uint_tp);
rt_uMod.ent = new_entity(get_glob_type(), ID(".urem"), tp);
set_entity_ld_ident(rt_uMod.ent, ID(".urem"));
rt_uMod.mode = mode_T;
rt_uMod.res_mode = mode_Iu;
rt_uMod.mem_proj_nr = pn_Mod_M;
rt_uMod.regular_proj_nr = pn_Mod_X_regular;
rt_uMod.exc_proj_nr = pn_Mod_X_except;
rt_uMod.exc_mem_proj_nr = pn_Mod_M;
rt_uMod.res_proj_nr = pn_Mod_res;
set_entity_visibility(rt_uMod.ent, ir_visibility_external);
map_Mod->kind = INTRINSIC_INSTR;
map_Mod->op = op_Mod;
map_Mod->i_mapper = (i_mapper_func)i_mapper_RuntimeCall;
map_Mod->ctx = &rt_uMod;
}
if (n_records > 0)
lower_intrinsics(records, n_records, /*part_block_used=*/0);
}
/**
* Initializes the backend ISA
*/
......@@ -364,6 +437,7 @@ static arch_env_t *sparc_init(FILE *outfile)
sparc_register_init();
sparc_create_opcodes(&sparc_irn_ops);
sparc_handle_intrinsics();
return &isa->arch_env;
}
......
......@@ -34,7 +34,7 @@
// sparc ABI requires a min stacksize to
// save registers in case of a trap etc.
// by now we assume only non-leaf procedures: 92 + 4 (padding)
#define SPARC_MIN_STACKSIZE 96
#define SPARC_MIN_STACKSIZE 112
typedef struct sparc_transform_env_t sparc_transform_env_t;
typedef struct _sparc_isa_t sparc_isa_t;
......
......@@ -320,6 +320,7 @@ static void emit_sparc_LoImm(const ir_node *irn)
static void emit_be_Return(const ir_node *irn)
{
be_emit_cstring("\tret");
//be_emit_cstring("\tjmp %i7+8");
be_emit_finish_line_gas(irn);
be_emit_cstring("\trestore");
be_emit_finish_line_gas(irn);
......@@ -335,6 +336,7 @@ static void emit_be_Call(const ir_node *irn)
if (entity != NULL) {
be_emit_cstring("\tcall ");
sparc_emit_entity(entity);
be_emit_cstring(", 0");
be_emit_finish_line_gas(irn);
be_emit_cstring("\tnop");
be_emit_pad_comment();
......
......@@ -79,7 +79,7 @@ static int sparc_dump_node(ir_node *n, FILE *F, dump_reason_t reason)
/* TODO: dump some attributes which should show up */
/* in node name in dump (e.g. consts or the like) */
fputs("\n", F);
//fputs("\n", F);
if (is_sparc_FrameAddr(n)) {
const sparc_symconst_attr_t *attr = get_sparc_symconst_attr_const(n);
......
......@@ -536,7 +536,7 @@ ShiftLR => {
comment => "construct shift logical right",
mode => $mode_gp,
reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
emit => '. slr %S1, %R2I, %D1',
emit => '. srl %S1, %R2I, %D1',
constructors => \%binop_operand_constructors,
},
......@@ -587,7 +587,8 @@ UMul => {
UDiv => {
irn_flags => "R",
mode => $mode_gp,
state => "exc_pinned",
# mode => $mode_gp,
comment => "construct Div: Div(a, b) = a / b",
reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
outs => [ "res" ],
......
......@@ -62,6 +62,69 @@ static inline int mode_needs_gp_reg(ir_mode *mode)
return mode_is_int(mode) || mode_is_reference(mode);
}
/**
* Create an And that will zero out upper bits.
*
* @param dbgi debug info
* @param block the basic block
* @param op the original node
* @param src_bits number of lower bits that will remain
*/
static ir_node *gen_zero_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
int src_bits)
{
if (src_bits == 8) {
return new_bd_sparc_And_imm(dbgi, block, op, 0xFF);
} else if (src_bits == 16) {
ir_node *lshift = new_bd_sparc_ShiftLL_imm(dbgi, block, op, 16);
ir_node *rshift = new_bd_sparc_ShiftLR_imm(dbgi, block, lshift, 16);
return rshift;
} else {
panic("zero extension only supported for 8 and 16 bits");
}
}
/**
* Generate code for a sign extension.
*/
static ir_node *gen_sign_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
int src_bits)
{
int shift_width = 32 - src_bits;
ir_node *lshift_node = new_bd_sparc_ShiftLL_imm(dbgi, block, op, shift_width);
ir_node *rshift_node = new_bd_sparc_ShiftRA_imm(dbgi, block, lshift_node, shift_width);
return rshift_node;
}
/**
* returns true if it is assured, that the upper bits of a node are "clean"
* which means for a 16 or 8 bit value, that the upper bits in the register
* are 0 for unsigned and a copy of the last significant bit for signed
* numbers.
*/
static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode)
{
(void) transformed_node;
(void) mode;
/* TODO */
return false;
}
static ir_node *gen_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
ir_mode *orig_mode)
{
int bits = get_mode_size_bits(orig_mode);
if (bits == 32)
return op;
if (mode_is_signed(orig_mode)) {
return gen_sign_extension(dbgi, block, op, bits);
} else {
return gen_zero_extension(dbgi, block, op, bits);
}
}
/**
* Creates a possible DAG for a constant.
*/
......@@ -274,11 +337,11 @@ static ir_node *gen_Store(ir_node *node)
/**
* Creates an sparc Mul.
* returns the lower 32bits of the 64bit multiply result
*
* @return the created sparc Mul node
*/
static ir_node *gen_Mul(ir_node *node)
{
static ir_node *gen_Mul(ir_node *node) {
ir_mode *mode = get_irn_mode(node);
dbg_info *dbgi = get_irn_dbg_info(node);
......@@ -291,11 +354,36 @@ static ir_node *gen_Mul(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_low = new_rd_Proj(dbgi, mul, mode_Iu, pn_sparc_UMul_low);
return proj_res_low;
}
/**
* Creates an sparc Mulh.
* Mulh returns the upper 32bits of a mul instruction
*
* @return the created sparc Mulh node
*/
static ir_node *gen_Mulh(ir_node *node) {
ir_mode *mode = get_irn_mode(node);
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *mul;
ir_node *proj_res_hi;
if (mode_is_float(mode))
panic("FP not supported yet");
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);
//return gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, new_bd_sparc_Mul_reg, new_bd_sparc_Mul_imm);
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]);
return proj_res_hi;
}
/**
......@@ -303,24 +391,21 @@ static ir_node *gen_Mul(ir_node *node)
*
* @return the created sparc Div node
*/
static ir_node *gen_Div(ir_node *node)
{
static ir_node *gen_Div(ir_node *node) {
ir_mode *mode = get_irn_mode(node);
//dbg_info *dbgi = get_irn_dbg_info(node);
//ir_node *proj_res_low;
ir_node *div;
if (mode_is_float(mode))
panic("FP not supported yet");
return gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_UDiv_reg, new_bd_sparc_UDiv_imm);
//proj_res = new_rd_Proj(dbgi, mul, mode_Iu, pn_sparc_UDiv_res);
//return proj_res;
//return gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, new_bd_sparc_Mul_reg, new_bd_sparc_Mul_imm);
//assert(mode_is_data(mode));
div = gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_UDiv_reg, new_bd_sparc_UDiv_imm);
return div;
}
/**
* transform abs node:
* mov a, b
......@@ -330,8 +415,7 @@ static ir_node *gen_Div(ir_node *node)
*
* @return
*/
static ir_node *gen_Abs(ir_node *node)
{
static ir_node *gen_Abs(ir_node *node) {
ir_node *block = be_transform_node(get_nodes_block(node));
ir_mode *mode = get_irn_mode(node);
dbg_info *dbgi = get_irn_dbg_info(node);
......@@ -367,6 +451,36 @@ static ir_node *gen_Not(ir_node *node)
return new_bd_sparc_Not(dbgi, block, new_op);
}
static ir_node *gen_And(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_And_reg, new_bd_sparc_And_imm);
}
static ir_node *gen_Or(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_Or_reg, new_bd_sparc_Or_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);
......@@ -377,6 +491,11 @@ static ir_node *gen_Shr(ir_node *node)
return gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_ShiftLR_reg, new_bd_sparc_ShiftLR_imm);
}
static ir_node *gen_Shra(ir_node *node)
{
return gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_ShiftRA_reg, new_bd_sparc_ShiftRA_imm);
}
/****** TRANSFORM GENERAL BACKEND NODES ********/
/**
......@@ -593,9 +712,11 @@ static ir_node *gen_Cmp(ir_node *node)
panic("FloatCmp not implemented");
}
/*
if (get_mode_size_bits(cmp_mode) != 32) {
panic("CmpMode != 32bit not supported yet");
}
*/
assert(get_irn_mode(op2) == cmp_mode);
is_unsigned = !mode_is_signed(cmp_mode);
......@@ -617,9 +738,9 @@ static ir_node *gen_Cmp(ir_node *node)
/* integer compare */
new_op1 = be_transform_node(op1);
//new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode);
new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode);
new_op2 = be_transform_node(op2);
//new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode);
new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode);
return new_bd_sparc_Cmp_reg(dbgi, block, new_op1, new_op2, false, is_unsigned);
}
......@@ -638,54 +759,6 @@ static ir_node *gen_SymConst(ir_node *node)
return new_node;
}
/**
* Create an And that will zero out upper bits.
*
* @param dbgi debug info
* @param block the basic block
* @param op the original node
* @param src_bits number of lower bits that will remain
*/
static ir_node *gen_zero_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
int src_bits)
{
if (src_bits == 8) {
return new_bd_sparc_And_imm(dbgi, block, op, 0xFF);
} else if (src_bits == 16) {
ir_node *lshift = new_bd_sparc_ShiftLL_imm(dbgi, block, op, 16);
ir_node *rshift = new_bd_sparc_ShiftLR_imm(dbgi, block, lshift, 16);
return rshift;
} else {
panic("zero extension only supported for 8 and 16 bits");
}
}
/**
* Generate code for a sign extension.
*/
static ir_node *gen_sign_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
int src_bits)
{
int shift_width = 32 - src_bits;
ir_node *lshift_node = new_bd_sparc_ShiftLL_imm(dbgi, block, op, shift_width);
ir_node *rshift_node = new_bd_sparc_ShiftRA_imm(dbgi, block, lshift_node, shift_width);
return rshift_node;
}
/**
* returns true if it is assured, that the upper bits of a node are "clean"
* which means for a 16 or 8 bit value, that the upper bits in the register
* are 0 for unsigned and a copy of the last significant bit for signed
* numbers.
*/
static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode)
{
(void) transformed_node;
(void) mode;
/* TODO */
return false;
}
/**
* Transforms a Conv node.
*
......@@ -830,13 +903,11 @@ static ir_node *gen_Proj_be_AddSP(ir_node *node)
long proj = get_Proj_proj(node);
if (proj == pn_be_AddSP_sp) {
// TODO: check for correct pn_sparc_* flags
ir_node *res = new_rd_Proj(dbgi, new_pred, mode_Iu,
pn_sparc_SubSP_stack);
arch_set_irn_register(res, &sparc_gp_regs[REG_SP]);
return res;
} else if (proj == pn_be_AddSP_res) {
// TODO: check for correct pn_sparc_* flags
return new_rd_Proj(dbgi, new_pred, mode_Iu, pn_sparc_SubSP_stack);
} else if (proj == pn_be_AddSP_M) {
return new_rd_Proj(dbgi, new_pred, mode_M, pn_sparc_SubSP_M);
......@@ -877,6 +948,27 @@ static ir_node *gen_Proj_Cmp(ir_node *node)
}
static ir_node *gen_Proj_Div(ir_node *node)
{
ir_node *pred = get_Proj_pred(node);
ir_node *new_pred = be_transform_node(pred);
dbg_info *dbgi = get_irn_dbg_info(node);
ir_mode *mode = get_irn_mode(node);
long proj = get_Proj_proj(node);
switch (proj) {
case pn_Div_res:
if (is_sparc_UDiv(new_pred)) {
return new_rd_Proj(dbgi, new_pred, mode, pn_sparc_UDiv_res);
}
break;
default:
break;
}
panic("Unsupported Proj from Div");
}
/**
* Transform a Proj node.
*/
......@@ -907,6 +999,8 @@ static ir_node *gen_Proj(ir_node *node)
} else if (is_Cmp(pred)) {
//panic("gen_Proj not implemented for Cmp");
return gen_Proj_Cmp(node);
} else if (is_Div(pred)) {
return gen_Proj_Div(node);
} else if (is_Start(pred)) {
/*
if (proj == pn_Start_X_initial_exec) {
......@@ -995,26 +1089,27 @@ void sparc_register_transformers(void)
set_transformer(op_Jmp, gen_Jmp);
set_transformer(op_Mul, gen_Mul);
set_transformer(op_Mulh, gen_Mulh);
set_transformer(op_Div, gen_Div);
set_transformer(op_Abs, gen_Abs);
set_transformer(op_Shl, gen_Shl);
set_transformer(op_Shr, gen_Shr);
set_transformer(op_Shrs, gen_Shra);
set_transformer(op_Minus, gen_Minus);
set_transformer(op_Not, gen_Not);
set_transformer(op_And, gen_And);
set_transformer(op_Or, gen_Or);
set_transformer(op_Unknown, gen_Unknown);
/* node list */
/*
set_transformer(op_And, gen_And);
set_transformer(op_CopyB, gen_CopyB);
set_transformer(op_Eor, gen_Eor);
set_transformer(op_Mul, gen_Mul);
set_transformer(op_Or, gen_Or);
set_transformer(op_Quot, gen_Quot);
set_transformer(op_Rotl, gen_Rotl);
set_transformer(op_Shrs, gen_Shrs);
*/
set_transformer(op_ASM, bad_transform);
......@@ -1029,7 +1124,7 @@ void sparc_register_transformers(void)
set_transformer(op_Free, bad_transform);
set_transformer(op_Id, bad_transform);
set_transformer(op_InstOf, bad_transform);
set_transformer(op_Mulh, bad_transform);
set_transformer(op_Mux, bad_transform);
set_transformer(op_Raise, bad_transform);
set_transformer(op_Sel, bad_transform);
......
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