static const arch_register_t *fp_reg = &sparc_registers[REG_FRAME_POINTER];
static calling_convention_t *cconv = NULL;
static ir_mode *mode_gp;
+static ir_mode *mode_flags;
static ir_mode *mode_fp;
static ir_mode *mode_fp2;
//static ir_mode *mode_fp4;
panic("unsupported mode %+F for float op", mode);
}
+typedef ir_node* (*new_binopx_imm_func)(dbg_info *dbgi, ir_node *block,
+ ir_node *op1, ir_node *flags,
+ ir_entity *imm_entity, int32_t imm);
+
+typedef ir_node* (*new_binopx_reg_func)(dbg_info *dbgi, ir_node *block,
+ ir_node *op1, ir_node *op2,
+ ir_node *flags);
+
+static ir_node *gen_helper_binopx(ir_node *node, match_flags_t match_flags,
+ new_binopx_reg_func new_binopx_reg,
+ new_binopx_imm_func new_binopx_imm)
+{
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *block = be_transform_node(get_nodes_block(node));
+ ir_node *op1 = get_irn_n(node, 0);
+ ir_node *op2 = get_irn_n(node, 1);
+ ir_node *flags = get_irn_n(node, 2);
+ ir_node *new_flags = be_transform_node(flags);
+ ir_node *new_op1;
+ ir_node *new_op2;
+
+ /* only support for mode-neutral implemented so far */
+ assert(match_flags & MATCH_MODE_NEUTRAL);
+
+ if (is_imm_encodeable(op2)) {
+ ir_node *new_op1 = be_transform_node(op1);
+ int32_t immediate = get_tarval_long(get_Const_tarval(op2));
+ return new_binopx_imm(dbgi, block, new_op1, new_flags, NULL, immediate);
+ }
+ new_op2 = be_transform_node(op2);
+ if ((match_flags & MATCH_COMMUTATIVE) && is_imm_encodeable(op1)) {
+ int32_t immediate = get_tarval_long(get_Const_tarval(op1));
+ return new_binopx_imm(dbgi, block, new_op2, new_flags, NULL, immediate);
+ }
+ new_op1 = be_transform_node(op1);
+ return new_binopx_reg(dbgi, block, new_op1, new_op2, new_flags);
+
+}
+
static ir_node *get_g0(void)
{
return be_prolog_get_reg_value(abihelper, &sparc_registers[REG_G0]);
new_bd_sparc_Add_reg, new_bd_sparc_Add_imm);
}
+static ir_node *gen_AddCC_t(ir_node *node)
+{
+ return gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_MODE_NEUTRAL,
+ new_bd_sparc_AddCC_reg, new_bd_sparc_AddCC_imm);
+}
+
+static ir_node *gen_Proj_AddCC_t(ir_node *node)
+{
+ long pn = get_Proj_proj(node);
+ ir_node *pred = get_Proj_pred(node);
+ ir_node *new_pred = be_transform_node(pred);
+
+ switch (pn) {
+ case pn_sparc_AddCC_t_res:
+ return new_r_Proj(new_pred, mode_gp, pn_sparc_AddCC_res);
+ case pn_sparc_AddCC_t_flags:
+ return new_r_Proj(new_pred, mode_flags, pn_sparc_AddCC_flags);
+ default:
+ panic("Invalid AddCC_t proj found");
+ }
+}
+
+static ir_node *gen_AddX_t(ir_node *node)
+{
+ return gen_helper_binopx(node, MATCH_COMMUTATIVE | MATCH_MODE_NEUTRAL,
+ new_bd_sparc_AddX_reg, new_bd_sparc_AddX_imm);
+}
+
/**
* Creates an sparc Sub.
*
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);
+ return gen_helper_binop(node, MATCH_MODE_NEUTRAL,
+ new_bd_sparc_Sub_reg, new_bd_sparc_Sub_imm);
+}
+
+static ir_node *gen_SubCC_t(ir_node *node)
+{
+ return gen_helper_binop(node, MATCH_MODE_NEUTRAL,
+ new_bd_sparc_SubCC_reg, new_bd_sparc_SubCC_imm);
+}
+
+static ir_node *gen_Proj_SubCC_t(ir_node *node)
+{
+ long pn = get_Proj_proj(node);
+ ir_node *pred = get_Proj_pred(node);
+ ir_node *new_pred = be_transform_node(pred);
+
+ switch (pn) {
+ case pn_sparc_SubCC_t_res:
+ return new_r_Proj(new_pred, mode_gp, pn_sparc_SubCC_res);
+ case pn_sparc_SubCC_t_flags:
+ return new_r_Proj(new_pred, mode_flags, pn_sparc_SubCC_flags);
+ default:
+ panic("Invalid SubCC_t proj found");
+ }
+}
+
+static ir_node *gen_SubX_t(ir_node *node)
+{
+ return gen_helper_binopx(node, MATCH_MODE_NEUTRAL,
+ new_bd_sparc_SubX_reg, new_bd_sparc_SubX_imm);
}
static ir_node *create_ldf(dbg_info *dbgi, ir_node *block, ir_node *ptr,
return res;
}
-#if 0
-static ir_node *gen_Abs(ir_node *node)
-{
- ir_mode *const mode = get_irn_mode(node);
-
- if (mode_is_float(mode)) {
- return gen_helper_unfpop(node, mode, new_bd_sparc_fabs_s,
- new_bd_sparc_fabs_d, new_bd_sparc_fabs_q);
- } else {
- ir_node *const block = be_transform_node(get_nodes_block(node));
- dbg_info *const dbgi = get_irn_dbg_info(node);
- ir_node *const op = get_Abs_op(node);
- ir_node *const new_op = be_transform_node(op);
- ir_node *const sra = new_bd_sparc_Sra_imm(dbgi, block, new_op, NULL, 31);
- ir_node *const xor = new_bd_sparc_Xor_reg(dbgi, block, new_op, sra);
- ir_node *const sub = new_bd_sparc_Sub_reg(dbgi, block, xor, sra);
- return sub;
- }
-}
-#endif
-
/**
* Transforms a Not node.
*
{
ir_entity *entity = create_float_const_entity(tv);
ir_node *hi = new_bd_sparc_SetHi(dbgi, block, entity, 0);
- ir_node *mem = new_r_NoMem(current_ir_graph);
+ ir_node *mem = get_irg_no_mem(current_ir_graph);
ir_mode *mode = get_tarval_mode(tv);
ir_node *new_op
= create_ldf(dbgi, block, hi, mem, mode, entity, 0, false);
{
ir_node *hi = new_bd_sparc_SetHi(dbgi, block, entity, offset);
ir_node *low = new_bd_sparc_Or_imm(dbgi, block, hi, entity, offset);
+
+ if (get_entity_owner(entity) == get_tls_type())
+ panic("thread local storage not supported yet in sparc backend");
return low;
}
set_entity_visibility(entity, ir_visibility_private);
add_entity_linkage(entity, IR_LINKAGE_CONSTANT);
- /* TODO: this code does not construct code to check for access
- * out-of bounds of the jumptable yet. I think we should put this stuff
- * into the switch_lowering phase to get some additional optimisations
- * done. */
-
/* construct base address */
table_address = make_address(dbgi, block, entity, 0);
/* scale index */
index = new_bd_sparc_Sll_imm(dbgi, block, new_selector, NULL, 2);
/* load from jumptable */
load = new_bd_sparc_Ld_reg(dbgi, block, table_address, index,
- new_r_NoMem(current_ir_graph),
+ get_irg_no_mem(current_ir_graph),
mode_gp);
address = new_r_Proj(load, mode_gp, pn_sparc_Ld_res);
{
ir_graph *irg = get_irn_irg(block);
ir_node *sp = get_irg_frame(irg);
- ir_node *nomem = new_r_NoMem(irg);
+ ir_node *nomem = get_irg_no_mem(irg);
ir_node *stf = create_stf(dbgi, block, ftoi, sp, nomem, src_mode,
NULL, 0, true);
ir_node *ld = new_bd_sparc_Ld_imm(dbgi, block, sp, stf, mode_gp,
{
ir_graph *irg = get_irn_irg(block);
ir_node *sp = get_irg_frame(irg);
- ir_node *nomem = new_r_NoMem(irg);
+ ir_node *nomem = get_irg_no_mem(irg);
ir_node *st = new_bd_sparc_St_imm(dbgi, block, op, sp, nomem,
mode_gp, NULL, 0, true);
ir_node *ldf = new_bd_sparc_Ldf_s(dbgi, block, sp, st, mode_fp,
layout->arg_type = arg_type;
layout->initial_offset = 0;
layout->initial_bias = 0;
- layout->stack_dir = -1;
layout->sp_relative = cconv->omit_fp;
assert(N_FRAME_TYPES == 3);
ir_node *block = get_nodes_block(node);
ir_node *new_block = be_transform_node(block);
dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *mem;
ir_node *start;
- ir_node *sp;
size_t i;
/* stackpointer is important at function prolog */
}
start = be_prolog_create_start(abihelper, dbgi, new_block);
- mem = be_prolog_get_memory(abihelper);
- sp = be_prolog_get_reg_value(abihelper, sp_reg);
-
- if (!cconv->omit_fp) {
- ir_node *save = new_bd_sparc_Save_imm(NULL, block, sp, NULL,
- -SPARC_MIN_STACKSIZE);
- arch_irn_add_flags(save, arch_irn_flags_prolog);
- arch_set_irn_register(save, sp_reg);
- sp = save;
- keep_alive(save);
- }
-
- sp = be_new_IncSP(sp_reg, new_block, sp, BE_STACK_FRAME_SIZE_EXPAND, 0);
- arch_irn_add_flags(sp, arch_irn_flags_prolog);
- be_prolog_set_reg_value(abihelper, sp_reg, sp);
- be_prolog_set_memory(abihelper, mem);
-
return start;
}
{
/* get predecessor in stack_order list */
ir_node *stack_pred = be_get_stack_pred(abihelper, node);
- ir_node *stack_pred_transformed;
ir_node *stack;
if (stack_pred == NULL) {
return sp_proj;
}
- stack_pred_transformed = be_transform_node(stack_pred);
- stack = (ir_node*)pmap_get(node_to_stack, stack_pred);
+ be_transform_node(stack_pred);
+ stack = (ir_node*)pmap_get(node_to_stack, stack_pred);
if (stack == NULL) {
return get_stack_pointer_for(stack_pred);
}
}
}
- /* we need a restore instruction */
- if (!cconv->omit_fp) {
- ir_node *fp = be_prolog_get_reg_value(abihelper, fp_reg);
- ir_node *restore = new_bd_sparc_RestoreZero(NULL, block, fp);
- arch_irn_add_flags(restore, arch_irn_flags_epilog);
- arch_set_irn_register(restore, sp_reg);
- be_epilog_set_reg_value(abihelper, sp_reg, restore);
- } else {
- /* epilog code: an incsp */
- sp = be_epilog_get_reg_value(abihelper, sp_reg);
- sp = be_new_IncSP(sp_reg, new_block, sp,
- BE_STACK_FRAME_SIZE_SHRINK, 0);
- arch_irn_add_flags(sp, arch_irn_flags_epilog);
- be_epilog_set_reg_value(abihelper, sp_reg, sp);
- }
-
bereturn = be_epilog_create_return(abihelper, dbgi, new_block);
- arch_irn_add_flags(bereturn, arch_irn_flags_epilog);
-
return bereturn;
}
{
ir_graph *irg = current_ir_graph;
ir_node *sp = get_irg_frame(irg);
- ir_node *nomem = new_r_NoMem(irg);
+ ir_node *nomem = get_irg_no_mem(irg);
ir_node *st = new_bd_sparc_St_imm(dbgi, block, value0, sp, nomem,
mode_gp, NULL, 0, true);
ir_mode *mode;
{
ir_graph *irg = current_ir_graph;
ir_node *stack = get_irg_frame(irg);
- ir_node *nomem = new_r_NoMem(irg);
+ ir_node *nomem = get_irg_no_mem(irg);
ir_node *stf = create_stf(dbgi, block, node, stack, nomem, float_mode,
NULL, 0, true);
int bits = get_mode_size_bits(float_mode);
case pn_Start_M:
return be_prolog_get_memory(abihelper);
case pn_Start_T_args:
- /* we should never need this explicitely */
- return new_r_Bad(get_irn_irg(block));
+ return new_r_Bad(get_irn_irg(block), mode_T);
case pn_Start_P_frame_base:
return get_frame_base();
- case pn_Start_P_tls:
- return new_r_Bad(current_ir_graph);
- case pn_Start_max:
- break;
}
panic("Unexpected start proj: %ld\n", pn);
}
case pn_Call_X_regular:
case pn_Call_X_except:
case pn_Call_T_result:
- case pn_Call_P_value_res_base:
- case pn_Call_max:
break;
}
panic("Unexpected Call proj %ld\n", pn);
/* FALLTHROUGH */
}
default:
+ if (is_sparc_AddCC_t(pred)) {
+ return gen_Proj_AddCC_t(node);
+ } else if (is_sparc_SubCC_t(pred)) {
+ return gen_Proj_SubCC_t(node);
+ }
panic("code selection didn't expect Proj after %+F\n", pred);
}
}
be_set_transform_function(op_SymConst, gen_SymConst);
be_set_transform_function(op_Unknown, gen_Unknown);
+ be_set_transform_function(op_sparc_AddX_t, gen_AddX_t);
+ be_set_transform_function(op_sparc_AddCC_t,gen_AddCC_t);
be_set_transform_function(op_sparc_Save, be_duplicate_node);
+ be_set_transform_function(op_sparc_SubX_t, gen_SubX_t);
+ be_set_transform_function(op_sparc_SubCC_t,gen_SubCC_t);
}
/**
node_to_stack = pmap_create();
- mode_gp = mode_Iu;
- mode_fp = mode_F;
- mode_fp2 = mode_D;
+ mode_gp = mode_Iu;
+ mode_fp = mode_F;
+ mode_fp2 = mode_D;
+ mode_flags = mode_Bu;
//mode_fp4 = ?
abihelper = be_abihelper_prepare(irg);