+ tarval *tv;
+ long val;
+ ir_mode *mode;
+
+ if(!is_Const(node))
+ return NULL;
+
+ mode = get_irn_mode(node);
+ if(!mode_needs_gp_reg(mode))
+ return NULL;
+
+ tv = get_Const_tarval(node);
+ if(tarval_is_long(tv)) {
+ val = get_tarval_long(tv);
+ } else {
+ ir_fprintf(stderr, "Optimisation Warning: tarval %+F is not a long?\n",
+ node);
+ return NULL;
+ }
+
+ if(val < -32768 || val > 32767)
+ return NULL;
+
+ return mips_create_Immediate(val);
+}
+
+static void create_binop_operands(ir_node **new_left, ir_node **new_right,
+ ir_node *left, ir_node *right,
+ int is_commutative)
+{
+ *new_right = try_create_Immediate(right);
+ if(*new_right != NULL) {
+ *new_left = be_transform_node(left);
+ return;
+ }
+ if(is_commutative) {
+ *new_right = try_create_Immediate(left);
+ if(*new_right != NULL) {
+ *new_left = be_transform_node(right);
+ return;
+ }
+ }
+
+ *new_left = be_transform_node(left);
+ *new_right = be_transform_node(right);
+}
+
+static ir_node *gen_binop(ir_node *node, ir_node *left, ir_node *right,
+ construct_binop_func func, int supports_immediate)
+{
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *block = be_transform_node(get_nodes_block(node));
+ ir_node *res;
+ ir_node *new_left, *new_right;
+
+ assert(mode_needs_gp_reg(get_irn_mode(node)));
+
+ if(supports_immediate) {
+ int is_commutative = is_op_commutative(get_irn_op(node));
+ create_binop_operands(&new_left, &new_right, left, right,
+ is_commutative);
+ } else {
+ new_left = be_transform_node(left);
+ new_right = be_transform_node(right);
+ }
+
+ res = func(dbgi, irg, block, new_left, new_right);
+
+ return res;
+}
+
+static ir_node *gen_Add(ir_node *node)
+{
+ /* TODO: match add(symconst, const) */
+ return gen_binop(node, get_Add_left(node), get_Add_right(node),
+ new_rd_mips_addu, 1);
+}
+
+static ir_node *gen_Sub(ir_node *node)
+{
+ return gen_binop(node, get_Sub_left(node), get_Sub_right(node),
+ new_rd_mips_addu, 0);
+}
+
+static ir_node *gen_And(ir_node *node)
+{
+ return gen_binop(node, get_Add_left(node), get_Add_right(node),
+ new_rd_mips_and, 1);
+}
+
+static ir_node *gen_Or(ir_node *node)
+{
+ return gen_binop(node, get_Add_left(node), get_Add_right(node),
+ new_rd_mips_or, 1);
+}
+
+static ir_node *gen_Eor(ir_node *node)
+{
+ return gen_binop(node, get_Add_left(node), get_Add_right(node),
+ new_rd_mips_xor, 1);
+}
+
+static ir_node *gen_Shl(ir_node *node)
+{
+ return gen_binop(node, get_Add_left(node), get_Add_right(node),
+ new_rd_mips_sll, 1);
+}
+
+static ir_node *gen_Shr(ir_node *node)
+{
+ return gen_binop(node, get_Add_left(node), get_Add_right(node),
+ new_rd_mips_srl, 1);
+}
+
+static ir_node *gen_Shrs(ir_node *node)
+{
+ return gen_binop(node, get_Add_left(node), get_Add_right(node),
+ new_rd_mips_sra, 1);
+}
+
+static ir_node *gen_Not(ir_node *node)
+{
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *block = be_transform_node(get_nodes_block(node));
+ ir_node *op = get_Not_op(node);
+ ir_node *new_op;
+ ir_node *res;
+ ir_node *one;
+
+ /* we can transform not->or to nor */
+ if(is_Or(op)) {
+ return gen_binop(op, get_Or_left(op), get_Or_right(op),
+ new_rd_mips_nor, 1);
+ }
+
+ /* construct (op < 1) */
+ one = mips_create_Immediate(1);
+ new_op = be_transform_node(op);
+ res = new_rd_mips_sltu(dbgi, irg, block, new_op, one);
+
+ return res;
+}
+
+static ir_node *gen_Minus(ir_node *node)
+{
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *block = be_transform_node(get_nodes_block(node));
+ ir_node *op = get_Minus_op(node);
+ ir_node *new_op = be_transform_node(op);
+ ir_node *res;
+ ir_node *zero;
+
+ /* construct (0 - op) */
+ zero = mips_create_zero();
+ res = new_rd_mips_subu(dbgi, irg, block, zero, new_op);
+
+ return res;
+}
+
+static ir_node *gen_Abs(ir_node *node)
+{
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *block = be_transform_node(get_nodes_block(node));
+ ir_node *op = get_Abs_op(node);
+ ir_node *new_op = be_transform_node(op);
+ ir_node *sra_const, *sra, *add, *xor;
+
+ /* TODO: support other bit sizes... */
+ assert(get_mode_size_bits(get_irn_mode(node)) == 32);
+ sra_const = mips_create_Immediate(31);
+ sra = new_rd_mips_sra(dbgi, irg, block, new_op, sra_const);
+ add = new_rd_mips_addu(dbgi, irg, block, new_op, sra);
+ xor = new_rd_mips_xor(dbgi, irg, block, sra, add);
+
+ return xor;
+}
+
+static ir_node* gen_Const(ir_node *node)
+{
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *block = be_transform_node(get_nodes_block(node));
+ tarval *tv = get_Const_tarval(node);
+ ir_node *upper_node;
+ ir_node *lower_node;
+ ir_node *or_const;