#include "arm_nodes_attr.h"
#include "archop.h"
#include "arm_transform.h"
+#include "arm_optimize.h"
#include "arm_new_nodes.h"
#include "arm_map_regs.h"
return mode_is_int(mode) || mode_is_reference(mode);
}
-typedef struct vals_ {
- int ops;
- unsigned char values[4];
- unsigned char shifts[4];
-} vals;
-
-/** Execute ROL. */
-static unsigned do_rol(unsigned v, unsigned rol) {
- return (v << rol) | (v >> (32 - rol));
-}
-
-/**
- * construct 8bit values and rot amounts for a value
- */
-static void gen_vals_from_word(unsigned int value, vals *result)
-{
- int initial = 0;
-
- memset(result, 0, sizeof(*result));
-
- /* special case: we prefer shift amount 0 */
- if (value < 0x100) {
- result->values[0] = value;
- result->ops = 1;
- return;
- }
-
- while (value != 0) {
- if (value & 0xFF) {
- unsigned v = do_rol(value, 8) & 0xFFFFFF;
- int shf = 0;
- for (;;) {
- if ((v & 3) != 0)
- break;
- shf += 2;
- v >>= 2;
- }
- v &= 0xFF;
- shf = (initial + shf - 8) & 0x1F;
- result->values[result->ops] = v;
- result->shifts[result->ops] = shf;
- ++result->ops;
-
- value ^= do_rol(v, shf) >> initial;
- }
- else {
- value >>= 8;
- initial += 8;
- }
- }
-}
-
/**
* Creates a arm_Const node.
*/
-static ir_node *create_const_node(dbg_info *dbg, ir_node *block, long value) {
+static ir_node *create_mov_node(dbg_info *dbg, ir_node *block, long value) {
ir_mode *mode = mode_Iu;
ir_graph *irg = current_ir_graph;
ir_node *res;
/**
* Creates a arm_Const_Neg node.
*/
-static ir_node *create_const_neg_node(dbg_info *dbg, ir_node *block, long value) {
+static ir_node *create_mvn_node(dbg_info *dbg, ir_node *block, long value) {
ir_mode *mode = mode_Iu;
ir_graph *irg = current_ir_graph;
ir_node *res;
#define NEW_BINOP_NODE(opname, env, op1, op2) new_rd_arm_##opname(env->dbg, current_ir_graph, env->block, op1, op2, env->mode)
-/**
- * Encodes an immediate with shifter operand
- */
-static unsigned int arm_encode_imm_w_shift(unsigned int shift, unsigned int immediate) {
- return immediate | ((shift>>1)<<8);
-}
-
-/**
- * Decode an immediate with shifter operand
- */
-unsigned int arm_decode_imm_w_shift(long imm_value) {
- unsigned l = (unsigned)imm_value;
- unsigned rol = (l & ~0xFF) >> 7;
-
- return do_rol(l & 0xFF, rol);
-}
-
/**
* Creates a possible DAG for an constant.
*/
static ir_node *create_const_graph_value(dbg_info *dbg, ir_node *block, unsigned int value) {
ir_node *result;
- vals v, vn;
+ arm_vals v, vn;
int cnt;
ir_mode *mode = mode_Iu;
- gen_vals_from_word(value, &v);
- gen_vals_from_word(~value, &vn);
+ arm_gen_vals_from_word(value, &v);
+ arm_gen_vals_from_word(~value, &vn);
if (vn.ops < v.ops) {
/* remove bits */
- result = create_const_neg_node(dbg, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0]));
+ result = create_mvn_node(dbg, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0]));
for (cnt = 1; cnt < vn.ops; ++cnt) {
long value = arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]);
}
else {
/* add bits */
- result = create_const_node(dbg, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
+ result = create_mov_node(dbg, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
for (cnt = 1; cnt < v.ops; ++cnt) {
long value = arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]);
}
}
else if (USE_VFP(env_cg->isa)) {
- panic("VFP not supported yet\n");
+ panic("VFP not supported yet");
return NULL;
}
else {
- panic("Softfloat not supported yet\n");
+ panic("Softfloat not supported yet");
return NULL;
}
}
return gen_zero_extension(dbg, block, new_op, min_bits);
}
} else {
- panic("Cannot handle Conv %+F->%+F with %d->%d bits\n", src_mode, dst_mode,
+ panic("Cannot handle Conv %+F->%+F with %d->%d bits", src_mode, dst_mode,
src_bits, dst_bits);
return NULL;
}
return new_rd_arm_fpaAdf(dbg, irg, block, new_op1, new_op2, mode);
} else if (USE_VFP(env_cg->isa)) {
assert(mode != mode_E && "IEEE Extended FP not supported");
- panic("VFP not supported yet\n");
+ panic("VFP not supported yet");
return NULL;
}
else {
- panic("Softfloat not supported yet\n");
+ panic("Softfloat not supported yet");
return NULL;
}
} else {
}
else if (USE_VFP(env_cg->isa)) {
assert(mode != mode_E && "IEEE Extended FP not supported");
- panic("VFP not supported yet\n");
+ panic("VFP not supported yet");
return NULL;
}
else {
- panic("Softfloat not supported yet\n");
+ panic("Softfloat not supported yet");
return NULL;
}
}
return new_rd_arm_fpaDvf(dbg, current_ir_graph, block, new_op1, new_op2, mode);
} else if (USE_VFP(env_cg->isa)) {
assert(mode != mode_E && "IEEE Extended FP not supported");
- panic("VFP not supported yet\n");
+ panic("VFP not supported yet");
}
else {
- panic("Softfloat not supported yet\n");
+ panic("Softfloat not supported yet");
return NULL;
}
}
return new_rd_arm_fpaSuf(dbg, irg, block, new_op1, new_op2, mode);
} else if (USE_VFP(env_cg->isa)) {
assert(mode != mode_E && "IEEE Extended FP not supported");
- panic("VFP not supported yet\n");
+ panic("VFP not supported yet");
return NULL;
}
else {
- panic("Softfloat not supported yet\n");
+ panic("Softfloat not supported yet");
return NULL;
}
}
return new_rd_arm_Shrs(dbg, current_ir_graph, block, new_op1, new_op2, mode);
}
+/**
+ * Creates an ARM Ror.
+ *
+ * @return the created ARM Ror node
+ */
+static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2) {
+ ir_node *block = be_transform_node(get_nodes_block(node));
+ ir_node *new_op1 = be_transform_node(op1);
+ ir_node *new_op2 = be_transform_node(op2);
+ ir_mode *mode = mode_Iu;
+ dbg_info *dbg = get_irn_dbg_info(node);
+
+ if (is_arm_Mov_i(new_op2)) {
+ return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ROR, get_arm_imm_value(new_op2));
+ }
+ return new_rd_arm_Ror(dbg, current_ir_graph, block, new_op1, new_op2, mode);
+}
+
+/**
+ * Creates an ARM Rol.
+ *
+ * @return the created ARM Rol node
+ *
+ * Note: there is no Rol on arm, we have to use Ror
+ */
+static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2) {
+ ir_node *block = be_transform_node(get_nodes_block(node));
+ ir_node *new_op1 = be_transform_node(op1);
+ ir_mode *mode = mode_Iu;
+ dbg_info *dbg = get_irn_dbg_info(node);
+ ir_node *new_op2 = be_transform_node(op2);
+
+ new_op2 = new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op2, mode, 32);
+ return new_rd_arm_Ror(dbg, current_ir_graph, block, new_op1, new_op2, mode);
+}
+
+/**
+ * Creates an ARM ROR from a Firm Rotl.
+ *
+ * @return the created ARM Ror node
+ */
+static ir_node *gen_Rotl(ir_node *node) {
+ ir_node *rotate = NULL;
+ ir_node *op1 = get_Rotl_left(node);
+ ir_node *op2 = get_Rotl_right(node);
+
+ /* Firm has only RotL, so we are looking for a right (op2)
+ operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
+ that means we can create a RotR. */
+
+ if (is_Add(op2)) {
+ ir_node *right = get_Add_right(op2);
+ if (is_Const(right)) {
+ tarval *tv = get_Const_tarval(right);
+ ir_mode *mode = get_irn_mode(node);
+ long bits = get_mode_size_bits(mode);
+ ir_node *left = get_Add_left(op2);
+
+ if (is_Minus(left) &&
+ tarval_is_long(tv) &&
+ get_tarval_long(tv) == bits &&
+ bits == 32)
+ rotate = gen_Ror(node, op1, get_Minus_op(left));
+ }
+ } else if (is_Sub(op2)) {
+ ir_node *left = get_Sub_left(op2);
+ if (is_Const(left)) {
+ tarval *tv = get_Const_tarval(left);
+ ir_mode *mode = get_irn_mode(node);
+ long bits = get_mode_size_bits(mode);
+ ir_node *right = get_Sub_right(op2);
+
+ if (tarval_is_long(tv) &&
+ get_tarval_long(tv) == bits &&
+ bits == 32)
+ rotate = gen_Ror(node, op1, right);
+ }
+ } else if (is_Const(op2)) {
+ tarval *tv = get_Const_tarval(op2);
+ ir_mode *mode = get_irn_mode(node);
+ long bits = get_mode_size_bits(mode);
+
+ if (tarval_is_long(tv) && bits == 32) {
+ ir_node *block = be_transform_node(get_nodes_block(node));
+ ir_node *new_op1 = be_transform_node(op1);
+ ir_mode *mode = mode_Iu;
+ dbg_info *dbg = get_irn_dbg_info(node);
+
+ bits = (bits - get_tarval_long(tv)) & 31;
+ rotate = new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ROR, bits);
+ }
+ }
+
+ if (rotate == NULL) {
+ rotate = gen_Rol(node, op1, op2);
+ }
+
+ return rotate;
+}
+
/**
* Transforms a Not node.
*
return new_rd_arm_fpaAbs(dbg, current_ir_graph, block, new_op, mode);
else if (USE_VFP(env_cg->isa)) {
assert(mode != mode_E && "IEEE Extended FP not supported");
- panic("VFP not supported yet\n");
+ panic("VFP not supported yet");
}
else {
- panic("Softfloat not supported yet\n");
+ panic("Softfloat not supported yet");
}
}
assert(mode_is_data(mode));
return new_rd_arm_fpaMvf(dbg, current_ir_graph, block, op, mode);
else if (USE_VFP(env_cg->isa)) {
assert(mode != mode_E && "IEEE Extended FP not supported");
- panic("VFP not supported yet\n");
+ panic("VFP not supported yet");
}
else {
- panic("Softfloat not supported yet\n");
+ panic("Softfloat not supported yet");
}
}
assert(mode_is_data(mode));
new_load = new_rd_arm_fpaLdf(dbg, irg, block, new_ptr, new_mem, mode);
else if (USE_VFP(env_cg->isa)) {
assert(mode != mode_E && "IEEE Extended FP not supported");
- panic("VFP not supported yet\n");
+ panic("VFP not supported yet");
}
else {
- panic("Softfloat not supported yet\n");
+ panic("Softfloat not supported yet");
}
}
else {
new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem);
break;
default:
- panic("mode size not supported\n");
+ panic("mode size not supported");
}
} else {
/* zero extended loads */
new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem);
break;
default:
- panic("mode size not supported\n");
+ panic("mode size not supported");
}
}
}
new_store = new_rd_arm_fpaStf(dbg, irg, block, new_ptr, new_val, new_mem, mode);
else if (USE_VFP(env_cg->isa)) {
assert(mode != mode_E && "IEEE Extended FP not supported");
- panic("VFP not supported yet\n");
+ panic("VFP not supported yet");
} else {
- panic("Softfloat not supported yet\n");
+ panic("Softfloat not supported yet");
}
} else {
assert(mode_is_data(mode) && "unsupported mode for Store");
ir_node *op1 = get_Cmp_left(cmp_node);
ir_node *new_op1 = be_transform_node(op1);
ir_node *op2 = get_Cmp_right(cmp_node);
- ir_node *new_op2 = be_transform_node(op2);
if (mode_is_float(get_irn_mode(op1))) {
+ ir_node *new_op2 = be_transform_node(op2);
/* floating point compare */
pn_Cmp pnc = get_Proj_proj(selector);
}
/* Hmm: use need cmfe */
return new_rd_arm_fpaCmfeBra(dbg, irg, block, new_op1, new_op2, pnc);
+ } else if (is_Const(op2) && tarval_is_null(get_Const_tarval(op2))) {
+ /* compare with 0 */
+ return new_rd_arm_TstBra(dbg, irg, block, new_op1, new_op1, get_Proj_proj(selector));
} else {
/* integer compare */
+ ir_node *new_op2 = be_transform_node(op2);
return new_rd_arm_CmpBra(dbg, irg, block, new_op1, new_op2, get_Proj_proj(selector));
}
} else {
}
else if (USE_VFP(env_cg->isa)) {
assert(mode != mode_E && "IEEE Extended FP not supported");
- panic("VFP not supported yet\n");
+ panic("VFP not supported yet");
}
else {
- panic("Softfloat not supported yet\n");
+ panic("Softfloat not supported yet");
}
}
return create_const_graph(node, block);
return new_rd_arm_Add(dbg, current_ir_graph, block, new_op, cnst, mode, ARM_SHF_NONE, 0);
}
-#if 0
-/**
- * Transforms a FrameLoad into an ARM Load.
- */
-static ir_node *gen_FrameLoad(ir_node *irn) {
- ir_node *new_op = NULL;
- ir_node *noreg = ia32_new_NoReg_gp(env->cg);
- ir_node *mem = get_irn_n(irn, 0);
- ir_node *ptr = get_irn_n(irn, 1);
- ir_entity *ent = be_get_frame_entity(irn);
- ir_mode *mode = get_type_mode(get_entity_type(ent));
-
- if (mode_is_float(mode)) {
- if (USE_SSE2(env->cg))
- new_op = new_rd_ia32_fLoad(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
- else {
- env->cg->used_x87 = 1;
- new_op = new_rd_ia32_vfld(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
- }
- }
- else {
- new_op = new_rd_ia32_Load(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
- }
-
- set_ia32_frame_ent(new_op, ent);
- set_ia32_use_frame(new_op);
-
- set_ia32_am_support(new_op, ia32_am_Source);
- set_ia32_op_type(new_op, ia32_AddrModeS);
- set_ia32_am_flavour(new_op, ia32_B);
- set_ia32_ls_mode(new_op, mode);
-
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
-
- return new_op;
-}
-#endif
-
/**
* Transform a be_AddSP into an arm_AddSP. Eat up const sizes.
*/
ir_node *nomem = new_NoMem();
ir_node *new_op;
- /* ARM stack grows in reverse direction, make a SubSP */
- new_op = new_rd_arm_SubSP(dbgi, irg, block, new_sp, new_sz, nomem);
+ /* ARM stack grows in reverse direction, make a SubSPandCopy */
+ new_op = new_rd_arm_SubSPandCopy(dbgi, irg, block, new_sp, new_sz, nomem);
return new_op;
}
if (proj == pn_be_AddSP_sp) {
ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu,
- pn_arm_SubSP_stack);
+ pn_arm_SubSPandCopy_stack);
arch_set_irn_register(env_cg->arch_env, res, &arm_gp_regs[REG_SP]);
return res;
} else if(proj == pn_be_AddSP_res) {
return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu,
- pn_arm_SubSP_addr);
+ pn_arm_SubSPandCopy_addr);
} else if (proj == pn_be_AddSP_M) {
- return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_SubSP_M);
+ return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_SubSPandCopy_M);
}
assert(0);
*/
static ir_node *gen_Proj_Cmp(ir_node *node) {
(void) node;
- panic("Psi NYI\n");
+ panic("Mux NYI");
}
/* we exchange the ProjX with a jump */
block = be_transform_node(block);
jump = new_rd_Jmp(dbgi, irg, block);
- ir_fprintf(stderr, "created jump: %+F\n", jump);
return jump;
}
if (node == get_irg_anchor(irg, anchor_tls)) {
* the BAD transformer.
*/
static ir_node *bad_transform(ir_node *irn) {
- panic("ARM backend: Not implemented: %+F\n", irn);
+ panic("ARM backend: Not implemented: %+F", irn);
return irn;
}
GEN(Shl);
GEN(Shr);
GEN(Shrs);
- BAD(Rot); /* unsupported yet */
+ GEN(Rotl);
GEN(Quot);
BAD(ASM); /* unsupported yet */
GEN(CopyB);
- BAD(Mux);
- BAD(Psi); /* unsupported yet */
+ BAD(Mux); /* unsupported yet */
GEN(Proj);
GEN(Phi);