#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;)
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);
}
}
}
+/**
+ * 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.
*/
}
/**
- * 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)
{
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
}
/**
- * TODO: check if this is correct
+ * Emit code for Perm node
*/
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.
*/
be_emit_finish_line_gas(irn);
}
-
/**
* Emits code for FrameAddr fix
*/
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);
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 */
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);
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");
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.
*/
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
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);",
);
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,
reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
outs => [ "res" ],
constructors => \%binop_operand_constructors,
- emit =>'. udiv %S1, %R2I, %D1'
+# emit =>'. div %S1, %R2I, %D1'
},
Minus => {
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",
# |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
#--------------------------------------------------------#
-# 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",
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);
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,
} 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);
/**
{
long val;
+ //assert(mode_is_float_vector(get_irn_mode(node)));
+
if (!is_Const(node))
return false;
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.
*
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;
}
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;
}
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;
}
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);
/**
* 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)
(void) dbg;
if (mode_is_float(mode)) {
- panic("FP not supported yet");
+ return create_fp_const_graph(node, block);
}
+
return create_const_graph(node, block);
}
ir_mode *dst_mode = get_irn_mode(node);
dbg_info *dbg = get_irn_dbg_info(node);
+ int src_bits = get_mode_size_bits(src_mode);
+ int dst_bits = get_mode_size_bits(dst_mode);
+
if (src_mode == dst_mode)
return new_op;
if (mode_is_float(src_mode) || mode_is_float(dst_mode)) {
- panic("FP not implemented");
+ assert((src_bits <= 64 && dst_bits <= 64) && "quad FP not implemented");
+
+ if (mode_is_float(src_mode)) {
+ if (mode_is_float(dst_mode)) {
+ // float -> float conv
+ if (src_bits > dst_bits) {
+ return new_bd_sparc_FpDToFpS(dbg, block, new_op, dst_mode);
+ } else {
+ return new_bd_sparc_FpSToFpD(dbg, block, new_op, dst_mode);
+ }
+ } else {
+ // float -> int conv
+ switch (dst_bits) {
+ case 32:
+ return new_bd_sparc_FpSToInt(dbg, block, new_op, dst_mode);
+ case 64:
+ return new_bd_sparc_FpDToInt(dbg, block, new_op, dst_mode);
+ default:
+ panic("quad FP not implemented");
+ }
+ }
+ } else {
+ // int -> float conv
+ switch (dst_bits) {
+ case 32:
+ return new_bd_sparc_IntToFpS(dbg, block, new_op, src_mode);
+ case 64:
+ return new_bd_sparc_IntToFpD(dbg, block, new_op, src_mode);
+ default:
+ panic("quad FP not implemented");
+ }
+ }
} else { /* complete in gp registers */
- int src_bits = get_mode_size_bits(src_mode);
- int dst_bits = get_mode_size_bits(dst_mode);
int min_bits;
ir_mode *min_mode;
panic("not implemented");
}
-
+/**
+ * transform Projs from a Div
+ */
static ir_node *gen_Proj_Div(ir_node *node)
{
ir_node *pred = get_Proj_pred(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);
+ if (is_sparc_Div(new_pred)) {
+ return new_rd_Proj(dbgi, new_pred, mode, pn_sparc_Div_res);
}
break;
default:
}
/**
- * configure transformation callbacks
+ * the BAD transformer.
*/
-void sparc_register_transformers(void)
+static ir_node *bad_transform(ir_node *irn)
{
- be_start_transform_setup();
-
- be_set_transform_function(op_Add, gen_Add);
- be_set_transform_function(op_Store, gen_Store);
- be_set_transform_function(op_Const, gen_Const);
- be_set_transform_function(op_Load, gen_Load);
- be_set_transform_function(op_Sub, gen_Sub);
-
- be_set_transform_function(op_be_AddSP, gen_be_AddSP);
- be_set_transform_function(op_be_SubSP, gen_be_SubSP);
- be_set_transform_function(op_be_Copy, gen_be_Copy);
- be_set_transform_function(op_be_Call, gen_be_Call);
- be_set_transform_function(op_be_FrameAddr, gen_be_FrameAddr);
-
- be_set_transform_function(op_Cond, gen_Cond);
- be_set_transform_function(op_Cmp, gen_Cmp);
-
- be_set_transform_function(op_SymConst, gen_SymConst);
-
- be_set_transform_function(op_Phi, gen_Phi);
- be_set_transform_function(op_Proj, gen_Proj);
-
- be_set_transform_function(op_Conv, gen_Conv);
- be_set_transform_function(op_Jmp, gen_Jmp);
-
- be_set_transform_function(op_Mul, gen_Mul);
- be_set_transform_function(op_Mulh, gen_Mulh);
- be_set_transform_function(op_Div, gen_Div);
- be_set_transform_function(op_Abs, gen_Abs);
- be_set_transform_function(op_Shl, gen_Shl);
- be_set_transform_function(op_Shr, gen_Shr);
- be_set_transform_function(op_Shrs, gen_Shra);
+ panic("SPARC backend: Not implemented: %+F", irn);
+}
- be_set_transform_function(op_Minus, gen_Minus);
- be_set_transform_function(op_Not, gen_Not);
- be_set_transform_function(op_And, gen_And);
- be_set_transform_function(op_Or, gen_Or);
+/**
+ * Set a node emitter. Make it a bit more type safe.
+ */
+static void set_transformer(ir_op *op, be_transform_func sparc_transform_func)
+{
+ op->ops.generic = (op_func)sparc_transform_func;
+}
- be_set_transform_function(op_Unknown, gen_Unknown);
+/**
+ * configure transformation callbacks
+ */
+void sparc_register_transformers(void)
+{
+ clear_irp_opcodes_generic_func();
+ set_transformer(op_Add, gen_Add);
+ set_transformer(op_Store, gen_Store);
+ set_transformer(op_Const, gen_Const);
+ set_transformer(op_Load, gen_Load);
+ set_transformer(op_Sub, gen_Sub);
+
+ set_transformer(op_be_AddSP, gen_be_AddSP);
+ set_transformer(op_be_SubSP, gen_be_SubSP);
+ set_transformer(op_be_Copy, gen_be_Copy);
+ set_transformer(op_be_Call, gen_be_Call);
+ set_transformer(op_be_FrameAddr, gen_be_FrameAddr);
+
+ set_transformer(op_Cond, gen_Cond);
+ set_transformer(op_Cmp, gen_Cmp);
+
+ set_transformer(op_SymConst, gen_SymConst);
+
+ set_transformer(op_Phi, gen_Phi);
+ set_transformer(op_Proj, gen_Proj);
+
+ set_transformer(op_Conv, gen_Conv);
+ 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_Eor, gen_Xor);
+
+ set_transformer(op_Unknown, gen_Unknown);
/* node list */
/*
- be_set_transform_function(op_CopyB, gen_CopyB);
- be_set_transform_function(op_Eor, gen_Eor);
- be_set_transform_function(op_Quot, gen_Quot);
- be_set_transform_function(op_Rotl, gen_Rotl);
+ set_transformer(op_CopyB, gen_CopyB);
+ set_transformer(op_Quot, gen_Quot);
+ set_transformer(op_Rotl, gen_Rotl);
*/
+
+ set_transformer(op_ASM, bad_transform);
+ set_transformer(op_Builtin, bad_transform);
+ set_transformer(op_CallBegin, bad_transform);
+ set_transformer(op_Cast, bad_transform);
+ set_transformer(op_Confirm, bad_transform);
+ set_transformer(op_DivMod, bad_transform);
+ set_transformer(op_EndExcept, bad_transform);
+ set_transformer(op_EndReg, bad_transform);
+ set_transformer(op_Filter, bad_transform);
+ set_transformer(op_Free, bad_transform);
+ set_transformer(op_Id, bad_transform);
+ set_transformer(op_InstOf, bad_transform);
+
+ set_transformer(op_Mux, bad_transform);
+ set_transformer(op_Raise, bad_transform);
+ set_transformer(op_Sel, bad_transform);
+ set_transformer(op_Tuple, bad_transform);
+}
+
+
+/**
+ * Pre-transform all unknown nodes.
+ */
+static void sparc_pretransform_node(void)
+{
+ sparc_code_gen_t *cg = env_cg;
+ (void) cg;
+ //cg->unknown_gp = be_pre_transform_node(cg->unknown_gp);
+ //cg->unknown_fpa = be_pre_transform_node(cg->unknown_fpa);
}
/**
{
sparc_register_transformers();
env_cg = cg;
- be_transform_graph(cg->irg, NULL);
+ be_transform_graph(cg->irg, sparc_pretransform_node);
}
void sparc_init_transform(void)