/*
- * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
+ * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
#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"
****************************************************************************************************/
static INLINE int mode_needs_gp_reg(ir_mode *mode) {
- return mode_is_int(mode) || mode_is_character(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;
- }
- }
+ return mode_is_int(mode) || mode_is_reference(mode);
}
/**
* Creates a arm_Const node.
*/
-static ir_node *create_const_node(be_abi_irg_t *abi, 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;
- tarval *tv = new_tarval_from_long(value, mode);
+ ir_graph *irg = current_ir_graph;
ir_node *res;
if (mode_needs_gp_reg(mode))
mode = mode_Iu;
- res = new_rd_arm_Mov_i(dbg, current_ir_graph, block, mode, tv);
- /* ensure the const is schedules AFTER the barrier */
- add_irn_dep(res, be_abi_get_start_barrier(abi));
+ res = new_rd_arm_Mov_i(dbg, irg, block, mode, value);
+ /* ensure the const is scheduled AFTER the stack frame */
+ add_irn_dep(res, get_irg_frame(irg));
return res;
}
/**
* Creates a arm_Const_Neg node.
*/
-static ir_node *create_const_neg_node(be_abi_irg_t *abi, 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;
- tarval *tv = new_tarval_from_long(value, mode);
+ ir_graph *irg = current_ir_graph;
ir_node *res;
if (mode_needs_gp_reg(mode))
mode = mode_Iu;
- res = new_rd_arm_Mvn_i(dbg, current_ir_graph, block, mode, tv);
- add_irn_dep(res, be_abi_get_start_barrier(abi));
- /* ensure the const is schedules AFTER the barrier */
+ res = new_rd_arm_Mvn_i(dbg, irg, block, mode, value);
+ /* ensure the const is scheduled AFTER the stack frame */
+ add_irn_dep(res, get_irg_frame(irg));
return 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(tarval *tv) {
- unsigned l = get_tarval_long(tv);
- 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(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, unsigned int value) {
+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(abi, 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) {
- tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]), mode);
- ir_node *bic_i_node = new_rd_arm_Bic_i(dbg, current_ir_graph, block, result, mode, tv);
+ long value = arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]);
+ ir_node *bic_i_node = new_rd_arm_Bic_i(dbg, current_ir_graph, block, result, mode, value);
result = bic_i_node;
}
}
else {
/* add bits */
- result = create_const_node(abi, 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) {
- tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]), mode);
- ir_node *orr_i_node = new_rd_arm_Or_i(dbg, current_ir_graph, block, result, mode, tv);
+ long value = arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]);
+ ir_node *orr_i_node = new_rd_arm_Or_i(dbg, current_ir_graph, block, result, mode, value);
result = orr_i_node;
}
}
*
* @param irn a Firm const
*/
-static ir_node *create_const_graph(be_abi_irg_t *abi, ir_node *irn, ir_node *block) {
+static ir_node *create_const_graph(ir_node *irn, ir_node *block) {
tarval *tv = get_Const_tarval(irn);
ir_mode *mode = get_tarval_mode(tv);
int value;
tv = tarval_convert_to(tv, mode_Iu);
}
value = get_tarval_long(tv);
- return create_const_graph_value(abi, get_irn_dbg_info(irn), block, value);
+ return create_const_graph_value(get_irn_dbg_info(irn), block, value);
}
/**
* Create an And that will mask all upper bits
*/
-static ir_node *gen_zero_extension(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) {
+static ir_node *gen_zero_extension(dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) {
unsigned mask_bits = (1 << result_bits) - 1;
- ir_node *mask_node = create_const_graph_value(abi, dbg, block, mask_bits);
- return new_rd_arm_And(dbg, current_ir_graph, block, op, mask_node, mode_Iu, ARM_SHF_NONE, NULL);
+ ir_node *mask_node = create_const_graph_value(dbg, block, mask_bits);
+ return new_rd_arm_And(dbg, current_ir_graph, block, op, mask_node, mode_Iu, ARM_SHF_NONE, 0);
}
/**
* Generate code for a sign extension.
*/
-static ir_node *gen_sign_extension(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) {
+static ir_node *gen_sign_extension(dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) {
ir_graph *irg = current_ir_graph;
int shift_width = 32 - result_bits;
- ir_node *shift_const_node = create_const_graph_value(abi, dbg, block, shift_width);
+ ir_node *shift_const_node = create_const_graph_value(dbg, block, shift_width);
ir_node *lshift_node = new_rd_arm_Shl(dbg, irg, block, op, shift_const_node, mode_Iu);
ir_node *rshift_node = new_rd_arm_Shrs(dbg, irg, block, lshift_node, shift_const_node, mode_Iu);
return rshift_node;
if (mode_is_float(src_mode)) {
if (mode_is_float(dst_mode)) {
/* from float to float */
- return new_rd_arm_fpaMov(dbg, irg, block, new_op, dst_mode);
+ return new_rd_arm_fpaMvf(dbg, irg, block, new_op, dst_mode);
}
else {
/* from float to int */
}
}
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;
}
}
min_mode = dst_mode;
}
if (mode_is_signed(min_mode)) {
- return gen_sign_extension(env_cg->birg->abi, dbg, block, new_op, min_bits);
+ return gen_sign_extension(dbg, block, new_op, min_bits);
} else {
- return gen_zero_extension(env_cg->birg->abi, dbg, block, new_op, min_bits);
+ 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;
}
*pmod = mod;
if (mod != ARM_SHF_NONE) {
- long v = get_tarval_long(get_arm_value(n));
+ long v = get_arm_imm_value(n);
if (v < 32)
return (int)v;
}
if (mode_is_float(mode)) {
env_cg->have_fp_insn = 1;
- if (USE_FPA(env_cg->isa))
- return new_rd_arm_fpaAdd(dbg, irg, block, new_op1, new_op2, mode);
- else if (USE_VFP(env_cg->isa)) {
+ if (USE_FPA(env_cg->isa)) {
+ if (is_arm_fpaMvf_i(new_op1))
+ return new_rd_arm_fpaAdf_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
+ if (is_arm_fpaMvf_i(new_op2))
+ return new_rd_arm_fpaAdf_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2));
+ 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 {
- assert(mode_is_numP(mode));
+ assert(mode_is_data(mode));
mode = mode_Iu;
if (is_arm_Mov_i(new_op1))
- return new_rd_arm_Add_i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1));
+ return new_rd_arm_Add_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
if (is_arm_Mov_i(new_op2))
- return new_rd_arm_Add_i(dbg, irg, block, new_op1, mode, get_arm_value(new_op2));
+ return new_rd_arm_Add_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2));
/* check for MLA */
- if (is_arm_Mul(new_op1) && get_irn_n_edges(new_op1) == 1) {
+ if (is_arm_Mul(new_op1) && get_irn_n_edges(op1) == 1) {
new_op3 = new_op2;
- op2 = get_irn_n(new_op1, 1);
- op1 = get_irn_n(new_op1, 0);
+ new_op2 = get_irn_n(new_op1, 1);
+ new_op1 = get_irn_n(new_op1, 0);
return new_rd_arm_Mla(dbg, irg, block, new_op1, new_op2, new_op3, mode);
}
- if (is_arm_Mul(new_op2) && get_irn_n_edges(new_op2) == 1) {
+ if (is_arm_Mul(new_op2) && get_irn_n_edges(op2) == 1) {
new_op3 = new_op1;
new_op1 = get_irn_n(new_op2, 0);
new_op2 = get_irn_n(new_op2, 1);
v = is_shifter_operand(new_op1, &mod);
if (v) {
new_op1 = get_irn_n(new_op1, 0);
- return new_rd_arm_Add(dbg, irg, block, new_op2, new_op1, mode, mod, new_tarval_from_long(v, mode_Iu));
+ return new_rd_arm_Add(dbg, irg, block, new_op2, new_op1, mode, mod, v);
}
/* is the second a shifter */
v = is_shifter_operand(new_op2, &mod);
if (v) {
new_op2 = get_irn_n(new_op2, 0);
- return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, mod, new_tarval_from_long(v, mode_Iu));
+ return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, mod, v);
}
/* normal ADD */
- return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL);
+ return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0);
}
}
if (mode_is_float(mode)) {
env_cg->have_fp_insn = 1;
- if (USE_FPA(env_cg->isa))
- return new_rd_arm_fpaMul(dbg, irg, block, new_op1, new_op2, mode);
+ if (USE_FPA(env_cg->isa)) {
+ if (is_arm_Mov_i(new_op1))
+ return new_rd_arm_fpaMuf_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
+ if (is_arm_Mov_i(new_op2))
+ return new_rd_arm_fpaMuf_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2));
+ return new_rd_arm_fpaMuf(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;
}
}
- assert(mode_is_numP(mode));
+ assert(mode_is_data(mode));
mode = mode_Iu;
return new_rd_arm_Mul(dbg, irg, block, new_op1, new_op2, mode);
}
assert(mode != mode_E && "IEEE Extended FP not supported");
env_cg->have_fp_insn = 1;
- if (USE_FPA(env_cg->isa))
- return new_rd_arm_fpaDiv(dbg, current_ir_graph, block, new_op1, new_op2, mode);
- else if (USE_VFP(env_cg->isa)) {
+ if (USE_FPA(env_cg->isa)) {
+ if (is_arm_Mov_i(new_op1))
+ return new_rd_arm_fpaRdf_i(dbg, current_ir_graph, block, new_op2, mode, get_arm_imm_value(new_op1));
+ if (is_arm_Mov_i(new_op2))
+ return new_rd_arm_fpaDvf_i(dbg, current_ir_graph, block, new_op1, mode, get_arm_imm_value(new_op2));
+ 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;
}
}
arm_shift_modifier mod; \
\
if (is_arm_Mov_i(new_op1)) \
- return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1)); \
+ return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1)); \
if (is_arm_Mov_i(new_op2)) \
- return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op1, mode, get_arm_value(new_op2)); \
+ return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2)); \
/* is the first a shifter */ \
v = is_shifter_operand(new_op1, &mod); \
if (v) { \
new_op1 = get_irn_n(new_op1, 0); \
- return new_rd_arm_ ## op(dbg, irg, block, new_op2, new_op1, mode, mod, new_tarval_from_long(v, mode_Iu)); \
+ return new_rd_arm_ ## op(dbg, irg, block, new_op2, new_op1, mode, mod, v); \
} \
/* is the second a shifter */ \
v = is_shifter_operand(new_op2, &mod); \
if (v) { \
new_op2 = get_irn_n(new_op2, 0); \
- return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, mod, new_tarval_from_long(v, mode_Iu)); \
+ return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, mod, v); \
} \
/* Normal op */ \
- return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL) \
+ return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0) \
/**
* Creates an ARM And.
if (mode_is_float(mode)) {
env_cg->have_fp_insn = 1;
- if (USE_FPA(env_cg->isa))
- return new_rd_arm_fpaSub(dbg, irg, block, new_op1, new_op2, mode);
- else if (USE_VFP(env_cg->isa)) {
+ if (USE_FPA(env_cg->isa)) {
+ if (is_arm_Mov_i(new_op1))
+ return new_rd_arm_fpaRsf_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
+ if (is_arm_Mov_i(new_op2))
+ return new_rd_arm_fpaSuf_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2));
+ 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;
}
}
else {
- assert(mode_is_numP(mode) && "unknown mode for Sub");
+ assert(mode_is_data(mode) && "unknown mode for Sub");
mode = mode_Iu;
if (is_arm_Mov_i(new_op1))
- return new_rd_arm_Rsb_i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1));
+ return new_rd_arm_Rsb_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
if (is_arm_Mov_i(new_op2))
- return new_rd_arm_Sub_i(dbg, irg, block, new_op1, mode, get_arm_value(new_op2));
+ return new_rd_arm_Sub_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2));
/* is the first a shifter */
v = is_shifter_operand(new_op1, &mod);
if (v) {
new_op1 = get_irn_n(new_op1, 0);
- return new_rd_arm_Rsb(dbg, irg, block, new_op2, new_op1, mode, mod, new_tarval_from_long(v, mode_Iu));
+ return new_rd_arm_Rsb(dbg, irg, block, new_op2, new_op1, mode, mod, v);
}
/* is the second a shifter */
v = is_shifter_operand(new_op2, &mod);
if (v) {
new_op2 = get_irn_n(new_op2, 0);
- return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, mod, new_tarval_from_long(v, mode_Iu));
+ return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, mod, v);
}
/* normal sub */
- return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL);
+ return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0);
}
}
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_LSL, get_arm_value(new_op2));
+ return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_LSL, get_arm_imm_value(new_op2));
}
return new_rd_arm_Shl(dbg, current_ir_graph, block, new_op1, new_op2, mode);
}
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_LSR, get_arm_value(new_op2));
+ return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_LSR, get_arm_imm_value(new_op2));
}
return new_rd_arm_Shr(dbg, current_ir_graph, block, new_op1, new_op2, mode);
}
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_ASR, get_arm_value(op2));
+ return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ASR, get_arm_imm_value(new_op2));
}
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.
*
ir_node *op = get_Not_op(node);
ir_node *new_op = be_transform_node(op);
dbg_info *dbg = get_irn_dbg_info(node);
- tarval *tv = NULL;
ir_mode *mode = mode_Iu;
arm_shift_modifier mod = ARM_SHF_NONE;
int v = is_shifter_operand(new_op, &mod);
if (v) {
new_op = get_irn_n(new_op, 0);
- tv = new_tarval_from_long(v, mode_Iu);
}
- return new_rd_arm_Mvn(dbg, current_ir_graph, block, new_op, mode, mod, tv);
+ return new_rd_arm_Mvn(dbg, current_ir_graph, block, new_op, mode, mod, v);
}
/**
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_numP(mode));
+ assert(mode_is_data(mode));
mode = mode_Iu;
return new_rd_arm_Abs(dbg, current_ir_graph, block, new_op, mode);
}
if (mode_is_float(mode)) {
env_cg->have_fp_insn = 1;
if (USE_FPA(env_cg->isa))
- return new_rd_arm_fpaMnv(dbg, current_ir_graph, block, op, 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_numP(mode));
+ assert(mode_is_data(mode));
mode = mode_Iu;
- return new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op, mode, get_mode_null(mode));
+ return new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op, mode, 0);
}
/**
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 {
- assert(mode_is_numP(mode) && "unsupported mode for Load");
+ assert(mode_is_data(mode) && "unsupported mode for Load");
if (mode_is_signed(mode)) {
/* sign 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");
}
} 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_numP(mode) && "unsupported mode for Store");
+ assert(mode_is_data(mode) && "unsupported mode for Store");
switch (get_mode_size_bits(mode)) {
case 8:
new_store = new_rd_arm_Storeb(dbg, irg, block, new_ptr, new_val, new_mem);
ir_mode *mode = get_irn_mode(selector);
if (mode == mode_b) {
- /* CondJmp */
+ /* an conditional jump */
ir_node *cmp_node = get_Proj_pred(selector);
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);
- return new_rd_arm_CondJmp(dbg, irg, block, new_op1, new_op2, get_Proj_proj(selector));
+ 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);
+
+ if (pnc & pn_Cmp_Uo) {
+ /* check for unordered, need cmf */
+ return new_rd_arm_fpaCmfBra(dbg, irg, block, new_op1, new_op2, pnc);
+ }
+ /* 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 {
/* SwitchJmp */
ir_node *new_op = be_transform_node(selector);
set_Proj_proj(proj, pn);
}
-
- const_graph = create_const_graph_value(env_cg->birg->abi, dbg, block, translation);
- sub = new_rd_arm_Sub(dbg, irg, block, new_op, const_graph, mode, ARM_SHF_NONE, NULL);
+ const_graph = create_const_graph_value(dbg, block, translation);
+ sub = new_rd_arm_Sub(dbg, irg, block, new_op, const_graph, mode, ARM_SHF_NONE, 0);
return new_rd_arm_SwitchJmp(dbg, irg, block, sub, n_projs, get_Cond_defaultProj(node) - translation);
}
}
case symconst_addr_ent:
ent = get_SymConst_entity(symc);
- mark_entity_visited(ent);
+ set_entity_backend_marked(ent, 1);
return get_entity_ld_ident(ent);
default:
return NULL;
}
+static tarval *fpa_imm[3][fpa_max];
+
+/**
+ * Check, if a floating point tarval is an fpa immediate, i.e.
+ * one of 0, 1, 2, 3, 4, 5, 10, or 0.5.
+ */
+static int is_fpa_immediate(tarval *tv) {
+ ir_mode *mode = get_tarval_mode(tv);
+ int i, j, res = 1;
+
+ switch (get_mode_size_bits(mode)) {
+ case 32:
+ i = 0;
+ break;
+ case 64:
+ i = 1;
+ break;
+ default:
+ i = 2;
+ }
+
+ if (tarval_cmp(tv, get_tarval_null(mode)) & pn_Cmp_Lt) {
+ tv = tarval_neg(tv);
+ res = -1;
+ }
+
+ for (j = 0; j < fpa_max; ++j) {
+ if (tv == fpa_imm[i][j])
+ return res * j;
+ }
+ return fpa_max;
+}
+
/**
* Transforms a Const node.
*
if (mode_is_float(mode)) {
env_cg->have_fp_insn = 1;
if (USE_FPA(env_cg->isa)) {
- node = new_rd_arm_fpaConst(dbg, irg, block, get_Const_tarval(node));
- /* ensure the const is schedules AFTER the barrier */
- add_irn_dep(node, be_abi_get_start_barrier(env_cg->birg->abi));
+ tarval *tv = get_Const_tarval(node);
+ int imm = is_fpa_immediate(tv);
+
+ if (imm != fpa_max) {
+ if (imm > 0)
+ node = new_rd_arm_fpaMvf_i(dbg, irg, block, mode, imm);
+ else
+ node = new_rd_arm_fpaMnf_i(dbg, irg, block, mode, -imm);
+ } else {
+ node = new_rd_arm_fpaConst(dbg, irg, block, tv);
+ }
+ /* ensure the const is scheduled AFTER the stack frame */
+ add_irn_dep(node, get_irg_frame(irg));
return node;
}
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(env_cg->birg->abi, node, block);
+ return create_const_graph(node, block);
}
/**
ir_node *block = be_transform_node(get_nodes_block(node));
ir_mode *mode = mode_Iu;
dbg_info *dbg = get_irn_dbg_info(node);
+ ir_graph *irg = current_ir_graph;
ir_node *res;
- res = new_rd_arm_SymConst(dbg, current_ir_graph, block, mode, get_sc_ident(node));
- add_irn_dep(res, be_abi_get_start_barrier(env_cg->birg->abi));
- /* ensure the const is schedules AFTER the barrier */
+ res = new_rd_arm_SymConst(dbg, irg, block, mode, get_sc_ident(node));
+ /* ensure the const is scheduled AFTER the stack frame */
+ add_irn_dep(res, get_irg_frame(irg));
return res;
}
new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu),
new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu),
new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu),
- new_mem, new_tarval_from_long(size, mode_Iu));
+ new_mem, size);
}
is relative. Both must be merged */
offset += get_sp_expand_offset(op);
}
- cnst = create_const_graph_value(env_cg->birg->abi, dbg, block, (unsigned)offset);
+ cnst = create_const_graph_value(dbg, block, (unsigned)offset);
if (is_arm_Mov_i(cnst))
- return new_rd_arm_Add_i(dbg, current_ir_graph, block, new_op, mode, get_arm_value(cnst));
- return new_rd_arm_Add(dbg, current_ir_graph, block, new_op, cnst, mode, ARM_SHF_NONE, NULL);
+ return new_rd_arm_Add_i(dbg, current_ir_graph, block, new_op, mode, get_arm_imm_value(cnst));
+ 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;
}
default:
break;
}
- assert(0);
- return new_rd_Unknown(irg, get_irn_mode(node));
+ panic("Unsupported Proj from Load");
}
/**
ir_node *new_pred = be_transform_node(pred);
ir_graph *irg = current_ir_graph;
dbg_info *dbgi = get_irn_dbg_info(node);
- ir_mode *mode = get_irn_mode(node);
long proj = get_Proj_proj(node);
switch(proj) {
default:
break;
}
- assert(0);
- return new_rd_Unknown(irg, mode);
+ panic("Unsupported Proj from CopyB");
}
/**
switch (proj) {
case pn_Quot_M:
- if (is_arm_fpaDiv(new_pred)) {
- return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaDiv_M);
- } else if (is_arm_fpaRdv(new_pred)) {
- return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaRdv_M);
- } else if (is_arm_fpaFDiv(new_pred)) {
- return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaFDiv_M);
- } else if (is_arm_fpaFRdv(new_pred)) {
- return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaFRdv_M);
+ if (is_arm_fpaDvf(new_pred) || is_arm_fpaDvf_i(new_pred)) {
+ return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaDvf_M);
+ } else if (is_arm_fpaRdf(new_pred) || is_arm_fpaRdf_i(new_pred)) {
+ return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaRdf_M);
+ } else if (is_arm_fpaFdv(new_pred) || is_arm_fpaFdv_i(new_pred)) {
+ return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaFdv_M);
+ } else if (is_arm_fpaFrd(new_pred) || is_arm_fpaFrd_i(new_pred)) {
+ return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaFrd_M);
}
break;
case pn_Quot_res:
- if (is_arm_fpaDiv(new_pred)) {
- return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaDiv_res);
- } else if (is_arm_fpaFDiv(new_pred)) {
- return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaRdv_res);
- } else if (is_arm_fpaFDiv(new_pred)) {
- return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaFDiv_res);
- } else if (is_arm_fpaFDiv(new_pred)) {
- return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaFRdv_res);
+ if (is_arm_fpaDvf(new_pred) || is_arm_fpaDvf_i(new_pred)) {
+ return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaDvf_res);
+ } else if (is_arm_fpaRdf(new_pred) || is_arm_fpaRdf_i(new_pred)) {
+ return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaRdf_res);
+ } else if (is_arm_fpaFdv(new_pred) || is_arm_fpaFdv_i(new_pred)) {
+ return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaFdv_res);
+ } else if (is_arm_fpaFrd(new_pred) || is_arm_fpaFrd_i(new_pred)) {
+ return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaFrd_res);
}
break;
default:
break;
}
- assert(0);
- return new_rd_Unknown(irg, mode);
+ panic("Unsupported Proj from Quot");
}
/**
- * Transform the Projs of an AddSP.
+ * Transform the Projs of a be_AddSP.
*/
static ir_node *gen_Proj_be_AddSP(ir_node *node) {
ir_node *block = be_transform_node(get_nodes_block(node));
dbg_info *dbgi = get_irn_dbg_info(node);
long proj = get_Proj_proj(node);
- if (proj == pn_be_AddSP_res) {
- ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_arm_AddSP_stack);
+ if (proj == pn_be_AddSP_sp) {
+ ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu,
+ 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_SubSPandCopy_addr);
} else if (proj == pn_be_AddSP_M) {
- return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_AddSP_M);
+ return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_SubSPandCopy_M);
}
-
- assert(0);
- return new_rd_Unknown(irg, get_irn_mode(node));
+ panic("Unsupported Proj from AddSP");
}
/**
- * Transform the Projs of a SubSP.
+ * Transform the Projs of a be_SubSP.
*/
static ir_node *gen_Proj_be_SubSP(ir_node *node) {
ir_node *block = be_transform_node(get_nodes_block(node));
dbg_info *dbgi = get_irn_dbg_info(node);
long proj = get_Proj_proj(node);
- if (proj == pn_be_SubSP_res) {
- ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_arm_SubSP_stack);
+ if (proj == pn_be_SubSP_sp) {
+ ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu,
+ pn_arm_AddSP_stack);
arch_set_irn_register(env_cg->arch_env, res, &arm_gp_regs[REG_SP]);
return res;
} else if (proj == pn_be_SubSP_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_AddSP_M);
}
-
- assert(0);
- return new_rd_Unknown(irg, get_irn_mode(node));
+ panic("Unsupported Proj from SubSP");
}
/**
*/
static ir_node *gen_Proj_Cmp(ir_node *node) {
(void) node;
- panic("Psi NYI\n");
+ panic("Mux NYI");
}
ir_node *pred = get_Proj_pred(node);
long proj = get_Proj_proj(node);
- if (is_Store(pred) || be_is_FrameStore(pred)) {
+ if (is_Store(pred)) {
if (proj == pn_Store_M) {
return be_transform_node(pred);
} else {
- assert(0);
- return new_r_Bad(irg);
+ panic("Unsupported Proj from Store");
}
- } else if (is_Load(pred) || be_is_FrameLoad(pred)) {
+ } else if (is_Load(pred)) {
return gen_Proj_Load(node);
} else if (is_CopyB(pred)) {
return gen_Proj_CopyB(node);
return gen_Proj_be_AddSP(node);
} else if (is_Cmp(pred)) {
return gen_Proj_Cmp(node);
- } else if (get_irn_op(pred) == op_Start) {
+ } else if (is_Start(pred)) {
if (proj == pn_Start_X_initial_exec) {
ir_node *block = get_nodes_block(pred);
ir_node *jump;
/* 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 == be_get_old_anchor(anchor_tls)) {
+ if (node == get_irg_anchor(irg, anchor_tls)) {
return gen_Proj_tls(node);
}
} else {
return be_duplicate_node(node);
}
+typedef ir_node *(*create_const_node_func)(dbg_info *db, ir_graph *irg, ir_node *block);
+
+static INLINE ir_node *create_const(ir_node **place,
+ create_const_node_func func,
+ const arch_register_t* reg)
+{
+ ir_node *block, *res;
+
+ if (*place != NULL)
+ return *place;
+
+ block = get_irg_start_block(env_cg->irg);
+ res = func(NULL, env_cg->irg, block);
+ arch_set_irn_register(env_cg->arch_env, res, reg);
+ *place = res;
+
+ add_irn_dep(get_irg_end(env_cg->irg), res);
+ return res;
+}
+
+static ir_node *arm_new_Unknown_gp(void) {
+ return create_const(&env_cg->unknown_gp, new_rd_arm_Unknown_GP,
+ &arm_gp_regs[REG_GP_UKNWN]);
+}
+
+static ir_node *arm_new_Unknown_fpa(void) {
+ return create_const(&env_cg->unknown_fpa, new_rd_arm_Unknown_FPA,
+ &arm_fpa_regs[REG_FPA_UKNWN]);
+}
+
/**
* This function just sets the register for the Unknown node
* as this is not done during register allocation because Unknown
* is an "ignore" node.
*/
static ir_node *gen_Unknown(ir_node *node) {
- (void) node;
- /*
ir_mode *mode = get_irn_mode(node);
if (mode_is_float(mode)) {
if (USE_FPA(env_cg->isa))
- return arm_new_Unknown_fpa(env_cg);
+ return arm_new_Unknown_fpa();
else if (USE_VFP(env_cg->isa))
- return arm_new_Unknown_vfp(env_cg);
+ panic("VFP not supported yet");
else
panic("Softfloat not supported yet");
} else if (mode_needs_gp_reg(mode)) {
- return ia32_new_Unknown_gp(env_cg);
+ return arm_new_Unknown_gp();
} else {
assert(0 && "unsupported Unknown-Mode");
}
-*/
- panic("Unknown NYI\n");
+
return NULL;
}
* 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);
GEN(be_FrameAddr);
//GEN(be_Call);
//GEN(be_Return);
- BAD(be_FrameLoad); /* unsupported yet */
- BAD(be_FrameStore); /* unsupported yet */
- BAD(be_StackParam); /* unsupported yet */
GEN(be_AddSP);
GEN(be_SubSP);
GEN(be_Copy);
}
/**
- * Pre-transform all unknown and noreg nodes.
+ * Pre-transform all unknown nodes.
*/
static void arm_pretransform_node(void *arch_cg) {
arm_code_gen_t *cg = arch_cg;
- (void) cg;
+
+ cg->unknown_gp = be_pre_transform_node(cg->unknown_gp);
+ cg->unknown_fpa = be_pre_transform_node(cg->unknown_fpa);
+}
+
+/**
+ * Initialize fpa Immediate support.
+ */
+static void arm_init_fpa_immediate(void) {
+ /* 0, 1, 2, 3, 4, 5, 10, or 0.5. */
+ fpa_imm[0][fpa_null] = get_tarval_null(mode_F);
+ fpa_imm[0][fpa_one] = get_tarval_one(mode_F);
+ fpa_imm[0][fpa_two] = new_tarval_from_str("2", 1, mode_F);
+ fpa_imm[0][fpa_three] = new_tarval_from_str("3", 1, mode_F);
+ fpa_imm[0][fpa_four] = new_tarval_from_str("4", 1, mode_F);
+ fpa_imm[0][fpa_five] = new_tarval_from_str("5", 1, mode_F);
+ fpa_imm[0][fpa_ten] = new_tarval_from_str("10", 2, mode_F);
+ fpa_imm[0][fpa_half] = new_tarval_from_str("0.5", 3, mode_F);
+
+ fpa_imm[1][fpa_null] = get_tarval_null(mode_D);
+ fpa_imm[1][fpa_one] = get_tarval_one(mode_D);
+ fpa_imm[1][fpa_two] = new_tarval_from_str("2", 1, mode_D);
+ fpa_imm[1][fpa_three] = new_tarval_from_str("3", 1, mode_D);
+ fpa_imm[1][fpa_four] = new_tarval_from_str("4", 1, mode_D);
+ fpa_imm[1][fpa_five] = new_tarval_from_str("5", 1, mode_D);
+ fpa_imm[1][fpa_ten] = new_tarval_from_str("10", 2, mode_D);
+ fpa_imm[1][fpa_half] = new_tarval_from_str("0.5", 3, mode_D);
+
+ fpa_imm[2][fpa_null] = get_tarval_null(mode_E);
+ fpa_imm[2][fpa_one] = get_tarval_one(mode_E);
+ fpa_imm[2][fpa_two] = new_tarval_from_str("2", 1, mode_E);
+ fpa_imm[2][fpa_three] = new_tarval_from_str("3", 1, mode_E);
+ fpa_imm[2][fpa_four] = new_tarval_from_str("4", 1, mode_E);
+ fpa_imm[2][fpa_five] = new_tarval_from_str("5", 1, mode_E);
+ fpa_imm[2][fpa_ten] = new_tarval_from_str("10", 2, mode_E);
+ fpa_imm[2][fpa_half] = new_tarval_from_str("0.5", 3, mode_E);
}
/**
* Transform a Firm graph into an ARM graph.
*/
void arm_transform_graph(arm_code_gen_t *cg) {
+ static int imm_initialized = 0;
+
+ if (! imm_initialized) {
+ arm_init_fpa_immediate();
+ imm_initialized = 1;
+ }
arm_register_transformers();
env_cg = cg;
- be_transform_graph(cg->birg, /*arm_pretransform_node*/ NULL, cg);
+ be_transform_graph(cg->birg, arm_pretransform_node, cg);
}
void arm_init_transform(void) {