From 5d79fe73922ccec0217bad72eca772e0487b7c49 Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Fri, 15 Jun 2007 15:26:41 +0000 Subject: [PATCH] Changed transformer to be like ia32: do a transform- and copy added some more isntructions, some fixes at least HelloWorld compiles again :-) [r14532] --- ir/be/arm/arm_emitter.c | 9 +- ir/be/arm/arm_map_regs.c | 47 +- ir/be/arm/arm_map_regs.h | 6 +- ir/be/arm/arm_new_nodes.c | 52 ++ ir/be/arm/arm_new_nodes.h | 15 + ir/be/arm/arm_nodes_attr.h | 11 +- ir/be/arm/arm_spec.pl | 69 +- ir/be/arm/arm_transform.c | 1514 +++++++++++++++++++++--------------- ir/be/arm/arm_transform.h | 8 +- ir/be/arm/bearch_arm.c | 75 +- ir/be/arm/bearch_arm_t.h | 19 +- 11 files changed, 1067 insertions(+), 758 deletions(-) diff --git a/ir/be/arm/arm_emitter.c b/ir/be/arm/arm_emitter.c index 868d349f9..c64480c8f 100644 --- a/ir/be/arm/arm_emitter.c +++ b/ir/be/arm/arm_emitter.c @@ -20,7 +20,7 @@ /** * @file * @brief arm emitter - * @author Oliver Richter, Tobias Gneist + * @author Oliver Richter, Tobias Gneist, Michael Beck * @version $Id$ */ #define SILENCER @@ -823,6 +823,11 @@ static void emit_arm_fpaDbl2GP(arm_emit_env_t *env, const ir_node *irn) { be_emit_finish_line_gas(env->emit, irn); } +static void emit_arm_LdTls(arm_emit_env_t *env, const ir_node *irn) { + panic("TLS not supported for this target\n"); + /* Er... our gcc does not support it... Install a newer toolchain. */ +} + /*********************************************************************************** * _ __ _ * (_) / _| | | @@ -875,11 +880,11 @@ static void arm_register_emitters(void) { ARM_EMIT(SwitchJmp); ARM_EMIT(fpaDbl2GP); ARM_EMIT(fpaConst); + ARM_EMIT(LdTls); /* benode emitter */ BE_EMIT(Call); BE_EMIT(IncSP); -// BE_EMIT(AddSP); BE_EMIT(Copy); BE_EMIT(Spill); BE_EMIT(Reload); diff --git a/ir/be/arm/arm_map_regs.c b/ir/be/arm/arm_map_regs.c index be81948e9..19a3ff169 100644 --- a/ir/be/arm/arm_map_regs.c +++ b/ir/be/arm/arm_map_regs.c @@ -78,51 +78,6 @@ void arm_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set) { } const arch_register_t *arm_get_firm_reg(const ir_node *irn, set *reg_set) { - struct arm_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set); + const struct arm_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set); return assoc->reg; } - - - -/** - * Translates the proj number into a "real" argument position for register - * requirements depended on the predecessor. - */ -long arm_translate_proj_pos(const ir_node *proj) { - ir_node *pred = get_Proj_pred(proj); - long nr = get_Proj_proj(proj); - - if (is_irn_machine_op(pred)) { - switch (get_arm_irn_opcode(pred)) { - - case iro_arm_Loadb: - case iro_arm_Loadbs: - case iro_arm_Loadh: - case iro_arm_Loadhs: - case iro_arm_Load: - case iro_arm_fpaLdf: - if (nr == pn_Load_res) - return 0; - assert(0 && "unsupported Proj(Load) number"); - break; - case iro_arm_Storeb: - case iro_arm_Storebs: - case iro_arm_Storeh: - case iro_arm_Storehs: - case iro_arm_Store: - case iro_arm_fpaStf: - return 0; - case iro_arm_fpaDiv: - case iro_arm_fpaRdv: - if (nr == pn_Quot_res) - return 0; - assert(0 && "there should be no more Projs for a fDiv"); - break; - default: - break; - } - } - -// assert(0 && "unsupported Proj(X)"); - return nr; -} diff --git a/ir/be/arm/arm_map_regs.h b/ir/be/arm/arm_map_regs.h index 4a59c3ab3..6a79d84e1 100644 --- a/ir/be/arm/arm_map_regs.h +++ b/ir/be/arm/arm_map_regs.h @@ -19,8 +19,8 @@ /** * @file - * @brief declarations for arm register allocation - * @author Oliver Richter, Tobias Gneist + * @brief declarations for ARM register allocation + * @author Oliver Richter, Tobias Gneist, Michael Beck * @version $Id$ */ #ifndef FIRM_BE_ARM_ARM_MAP_REGS_H @@ -38,6 +38,4 @@ int arm_cmp_irn_reg_assoc(const void *a, const void *b, size_t len); void arm_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set); const arch_register_t *arm_get_firm_reg(const ir_node *irn, set *reg_set); -long arm_translate_proj_pos(const ir_node *proj); - #endif diff --git a/ir/be/arm/arm_new_nodes.c b/ir/be/arm/arm_new_nodes.c index e1b6e1f18..3a98f6985 100644 --- a/ir/be/arm/arm_new_nodes.c +++ b/ir/be/arm/arm_new_nodes.c @@ -416,6 +416,24 @@ const arch_register_t *get_arm_out_reg(const ir_node *node, int pos) { return attr->slots[pos]; } +/** + * Sets the flags for the n'th out. + */ +void set_arm_out_flags(ir_node *node, arch_irn_flags_t flags, int pos) { + arm_attr_t *attr = get_arm_attr(node); + assert(pos < ARR_LEN(attr->out_flags) && "Invalid OUT position."); + attr->out_flags[pos] = flags; +} + +/** + * Gets the flags for the n'th out. + */ +arch_irn_flags_t get_arm_out_flags(const ir_node *node, int pos) { + const arm_attr_t *attr = get_arm_attr_const(node); + assert(pos < ARR_LEN(attr->out_flags) && "Invalid OUT position."); + return attr->out_flags[pos]; +} + /** * Returns the number of results. */ @@ -525,6 +543,9 @@ void init_arm_attributes(ir_node *node, int flags, const arch_register_req_t ** attr->instr_fl = (ARM_COND_AL << 3) | ARM_SHF_NONE; attr->value = NULL; + attr->out_flags = NEW_ARR_D(int, obst, n_res); + memset(attr->out_flags, 0, n_res * sizeof(attr->out_flags[0])); + attr->slots = NEW_ARR_D(const arch_register_t*, obst, n_res); memset((arch_register_t **)attr->slots, 0, n_res * sizeof(attr->slots[0])); } @@ -668,7 +689,38 @@ static int cmp_attr_arm_SwitchJmp(ir_node *a, ir_node *b) { return 1; } +/** copies the ARM attributes of a node. */ +static void arm_copy_attr(const ir_node *old_node, ir_node *new_node) { + ir_graph *irg = get_irn_irg(new_node); + struct obstack *obst = get_irg_obstack(irg); + const arm_attr_t *attr_old = get_arm_attr_const(old_node); + arm_attr_t *attr_new = get_arm_attr(new_node); + + /* copy the attributes */ + memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node))); + + /* copy out flags */ + attr_new->out_flags = + DUP_ARR_D(int, obst, attr_old->out_flags); + /* copy register assignments */ + attr_new->slots = + DUP_ARR_D(arch_register_t*, obst, attr_old->slots); +} + /* Include the generated constructor functions */ #include "gen_arm_new_nodes.c.inl" + +/** + * Registers the arm_copy_attr function for all ARM opcodes. + */ +void arm_register_copy_attr_func(void) { + int i; + + for (i = get_irp_n_opcodes() - 1; i >= 0; --i) { + ir_op *op = get_irp_opcode(i); + if (is_arm_op(op)) + op->ops.copy_attr = arm_copy_attr; + } +} diff --git a/ir/be/arm/arm_new_nodes.h b/ir/be/arm/arm_new_nodes.h index 6fe6a7b8b..3116c2b9b 100644 --- a/ir/be/arm/arm_new_nodes.h +++ b/ir/be/arm/arm_new_nodes.h @@ -140,6 +140,16 @@ int get_arm_n_res(const ir_node *node); void init_arm_attributes(ir_node *node, int flags, const arch_register_req_t ** in_reqs, const arch_register_req_t ** out_reqs, const be_execution_unit_t ***execution_units, int n_res, unsigned latency); +/** + * Sets the flags for the n'th out. + */ +void set_arm_out_flags(ir_node *node, arch_irn_flags_t flags, int pos); + +/** + * Gets the flags for the n'th out. + */ +arch_irn_flags_t get_arm_out_flags(const ir_node *node, int pos); + /** * Returns the tarval */ @@ -196,6 +206,11 @@ arm_shift_modifier get_arm_shift_modifier(const ir_node *node); */ unsigned int arm_decode_imm_w_shift(tarval *tv); +/** + * Registers the arm_copy_attr function for all ARM opcodes. + */ +void arm_register_copy_attr_func(void); + /* Include the generated headers */ #include "gen_arm_new_nodes.h" diff --git a/ir/be/arm/arm_nodes_attr.h b/ir/be/arm/arm_nodes_attr.h index ae98d1aea..8a0ace3e2 100644 --- a/ir/be/arm/arm_nodes_attr.h +++ b/ir/be/arm/arm_nodes_attr.h @@ -82,16 +82,17 @@ typedef enum _arm_condition { /** Generic ARM node attributes. */ typedef struct _arm_attr_t { - arch_irn_flags_t flags; /**< indicating if spillable, rematerializeable ... etc. */ + arch_irn_flags_t flags; /**< indicating if spillable, rematerializeable ... etc. */ const arch_register_req_t **in_req; /**< register requirements for arguments */ const arch_register_req_t **out_req; /**< register requirements for results */ - ir_mode *op_mode; /**< operation mode if different from node's mode */ - unsigned instr_fl; /**< condition code, shift modifier */ - tarval *value; /**< immediate */ + ir_mode *op_mode; /**< operation mode if different from node's mode */ + unsigned instr_fl; /**< condition code, shift modifier */ + tarval *value; /**< immediate */ + int *out_flags; /**< flags for each produced value */ - const arch_register_t **slots; /**< register slots for assigned registers */ + const arch_register_t **slots; /**< register slots for assigned registers */ } arm_attr_t; /** Attributes for a SymConst */ diff --git a/ir/be/arm/arm_spec.pl b/ir/be/arm/arm_spec.pl index ae90b2dc6..c1d510cbe 100644 --- a/ir/be/arm/arm_spec.pl +++ b/ir/be/arm/arm_spec.pl @@ -472,6 +472,9 @@ Abs => { # other operations +# +# this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd +# EmptyReg => { op_flags => "c", irn_flags => "R", @@ -490,7 +493,10 @@ CopyB => { op_flags => "F|H", state => "pinned", comment => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)", + attr => "tarval *tv", + init_attr => 'attr->value = tv;', reg_req => { "in" => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], "out" => [ "none" ] }, + outs => [ "M" ], }, SymConst => { @@ -586,16 +592,6 @@ Storeb => { outs => [ "M" ], }, -Storebs => { - op_flags => "L|F", - irn_flags => "R", - state => "exc_pinned", - comment => "construct Store: Store(ptr, val, mem) = ST ptr,val", - reg_req => { "in" => [ "gp", "gp", "none" ], "out" => [ "none" ] }, - emit => '. strsb %S1, [%S0, #0]', - outs => [ "M" ], -}, - Storeh => { op_flags => "L|F", irn_flags => "R", @@ -606,16 +602,6 @@ Storeh => { outs => [ "M" ], }, -Storehs => { - op_flags => "L|F", - irn_flags => "R", - state => "exc_pinned", - comment => "construct Store: Store(ptr, val, mem) = ST ptr,val", - reg_req => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] }, - emit => '. strhs %S1, [%S0, #0]', - outs => [ "M" ], -}, - Store => { op_flags => "L|F", irn_flags => "R", @@ -716,26 +702,38 @@ fpaRsb => { fpaDiv => { comment => "construct FPA Div: Div(a, b) = a / b", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, + attr => "ir_mode *op_mode", + init_attr => "attr->op_mode = op_mode;", + reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] }, emit =>'. dvf%M %D0, %S0, %S1', + outs => [ "res", "M" ], }, fpaRdv => { comment => "construct FPA reverse Div: Div(a, b) = b / a", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, + attr => "ir_mode *op_mode", + init_attr => "attr->op_mode = op_mode;", + reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] }, emit =>'. rdf%M %D0, %S0, %S1', + outs => [ "res", "M" ], }, fpaFDiv => { comment => "construct FPA Fast Div: Div(a, b) = a / b", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, + attr => "ir_mode *op_mode", + init_attr => "attr->op_mode = op_mode;", + reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] }, emit =>'. fdv%M %D0, %S0, %S1', + outs => [ "res", "M" ], }, fpaFRdv => { comment => "construct FPA Fast reverse Div: Div(a, b) = b / a", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, + attr => "ir_mode *op_mode", + init_attr => "attr->op_mode = op_mode;", + reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] }, emit =>'. frd%M %D0, %S0, %S1', + outs => [ "res", "M" ], }, fpaMov => { @@ -810,6 +808,29 @@ fpaDbl2GP => { outs => [ "low", "high", "M" ], }, +AddSP => { + irn_flags => "I", + comment => "construct Add to stack pointer", + reg_req => { in => [ "sp", "gp", "none" ], out => [ "in_r1", "none" ] }, + emit => '. add %D0, %S0, %S1', + outs => [ "stack:S", "M" ], +}, + +SubSP => { + irn_flags => "I", + comment => "construct Sub from stack pointer", + reg_req => { in => [ "sp", "gp", "none" ], out => [ "in_r1", "none" ] }, + emit => '. sub %D0, %S0, %S1', + outs => [ "stack:S", "M" ], +}, + +LdTls => { + irn_flags => "R", + comment => "load the TLS address", + reg_req => { out => [ "gp" ] }, +}, + + # # floating point constants # diff --git a/ir/be/arm/arm_transform.c b/ir/be/arm/arm_transform.c index 21e287742..5c11cd49a 100644 --- a/ir/be/arm/arm_transform.c +++ b/ir/be/arm/arm_transform.c @@ -42,6 +42,7 @@ #include "../benode_t.h" #include "../beirg_t.h" +#include "../betranshlp.h" #include "bearch_arm_t.h" #include "arm_nodes_attr.h" @@ -55,8 +56,10 @@ #include -extern ir_op *get_op_Mulh(void); +/** hold the current code generator during transformation */ +static arm_code_gen_t *env_cg; +extern ir_op *get_op_Mulh(void); /**************************************************************************************************** @@ -69,6 +72,10 @@ extern ir_op *get_op_Mulh(void); * ****************************************************************************************************/ +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]; @@ -81,7 +88,7 @@ static unsigned do_rol(unsigned v, unsigned rol) { } /** - * construct 8bit values und rot amounts for a value + * construct 8bit values and rot amounts for a value */ static void gen_vals_from_word(unsigned int value, vals *result) { @@ -125,9 +132,14 @@ static void gen_vals_from_word(unsigned int value, vals *result) * Creates a arm_Const node. */ static ir_node *create_const_node(be_abi_irg_t *abi, ir_node *irn, ir_node *block, long value) { - tarval *tv = new_tarval_from_long(value, mode_Iu); - dbg_info *dbg = get_irn_dbg_info(irn); - ir_node *res = new_rd_arm_Mov_i(dbg, current_ir_graph, block, get_irn_mode(irn), tv); + tarval *tv = new_tarval_from_long(value, mode_Iu); + dbg_info *dbg = get_irn_dbg_info(irn); + ir_mode *mode = get_irn_mode(irn); + 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)); return res; @@ -137,9 +149,14 @@ static ir_node *create_const_node(be_abi_irg_t *abi, ir_node *irn, ir_node *bloc * Creates a arm_Const_Neg node. */ static ir_node *create_const_neg_node(be_abi_irg_t *abi, ir_node *irn, ir_node *block, long value) { - tarval *tv = new_tarval_from_long(value, mode_Iu); - dbg_info *dbg = get_irn_dbg_info(irn); - ir_node *res = new_rd_arm_Mvn_i(dbg, current_ir_graph, block, get_irn_mode(irn), tv); + tarval *tv = new_tarval_from_long(value, mode_Iu); + dbg_info *dbg = get_irn_dbg_info(irn); + ir_mode *mode = get_irn_mode(irn); + 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 */ return res; @@ -177,6 +194,9 @@ static ir_node *create_const_graph_value(be_abi_irg_t *abi, ir_node *irn, ir_nod gen_vals_from_word(value, &v); gen_vals_from_word(~value, &vn); + if (mode_needs_gp_reg(mode)) + mode = mode_Iu; + if (vn.ops < v.ops) { /* remove bits */ result = create_const_neg_node(abi, irn, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0])); @@ -206,7 +226,16 @@ static ir_node *create_const_graph_value(be_abi_irg_t *abi, ir_node *irn, ir_nod * @param irn a Firm const */ static ir_node *create_const_graph(be_abi_irg_t *abi, ir_node *irn, ir_node *block) { - int value = get_tarval_long(get_Const_tarval(irn)); + tarval *tv = get_Const_tarval(irn); + ir_mode *mode = get_tarval_mode(tv); + int value; + + if (mode_is_reference(mode)) { + /* ARM is 32bit, so we can safely convert a reference tarval into Iu */ + assert(get_mode_size_bits(mode) == get_mode_size_bits(mode_Iu)); + tv = tarval_convert_to(tv, mode_Iu); + } + value = get_tarval_long(tv); return create_const_graph_value(abi, irn, block, value); } @@ -219,7 +248,7 @@ static ir_node *gen_arm_Const(ir_node *irn, ir_node *block, arm_code_gen_t *cg) dbg_info *dbg = get_irn_dbg_info(irn); if (mode_is_float(mode)) { - cg->have_fp = 1; + cg->have_fp_insn = 1; if (USE_FPA(cg->isa)) { irn = new_rd_arm_fpaConst(dbg, irg, block, get_Const_tarval(irn)); /* ensure the const is schedules AFTER the barrier */ @@ -230,8 +259,6 @@ static ir_node *gen_arm_Const(ir_node *irn, ir_node *block, arm_code_gen_t *cg) assert(mode != mode_E && "IEEE Extended FP not supported"); assert(0 && "NYI"); } - else if (mode_is_reference(mode)) - return irn; return create_const_graph(cg->birg->abi, irn, block); } @@ -257,106 +284,110 @@ static ir_node *gen_sign_extension(be_abi_irg_t *abi, ir_node *irn, ir_node *op, /** * Transforms a Conv node. * - * @param env The transformation environment - * @return the created arm Conv node + * @return The created ia32 Conv node */ -static ir_node *gen_Conv(ir_node *irn, arm_code_gen_t *cg) { - ir_graph *irg = current_ir_graph; - ir_node *block = get_nodes_block(irn); - ir_node *op = get_Conv_op(irn); - ir_mode *in_mode = get_irn_mode(op); - ir_mode *out_mode = get_irn_mode(irn); - dbg_info *dbg = get_irn_dbg_info(irn); - - if (in_mode == out_mode) - return op; - - if (mode_is_float(in_mode) || mode_is_float(out_mode)) { - cg->have_fp = 1; - - if (USE_FPA(cg->isa)) { - if (mode_is_float(in_mode)) { - if (mode_is_float(out_mode)) { +static ir_node *gen_Conv(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *op = get_Conv_op(node); + ir_node *new_op = be_transform_node(op); + ir_graph *irg = current_ir_graph; + ir_mode *src_mode = get_irn_mode(op); + ir_mode *dst_mode = get_irn_mode(node); + dbg_info *dbg = get_irn_dbg_info(node); + + if (mode_needs_gp_reg(dst_mode)) + dst_mode = mode_Iu; + + if (src_mode == dst_mode) + return new_op; + + if (mode_is_float(src_mode) || mode_is_float(dst_mode)) { + env_cg->have_fp_insn = 1; + + if (USE_FPA(env_cg->isa)) { + if (mode_is_float(src_mode)) { + if (mode_is_float(dst_mode)) { /* from float to float */ - return new_rd_arm_fpaMov(dbg, irg, block, op, out_mode); + return new_rd_arm_fpaMov(dbg, irg, block, new_op, dst_mode); } else { /* from float to int */ - return new_rd_arm_fpaFix(dbg, irg, block, op, out_mode); + return new_rd_arm_fpaFix(dbg, irg, block, new_op, dst_mode); } } else { /* from int to float */ - return new_rd_arm_fpaFlt(dbg, irg, block, op, out_mode); + return new_rd_arm_fpaFlt(dbg, irg, block, new_op, dst_mode); } } - assert(0 && "NYI"); + else { + panic("VFP not supported yet\n"); + return NULL; + } } else { /* complete in gp registers */ - int in_bits = get_mode_size_bits(in_mode); - int out_bits = get_mode_size_bits(out_mode); - int in_sign = get_mode_sign(in_mode); - int out_sign = get_mode_sign(out_mode); - - // 32 -> 32 - // NOPpen - if (in_bits == out_bits && in_bits == 32) - return op; - - // 16 -> 16 - // unsigned -> unsigned - // NOP - // unsigned -> signed - // sign extension (31:16)=(15) - // signed -> unsigned - // maskieren (31:16)=0 - // signed -> signed - // NOP - if (in_bits == out_bits && out_bits < 32) { - if (in_sign && !out_sign) { - return gen_mask(cg->birg->abi, irn, op, out_bits); + int src_bits = get_mode_size_bits(src_mode); + int dst_bits = get_mode_size_bits(dst_mode); + int src_sign = get_mode_sign(src_mode); + int dst_sign = get_mode_sign(dst_mode); + + if (src_bits == dst_bits) { + /* kill 32 -> 32 convs */ + if (src_bits == 32) { + return new_op; + } else if (dst_bits < 32) { + // 16 -> 16 + // unsigned -> unsigned + // NOP + // unsigned -> signed + // sign extension (31:16)=(15) + // signed -> unsigned + // zero extension (31:16)=0 + // signed -> signed + // NOP + if (src_sign && !dst_sign) { + return gen_mask(env_cg->birg->abi, node, new_op, dst_bits); + } else { + return gen_sign_extension(env_cg->birg->abi, node, new_op, dst_bits); + } } else { - return gen_sign_extension(cg->birg->abi, irn, op, out_bits); + panic("Cannot handle mode %+F with %d bits\n", dst_mode, dst_bits); + return NULL; } } - - // 16 -> 32 - // unsigned -> unsigned - // NOP - // unsigned -> signed - // NOP - // signed -> unsigned - // sign extension (31:16)=(15) - // signed -> signed - // sign extension (31:16)=(15) - if (in_bits < out_bits) { - if (in_sign) { - return gen_sign_extension(cg->birg->abi, irn, op, out_bits); + else if (src_bits < dst_bits) { + // 16 -> 32 + // unsigned -> unsigned + // NOP + // unsigned -> signed + // NOP + // signed -> unsigned + // sign extension (31:16)=(15) + // signed -> signed + // sign extension (31:16)=(15) + if (src_sign) { + return gen_sign_extension(env_cg->birg->abi, node, new_op, dst_bits); } else { - return op; + return new_op; } } - - // 32 -> 16 - // unsigned -> unsigned - // maskieren (31:16)=0 - // unsigned -> signed - // maskieren (31:16)=0 - // signed -> unsigned - // maskieren (31:16)=0 - // signed -> signed - // sign extension (erledigt auch maskieren) (31:16)=(15) - if (in_bits > out_bits) { - if (in_sign && out_sign) { - return gen_sign_extension(cg->birg->abi, irn, op, out_bits); + else { + // 32 -> 16 + // unsigned -> unsigned + // maskieren (31:16)=0 + // unsigned -> signed + // maskieren (31:16)=0 + // signed -> unsigned + // maskieren (31:16)=0 + // signed -> signed + // sign extension (erledigt auch maskieren) (31:16)=(15) + if (src_sign && dst_sign) { + return gen_sign_extension(env_cg->birg->abi, node, new_op, dst_bits); } else { - return gen_mask(cg->birg->abi, irn, op, out_bits); + return gen_mask(env_cg->birg->abi, node, new_op, dst_bits); } } - assert(0 && "recheck integer conversion logic!"); - return irn; } - return NULL; } /** @@ -378,492 +409,517 @@ static int is_shifter_operand(ir_node *n, arm_shift_modifier *pmod) { } /** - * Creates an arm Add. + * Creates an ARM Add. * - * @param env The transformation environment * @return the created arm Add node */ -static ir_node *gen_Add(ir_node *irn, arm_code_gen_t *cg) { - ir_node *block = get_nodes_block(irn); - ir_node *op1 = get_Add_left(irn); - ir_node *op2 = get_Add_right(irn); - ir_mode *mode = get_irn_mode(irn); - ir_graph *irg = current_ir_graph; - ir_node *op3; +static ir_node *gen_Add(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *op1 = get_Add_left(node); + ir_node *new_op1 = be_transform_node(op1); + ir_node *op2 = get_Add_right(node); + ir_node *new_op2 = be_transform_node(op2); + ir_mode *mode = get_irn_mode(node); + ir_graph *irg = current_ir_graph; + ir_node *new_op3; int v; arm_shift_modifier mod; - dbg_info *dbg = get_irn_dbg_info(irn); + dbg_info *dbg = get_irn_dbg_info(node); if (mode_is_float(mode)) { - cg->have_fp = 1; - if (USE_FPA(cg->isa)) - return new_rd_arm_fpaAdd(dbg, irg, block, op1, op2, mode); - else if (USE_VFP(cg->isa)) { + 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)) { assert(mode != mode_E && "IEEE Extended FP not supported"); + panic("VFP not supported yet\n"); + return NULL; } - assert(0 && "NYI"); - } - if (mode_is_numP(mode)) { - if (is_arm_Mov_i(op1)) - return new_rd_arm_Add_i(dbg, irg, block, op2, mode, get_arm_value(op1)); - if (is_arm_Mov_i(op2)) - return new_rd_arm_Add_i(dbg, irg, block, op1, mode, get_arm_value(op2)); + else { + panic("Softfloat not supported yet\n"); + return NULL; + } + } else { + assert(mode_is_numP(mode)); + + if (is_arm_Mov_i(new_op1)) + return new_rd_arm_Add_i(dbg, irg, block, new_op2, mode, get_arm_value(op1)); + if (is_arm_Mov_i(new_op2)) + return new_rd_arm_Add_i(dbg, irg, block, new_op1, mode, get_arm_value(op2)); /* check for MLA */ - if (is_arm_Mul(op1) && get_irn_n_edges(op1) == 1) { - op3 = op2; - op2 = get_irn_n(op1, 1); - op1 = get_irn_n(op1, 0); + if (is_arm_Mul(new_op1) && get_irn_n_edges(new_op1) == 1) { + new_op3 = new_op2; + op2 = get_irn_n(new_op1, 1); + op1 = get_irn_n(new_op1, 0); - return new_rd_arm_Mla(dbg, irg, block, op1, op2, op3, mode); + return new_rd_arm_Mla(dbg, irg, block, new_op1, new_op2, new_op3, mode); } - if (is_arm_Mul(op2) && get_irn_n_edges(op2) == 1) { - op3 = op1; - op1 = get_irn_n(op2, 0); - op2 = get_irn_n(op2, 1); + if (is_arm_Mul(new_op2) && get_irn_n_edges(new_op2) == 1) { + new_op3 = new_op1; + new_op1 = get_irn_n(new_op2, 0); + new_op2 = get_irn_n(new_op2, 1); - return new_rd_arm_Mla(dbg, irg, block, op1, op2, op3, mode); + return new_rd_arm_Mla(dbg, irg, block, new_op1, new_op2, new_op3, mode); } /* is the first a shifter */ - v = is_shifter_operand(op1, &mod); + v = is_shifter_operand(new_op1, &mod); if (v) { - op1 = get_irn_n(op1, 0); - return new_rd_arm_Add(dbg, irg, block, op2, op1, mode, mod, new_tarval_from_long(v, mode_Iu)); + 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)); } /* is the second a shifter */ - v = is_shifter_operand(op2, &mod); + v = is_shifter_operand(new_op2, &mod); if (v) { - op2 = get_irn_n(op2, 0); - return new_rd_arm_Add(dbg, irg, block, op1, op2, mode, mod, new_tarval_from_long(v, mode_Iu)); + 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)); } /* normal ADD */ - return new_rd_arm_Add(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL); + return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL); } - - assert(0 && "unknown mode for add"); - return NULL; } /** - * Creates an arm Mul. + * Creates an ARM Mul. * - * @param env The transformation environment * @return the created arm Mul node */ -static ir_node *gen_Mul(ir_node *irn, arm_code_gen_t *cg) { - ir_node *block = get_nodes_block(irn); - ir_node *op1 = get_Mul_left(irn); - ir_node *op2 = get_Mul_right(irn); - ir_mode *mode = get_irn_mode(irn); - ir_graph *irg = current_ir_graph; - dbg_info *dbg = get_irn_dbg_info(irn); +static ir_node *gen_Mul(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *op1 = get_Mul_left(node); + ir_node *new_op1 = be_transform_node(op1); + ir_node *op2 = get_Mul_right(node); + ir_node *new_op2 = be_transform_node(op2); + ir_mode *mode = get_irn_mode(node); + ir_graph *irg = current_ir_graph; + dbg_info *dbg = get_irn_dbg_info(node); if (mode_is_float(mode)) { - cg->have_fp = 1; - if (USE_FPA(cg->isa)) - return new_rd_arm_fpaMul(dbg, irg, block, op1, op2, mode); - else if (USE_VFP(cg->isa)) { + 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); + else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); + panic("VFP not supported yet\n"); + } + else { + panic("Softfloat not supported yet\n"); + return NULL; } - assert(0 && "NYI"); } - return new_rd_arm_Mul(dbg, irg, block, op1, op2, mode); + return new_rd_arm_Mul(dbg, irg, block, new_op1, new_op2, mode); } /** - * Creates an arm floating point Div. + * Creates an ARM floating point Div. * * @param env The transformation environment * @return the created arm fDiv node */ -static ir_node *gen_Quot(ir_node *irn, arm_code_gen_t *cg) { - ir_node *block = get_nodes_block(irn); - ir_node *op1 = get_Quot_left(irn); - ir_node *op2 = get_Quot_right(irn); - ir_mode *mode = get_irn_mode(irn); - dbg_info *dbg = get_irn_dbg_info(irn); +static ir_node *gen_Quot(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *op1 = get_Quot_left(node); + ir_node *new_op1 = be_transform_node(op1); + ir_node *op2 = get_Quot_right(node); + ir_node *new_op2 = be_transform_node(op2); + ir_mode *mode = get_irn_mode(node); + dbg_info *dbg = get_irn_dbg_info(node); assert(mode != mode_E && "IEEE Extended FP not supported"); - cg->have_fp = 1; - if (USE_FPA(cg->isa)) + env_cg->have_fp_insn = 1; + if (USE_FPA(env_cg->isa)) return new_rd_arm_fpaDiv(dbg, current_ir_graph, block, op1, op2, mode); - else if (USE_VFP(cg->isa)) { + else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); + panic("VFP not supported yet\n"); + } + else { + panic("Softfloat not supported yet\n"); + return NULL; } - assert(0 && "NYI"); - - return NULL; } #define GEN_INT_OP(op) \ -static ir_node *gen_ ## op(ir_node *irn, arm_code_gen_t *cg) { \ - ir_graph *irg = current_ir_graph; \ - ir_node *block = get_nodes_block(irn); \ - ir_node *op1 = get_ ## op ## _left(irn); \ - ir_node *op2 = get_ ## op ## _right(irn); \ - int v; \ + ir_node *block = be_transform_node(get_nodes_block(node)); \ + ir_node *op1 = get_ ## op ## _left(node); \ + ir_node *new_op1 = be_transform_node(op1); \ + ir_node *op2 = get_ ## op ## _right(node); \ + ir_node *new_op2 = be_transform_node(op2); \ + ir_graph *irg = current_ir_graph; \ + ir_mode *mode = get_irn_mode(node); \ + dbg_info *dbg = get_irn_dbg_info(node); \ + int v; \ arm_shift_modifier mod; \ - ir_mode *mode = get_irn_mode(irn); \ - dbg_info *dbg = get_irn_dbg_info(irn); \ \ - if (is_arm_Mov_i(op1)) \ - return new_rd_arm_ ## op ## _i(dbg, irg, block, op2, mode, get_arm_value(op1)); \ - if (is_arm_Mov_i(op2)) \ - return new_rd_arm_ ## op ## _i(dbg, irg, block, op1, mode, get_arm_value(op2)); \ + if (is_arm_Mov_i(new_op1)) \ + return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op2, mode, get_arm_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)); \ /* is the first a shifter */ \ - v = is_shifter_operand(op1, &mod); \ + v = is_shifter_operand(new_op1, &mod); \ if (v) { \ - op1 = get_irn_n(op1, 0); \ - return new_rd_arm_ ## op(dbg, irg, block, op2, op1, mode, mod, new_tarval_from_long(v, mode_Iu)); \ + 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)); \ } \ /* is the second a shifter */ \ - v = is_shifter_operand(op2, &mod); \ + v = is_shifter_operand(new_op2, &mod); \ if (v) { \ - op2 = get_irn_n(op2, 0); \ - return new_rd_arm_ ## op(dbg, irg, block, op1, op2, mode, mod, new_tarval_from_long(v, mode_Iu)); \ + 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)); \ } \ /* Normal op */ \ - return new_rd_arm_ ## op(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL); \ -} - + return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL) \ /** - * Creates an arm And. + * Creates an ARM And. * - * @param env The transformation environment * @return the created arm And node */ -static ir_node *gen_And(ir_node *irn, arm_code_gen_t *cg); -GEN_INT_OP(And) +static ir_node *gen_And(ir_node *node) { + GEN_INT_OP(And); +} /** - * Creates an arm Orr. + * Creates an ARM Orr. * * @param env The transformation environment * @return the created arm Or node */ -static ir_node *gen_Or(ir_node *irn, arm_code_gen_t *cg); -GEN_INT_OP(Or) +static ir_node *gen_Or(ir_node *node) { + GEN_INT_OP(Or); +} /** - * Creates an arm Eor. + * Creates an ARM Eor. * - * @param env The transformation environment * @return the created arm Eor node */ -static ir_node *gen_Eor(ir_node *irn, arm_code_gen_t *cg); -GEN_INT_OP(Eor) +static ir_node *gen_Eor(ir_node *node) { + GEN_INT_OP(Eor); +} /** - * Creates an arm Sub. + * Creates an ARM Sub. * - * @param env The transformation environment * @return the created arm Sub node */ -static ir_node *gen_Sub(ir_node *irn, arm_code_gen_t *cg) { - ir_node *block = get_nodes_block(irn); - ir_node *op1 = get_Sub_left(irn); - ir_node *op2 = get_Sub_right(irn); - int v; +static ir_node *gen_Sub(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *op1 = get_Sub_left(node); + ir_node *new_op1 = be_transform_node(op1); + ir_node *op2 = get_Sub_right(node); + ir_node *new_op2 = be_transform_node(node); + ir_mode *mode = get_irn_mode(node); + ir_graph *irg = current_ir_graph; + dbg_info *dbg = get_irn_dbg_info(node); + int v; arm_shift_modifier mod; - ir_mode *mode = get_irn_mode(irn); - ir_graph *irg = current_ir_graph; - dbg_info *dbg = get_irn_dbg_info(irn); if (mode_is_float(mode)) { - cg->have_fp = 1; - if (USE_FPA(cg->isa)) - return new_rd_arm_fpaSub(dbg, irg, block, op1, op2, mode); - else if (USE_VFP(cg->isa)) { + 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)) { assert(mode != mode_E && "IEEE Extended FP not supported"); + panic("VFP not supported yet\n"); + return NULL; + } + else { + panic("Softfloat not supported yet\n"); + return NULL; } - assert(0 && "NYI"); } - if (mode_is_numP(mode)) { - if (is_arm_Mov_i(op1)) - return new_rd_arm_Rsb_i(dbg, irg, block, op2, mode, get_arm_value(op1)); - if (is_arm_Mov_i(op2)) - return new_rd_arm_Sub_i(dbg, irg, block, op1, mode, get_arm_value(op2)); + else { + assert(mode_is_numP(mode) && "unknown mode for Sub"); + + if (is_arm_Mov_i(new_op1)) + return new_rd_arm_Rsb_i(dbg, irg, block, new_op2, mode, get_arm_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)); /* is the first a shifter */ - v = is_shifter_operand(op1, &mod); + v = is_shifter_operand(new_op1, &mod); if (v) { - op1 = get_irn_n(op1, 0); - return new_rd_arm_Rsb(dbg, irg, block, op2, op1, mode, mod, new_tarval_from_long(v, mode_Iu)); + 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)); } /* is the second a shifter */ - v = is_shifter_operand(op2, &mod); + v = is_shifter_operand(new_op2, &mod); if (v) { - op2 = get_irn_n(op2, 0); - return new_rd_arm_Sub(dbg, irg, block, op1, op2, mode, mod, new_tarval_from_long(v, mode_Iu)); + 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)); } /* normal sub */ - return new_rd_arm_Sub(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL); + return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL); } - assert(0 && "unknown mode for sub"); - return NULL; } /** - * Creates an arm Shl. + * Creates an ARM Shl. * - * @param env The transformation environment - * @return the created arm Shl node + * @return the created ARM Shl node */ -static ir_node *gen_Shl(ir_node *irn, arm_code_gen_t *cg) { - ir_node *result; - ir_node *block = get_nodes_block(irn); - ir_node *op1 = get_Shl_left(irn); - ir_node *op2 = get_Shl_right(irn); - ir_mode *mode = get_irn_mode(irn); - ir_graph *irg = current_ir_graph; - dbg_info *dbg = get_irn_dbg_info(irn); - - if (is_arm_Mov_i(op2)) { - result = new_rd_arm_Mov(dbg, irg, block, op1, mode, ARM_SHF_LSL, get_arm_value(op2)); - } else { - result = new_rd_arm_Shl(dbg, irg, block, op1, op2, mode); +static ir_node *gen_Shl(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *op1 = get_Shl_left(node); + ir_node *new_op1 = be_transform_node(op1); + ir_node *op2 = get_Shl_right(node); + ir_node *new_op2 = be_transform_node(op2); + ir_mode *mode = get_irn_mode(node); + 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 result; + return new_rd_arm_Shl(dbg, current_ir_graph, block, new_op1, new_op2, mode); } /** - * Creates an arm Shr. + * Creates an ARM Shr. * - * @param env The transformation environment - * @return the created arm Shr node + * @return the created ARM Shr node */ -static ir_node *gen_Shr(ir_node *irn, arm_code_gen_t *cg) { - ir_node *result; - ir_node *block = get_nodes_block(irn); - ir_node *op1 = get_Shr_left(irn); - ir_node *op2 = get_Shr_right(irn); - ir_mode *mode = get_irn_mode(irn); - ir_graph *irg = current_ir_graph; - dbg_info *dbg = get_irn_dbg_info(irn); - - if (is_arm_Mov_i(op2)) { - result = new_rd_arm_Mov(dbg, irg, block, op1, mode, ARM_SHF_LSR, get_arm_value(op2)); - } else { - result = new_rd_arm_Shr(dbg, irg, block, op1, op2, mode); +static ir_node *gen_Shr(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *op1 = get_Shr_left(node); + ir_node *new_op1 = be_transform_node(op1); + ir_node *op2 = get_Shr_right(node); + ir_node *new_op2 = be_transform_node(op2); + ir_mode *mode = get_irn_mode(node); + 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 result; + return new_rd_arm_Shr(dbg, current_ir_graph, block, new_op1, new_op2, mode); } /** - * Creates an arm Shrs. + * Creates an ARM Shrs. * - * @param env The transformation environment - * @return the created arm Shrs node + * @return the created ARM Shrs node */ -static ir_node *gen_Shrs(ir_node *irn, arm_code_gen_t *cg) { - ir_node *result; - ir_node *block = get_nodes_block(irn); - ir_node *op1 = get_Shrs_left(irn); - ir_node *op2 = get_Shrs_right(irn); - ir_mode *mode = get_irn_mode(irn); - dbg_info *dbg = get_irn_dbg_info(irn); - - if (is_arm_Mov_i(op2)) { - result = new_rd_arm_Mov(dbg, current_ir_graph, block, op1, mode, ARM_SHF_ASR, get_arm_value(op2)); - } else { - result = new_rd_arm_Shrs(dbg, current_ir_graph, block, op1, op2, mode); +static ir_node *gen_Shrs(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *op1 = get_Shrs_left(node); + ir_node *new_op1 = be_transform_node(op1); + ir_node *op2 = get_Shrs_right(node); + ir_node *new_op2 = be_transform_node(op2); + ir_mode *mode = get_irn_mode(node); + 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 result; + return new_rd_arm_Shrs(dbg, current_ir_graph, block, new_op1, new_op2, mode); } /** * Transforms a Not node. * - * @param env The transformation environment - * @return the created arm Not node + * @return the created ARM Not node */ -static ir_node *gen_Not(ir_node *irn, arm_code_gen_t *cg) { - ir_node *block = get_nodes_block(irn); - ir_node *op = get_Not_op(irn); - int v; +static ir_node *gen_Not(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(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; arm_shift_modifier mod = ARM_SHF_NONE; - tarval *tv = NULL; - dbg_info *dbg = get_irn_dbg_info(irn); + int v = is_shifter_operand(new_op, &mod); - v = is_shifter_operand(op, &mod); if (v) { - op = get_irn_n(op, 0); + 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, op, get_irn_mode(irn), mod, tv); + return new_rd_arm_Mvn(dbg, current_ir_graph, block, new_op, get_irn_mode(node), mod, tv); } /** * Transforms an Abs node. * * @param env The transformation environment - * @return the created arm Abs node + * @return the created ARM Abs node */ -static ir_node *gen_Abs(ir_node *irn, arm_code_gen_t *cg) { - ir_node *block = get_nodes_block(irn); - ir_node *op = get_Abs_op(irn); - ir_mode *mode = get_irn_mode(irn); - dbg_info *dbg = get_irn_dbg_info(irn); +static ir_node *gen_Abs(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *op = get_Not_op(node); + ir_node *new_op = be_transform_node(op); + dbg_info *dbg = get_irn_dbg_info(node); + ir_mode *mode = get_irn_mode(node); if (mode_is_float(mode)) { - cg->have_fp = 1; - if (USE_FPA(cg->isa)) - return new_rd_arm_fpaAbs(dbg, current_ir_graph, block, op, mode); - else if (USE_VFP(cg->isa)) { + env_cg->have_fp_insn = 1; + if (USE_FPA(env_cg->isa)) + 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"); + assert(0 && "NYI"); } - assert(0 && "NYI"); } - return new_rd_arm_Abs(dbg, current_ir_graph, block, op, mode); + return new_rd_arm_Abs(dbg, current_ir_graph, block, new_op, mode); } /** * Transforms a Minus node. * - * @param env The transformation environment - * @return the created arm Minus node + * @return the created ARM Minus node */ -static ir_node *gen_Minus(ir_node *irn, arm_code_gen_t *cg) { - ir_node *block = get_nodes_block(irn); - ir_node *op = get_Minus_op(irn); - ir_mode *mode = get_irn_mode(irn); - ir_graph *irg = current_ir_graph; - dbg_info *dbg = get_irn_dbg_info(irn); +static ir_node *gen_Minus(ir_node *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); + dbg_info *dbg = get_irn_dbg_info(node); + ir_mode *mode = get_irn_mode(node); if (mode_is_float(mode)) { - cg->have_fp = 1; - if (USE_FPA(cg->isa)) - return new_rd_arm_fpaMnv(dbg, irg, block, op, mode); - else if (USE_VFP(cg->isa)) { + env_cg->have_fp_insn = 1; + if (USE_FPA(env_cg->isa)) + return new_rd_arm_fpaMnv(dbg, current_ir_graph, block, op, mode); + else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); + assert(0 && "NYI"); } - assert(0 && "NYI"); } - return new_rd_arm_Rsb_i(dbg, irg, block, op, mode, get_mode_null(mode)); + return new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op, mode, get_mode_null(mode)); } /** * Transforms a Load. * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Load node - * @param mode node mode - * @return the created arm Load node + * @return the created ARM Load node */ -static ir_node *gen_Load(ir_node *irn, arm_code_gen_t *cg) { - ir_node *block = get_nodes_block(irn); - ir_mode *mode = get_Load_mode(irn); - ir_graph *irg = current_ir_graph; - dbg_info *dbg = get_irn_dbg_info(irn); +static ir_node *gen_Load(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *ptr = get_Load_ptr(node); + ir_node *new_ptr = be_transform_node(ptr); + ir_node *mem = get_Load_mem(node); + ir_node *new_mem = be_transform_node(mem); + ir_mode *mode = get_Load_mode(node); + ir_graph *irg = current_ir_graph; + dbg_info *dbg = get_irn_dbg_info(node); if (mode_is_float(mode)) { - cg->have_fp = 1; - if (USE_FPA(cg->isa)) - return new_rd_arm_fpaLdf(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn), - get_Load_mode(irn)); - else if (USE_VFP(cg->isa)) { + env_cg->have_fp_insn = 1; + if (USE_FPA(env_cg->isa)) + return 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"); + } + else { + panic("Softfloat not supported yet\n"); + return NULL; } - assert(0 && "NYI"); - } - if (mode == mode_Bu) { - return new_rd_arm_Loadb(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn)); - } - if (mode == mode_Bs) { - return new_rd_arm_Loadbs(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn)); - } - if (mode == mode_Hu) { - return new_rd_arm_Loadh(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn)); - } - if (mode == mode_Hs) { - return new_rd_arm_Loadhs(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn)); } - if (mode_is_reference(mode)) { - return new_rd_arm_Load(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn)); + else { + assert(mode_is_numP(mode) && "unsupported mode for Load"); + + if (mode_is_signed(mode)) { + /* sign extended loads */ + switch (get_mode_size_bits(mode)) { + case 8: + return new_rd_arm_Loadbs(dbg, irg, block, new_ptr, new_mem); + case 16: + return new_rd_arm_Loadhs(dbg, irg, block, new_ptr, new_mem); + case 32: + break; + default: + assert(!"mode size not supported"); + } + } else { + /* zero extended loads */ + switch (get_mode_size_bits(mode)) { + case 8: + return new_rd_arm_Loadb(dbg, irg, block, new_ptr, new_mem); + case 16: + return new_rd_arm_Loadh(dbg, irg, block, new_ptr, new_mem); + case 32: + break; + default: + assert(!"mode size not supported"); + } + } + return new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem); } - return new_rd_arm_Load(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn)); } /** * Transforms a Store. * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Store node - * @param mode node mode - * @return the created arm Store node + * @return the created ARM Store node */ -static ir_node *gen_Store(ir_node *irn, arm_code_gen_t *cg) { - ir_node *block = get_nodes_block(irn); - ir_mode *mode = get_irn_mode(get_Store_value(irn)); - ir_graph *irg = current_ir_graph; - dbg_info *dbg = get_irn_dbg_info(irn); +static ir_node *gen_Store(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *ptr = get_Store_ptr(node); + ir_node *new_ptr = be_transform_node(ptr); + ir_node *mem = get_Store_mem(node); + ir_node *new_mem = be_transform_node(mem); + ir_node *val = get_Store_value(node); + ir_node *new_val = be_transform_node(val); + ir_mode *mode = get_irn_mode(val); + ir_graph *irg = current_ir_graph; + dbg_info *dbg = get_irn_dbg_info(node); - assert(mode != mode_E && "IEEE Extended FP not supported"); if (mode_is_float(mode)) { - cg->have_fp = 1; - if (USE_FPA(cg->isa)) - return new_rd_arm_fpaStf(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), - get_Store_mem(irn), get_irn_mode(get_Store_value(irn))); - else if (USE_VFP(cg->isa)) { + env_cg->have_fp_insn = 1; + if (USE_FPA(env_cg->isa)) + return 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"); + assert(0 && "NYI"); } - assert(0 && "NYI"); } - if (mode == mode_Bu) { - return new_rd_arm_Storeb(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn)); - } - if (mode == mode_Bs) { - return new_rd_arm_Storebs(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn)); - } - if (mode == mode_Hu) { - return new_rd_arm_Storeh(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn)); - } - if (mode == mode_Hs) { - return new_rd_arm_Storehs(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn)); + + switch (get_mode_size_bits(mode)) { + case 8: + return new_rd_arm_Storeb(dbg, irg, block, new_ptr, new_val, new_mem); + case 16: + return new_rd_arm_Storeh(dbg, irg, block, new_ptr, new_val, new_mem); + default: + return new_rd_arm_Store(dbg, irg, block, new_ptr, new_val, new_mem); } - return new_rd_arm_Store(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn)); } - -static ir_node *gen_Cond(ir_node *irn, arm_code_gen_t *cg) { - ir_node *result = NULL; - ir_node *selector = get_Cond_selector(irn); - ir_node *block = get_nodes_block(irn); - ir_graph *irg = current_ir_graph; - dbg_info *dbg = get_irn_dbg_info(irn); - - if ( get_irn_mode(selector) == mode_b ) { - //CondJmp - ir_node *proj_node = get_Cond_selector(irn); - ir_node *cmp_node = get_Proj_pred(proj_node); - ir_node *op1 = get_Cmp_left(cmp_node); - ir_node *op2 = get_Cmp_right(cmp_node); - result = new_rd_arm_CondJmp(dbg, irg, block, op1, op2, get_Proj_proj(proj_node)); +/** + * Transforms a Cond. + * + * @return the created ARM Cond node + */ +static ir_node *gen_Cond(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *selector = get_Cond_selector(node); + ir_graph *irg = current_ir_graph; + dbg_info *dbg = get_irn_dbg_info(node); + ir_mode *mode = get_irn_mode(selector); + + if (mode == mode_b) { + /* CondJmp */ + 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)); } else { - //SwitchJmp - ir_node *op = get_irn_n(irn, 0); + /* SwitchJmp */ + ir_node *new_op = be_transform_node(selector); ir_node *const_graph; ir_node *sub; - ir_node *const_node; ir_node *proj; const ir_edge_t *edge; int min = INT_MAX; int max = INT_MIN; int translation; - int norm_max; - int norm_min; int pn; int n_projs; - ir_node **projs; - foreach_out_edge(irn, edge) { + foreach_out_edge(node, edge) { proj = get_edge_src_irn(edge); assert(is_Proj(proj) && "Only proj allowed at SwitchJmp"); @@ -873,14 +929,9 @@ static ir_node *gen_Cond(ir_node *irn, arm_code_gen_t *cg) { max = pn>max ? pn : max; } translation = min; - norm_max = max - translation; - norm_min = min - translation; + n_projs = max - translation + 1; - n_projs = norm_max + 1; - projs = xcalloc(n_projs , sizeof(ir_node*)); - - - foreach_out_edge(irn, edge) { + foreach_out_edge(node, edge) { proj = get_edge_src_irn(edge); assert(is_Proj(proj) && "Only proj allowed at SwitchJmp"); @@ -889,13 +940,10 @@ static ir_node *gen_Cond(ir_node *irn, arm_code_gen_t *cg) { } - const_node = new_rd_Const(dbg, irg, block, mode_Iu, new_tarval_from_long(translation, mode_Iu)); - const_graph = create_const_graph(cg->birg->abi, const_node, block); - sub = new_rd_arm_Sub(dbg, irg, block, op, const_graph, get_irn_mode(op), ARM_SHF_NONE, NULL); - result = new_rd_arm_SwitchJmp(dbg, irg, block, sub, - n_projs, get_Cond_defaultProj(irn)-translation); + const_graph = create_const_graph_value(env_cg->birg->abi, node, block, translation); + sub = new_rd_arm_Sub(dbg, irg, block, new_op, const_graph, mode, ARM_SHF_NONE, NULL); + return new_rd_arm_SwitchJmp(dbg, irg, block, sub, n_projs, get_Cond_defaultProj(node) - translation); } - return result; } /** @@ -923,47 +971,64 @@ static ident *get_sc_ident(ir_node *symc) { } /** - * Transforms a SymConst node. + * Transforms a Const node. + * + * @return The transformed ARM node. */ -static ir_node *gen_SymConst(ir_node *irn, arm_code_gen_t *cg) { - ir_node *block = get_nodes_block(irn); - ir_mode *mode = get_irn_mode(irn); - dbg_info *dbg = get_irn_dbg_info(irn); - return new_rd_arm_SymConst(dbg, current_ir_graph, block, mode, get_sc_ident(irn)); -} +static ir_node *gen_Const(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_mode *mode = get_irn_mode(node); + dbg_info *dbg = get_irn_dbg_info(node); + return create_const_graph(env_cg->birg->abi, node, block); +} /** - * Transforms a CopyB node. + * Transforms a SymConst node. * - * @param env The transformation environment - * @return The transformed node. + * @return The transformed ARM node. */ -static ir_node *gen_CopyB(ir_node *irn, arm_code_gen_t *cg) { - ir_node *res = NULL; - dbg_info *dbg = get_irn_dbg_info(irn); - ir_mode *mode = get_irn_mode(irn); - ir_node *src = get_CopyB_src(irn); - ir_node *dst = get_CopyB_dst(irn); - ir_node *mem = get_CopyB_mem(irn); - ir_node *block = get_nodes_block(irn); - int size = get_type_size_bytes(get_CopyB_type(irn)); - ir_graph *irg = current_ir_graph; - ir_node *src_copy; - ir_node *dst_copy; - - src_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, src); - dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, dst); - - res = new_rd_arm_CopyB( dbg, irg, block, dst_copy, src_copy, 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), mem, mode); - set_arm_value(res, new_tarval_from_long(size, mode_Iu)); - +static ir_node *gen_SymConst(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_mode *mode = get_irn_mode(node); + dbg_info *dbg = get_irn_dbg_info(node); + 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 */ return res; } - - +/** + * Transforms a CopyB node. + * + * @return The transformed ARM node. + */ +static ir_node *gen_CopyB(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *src = get_CopyB_src(node); + ir_node *new_src = be_transform_node(src); + ir_node *dst = get_CopyB_dst(node); + ir_node *new_dst = be_transform_node(dst); + ir_node *mem = get_CopyB_mem(node); + ir_node *new_mem = be_transform_node(mem); + ir_graph *irg = current_ir_graph; + dbg_info *dbg = get_irn_dbg_info(node); + int size = get_type_size_bytes(get_CopyB_type(node)); + ir_node *src_copy; + ir_node *dst_copy; + + src_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, new_src); + dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, new_dst); + + return new_rd_arm_CopyB(dbg, irg, block, dst_copy, src_copy, + 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), + mem, new_tarval_from_long(size, mode_Iu)); +} /******************************************** @@ -994,9 +1059,9 @@ static int get_sp_expand_offset(ir_node *inc_sp) { } #if 0 -static ir_node *gen_StackParam(ir_node *irn, arm_code_gen_t *cg) { +static ir_node *gen_StackParam(ir_node *irn) { + ir_node *block = be_transform_node(get_nodes_block(node)); ir_node *new_op = NULL; - ir_node *block = get_nodes_block(irn); ir_node *noreg = ia32_new_NoReg_gp(env->cg); ir_node *mem = new_rd_NoMem(env->irg); ir_node *ptr = get_irn_n(irn, 0); @@ -1036,33 +1101,34 @@ static ir_node *gen_StackParam(ir_node *irn, arm_code_gen_t *cg) { #endif /** - * Transforms a FrameAddr into an ia32 Add. + * Transforms a FrameAddr into an ARM Add. */ -static ir_node *gen_be_FrameAddr(ir_node *irn, arm_code_gen_t *cg) { - ir_node *block = get_nodes_block(irn); - ir_entity *ent = be_get_frame_entity(irn); - int offset = get_entity_offset(ent); - ir_node *op = get_irn_n(irn, 0); - ir_node *cnst; - ir_mode *mode = get_irn_mode(irn); - dbg_info *dbg = get_irn_dbg_info(irn); +static ir_node *gen_be_FrameAddr(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_entity *ent = be_get_frame_entity(node); + int offset = get_entity_offset(ent); + ir_node *op = be_get_FrameAddr_frame(node); + ir_node *new_op = be_transform_node(op); + ir_mode *mode = get_irn_mode(node); + dbg_info *dbg = get_irn_dbg_info(node); + ir_node *cnst; if (be_is_IncSP(op)) { /* BEWARE: we get an offset which is absolute from an offset that is relative. Both must be merged */ offset += get_sp_expand_offset(op); } - cnst = create_const_graph_value(cg->birg->abi, irn, block, (unsigned)offset); + cnst = create_const_graph_value(env_cg->birg->abi, node, block, (unsigned)offset); if (is_arm_Mov_i(cnst)) - return new_rd_arm_Add_i(dbg, current_ir_graph, block, op, mode, get_arm_value(cnst)); - return new_rd_arm_Add(dbg, current_ir_graph, block, op, cnst, mode, ARM_SHF_NONE, NULL); + 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); } #if 0 /** - * Transforms a FrameLoad into an ia32 Load. + * Transforms a FrameLoad into an ARM Load. */ -static ir_node *gen_FrameLoad(ir_node *irn, arm_code_gen_t *cg) { +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); @@ -1096,210 +1162,400 @@ static ir_node *gen_FrameLoad(ir_node *irn, arm_code_gen_t *cg) { } #endif -#if 0 /** - * Transforms a FrameStore into an ia32 Store. + * Transform a be_AddSP into an arm_AddSP. Eat up const sizes. */ -static ir_node *gen_FrameStore(ir_node *irn, arm_code_gen_t *cg) { - 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_node *val = get_irn_n(irn, 2); - ir_entity *ent = be_get_frame_entity(irn); - ir_mode *mode = get_irn_mode(val); +static ir_node *gen_be_AddSP(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *sz = get_irn_n(node, be_pos_AddSP_size); + ir_node *new_sz = be_transform_node(sz); + ir_node *sp = get_irn_n(node, be_pos_AddSP_old_sp); + ir_node *new_sp = be_transform_node(sp); + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + 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); - if (mode_is_float(mode)) { - if (USE_SSE2(env->cg)) - new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T); - else { - env->cg->used_x87 = 1; - new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T); + return new_op; +} + +/** + * Transform a be_SubSP into an arm_SubSP. Eat up const sizes. + */ +static ir_node *gen_be_SubSP(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *sz = get_irn_n(node, be_pos_SubSP_size); + ir_node *new_sz = be_transform_node(sz); + ir_node *sp = get_irn_n(node, be_pos_SubSP_old_sp); + ir_node *new_sp = be_transform_node(sp); + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *nomem = new_NoMem(); + ir_node *new_op; + + /* ARM stack grows in reverse direction, make an AddSP */ + new_op = new_rd_arm_AddSP(dbgi, irg, block, new_sp, new_sz, nomem); + + return new_op; +} + +/** + * Transform a be_Copy. + */ +static ir_node *gen_be_Copy(ir_node *node) { + ir_node *result = be_duplicate_node(node); + ir_mode *mode = get_irn_mode(result); + + if (mode_needs_gp_reg(mode)) { + set_irn_mode(node, mode_Iu); + } + + return result; +} + +/** + * Transform a Proj from a Load. + */ +static ir_node *gen_Proj_Load(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *load = get_Proj_pred(node); + ir_node *new_load = be_transform_node(load); + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + long proj = get_Proj_proj(node); + + /* renumber the proj */ + switch (get_arm_irn_opcode(new_load)) { + case iro_arm_Load: + case iro_arm_Loadb: + case iro_arm_Loadbs: + case iro_arm_Loadh: + case iro_arm_Loadhs: + /* handle all gp loads equal: they have the same proj numbers. */ + if (proj == pn_Load_res) { + return new_rd_Proj(dbgi, irg, block, new_load, mode_Iu, pn_arm_Load_res); + } else if (proj == pn_Load_M) { + return new_rd_Proj(dbgi, irg, block, new_load, mode_M, pn_arm_Load_M); + } + break; + case iro_arm_fpaLdf: + if (proj == pn_Load_res) { + ir_mode *mode = get_Load_mode(load); + return new_rd_Proj(dbgi, irg, block, new_load, mode, pn_arm_fpaLdf_res); + } else if (proj == pn_Load_M) { + return new_rd_Proj(dbgi, irg, block, new_load, mode_M, pn_arm_fpaLdf_M); } + break; + default: + break; } - else if (get_mode_size_bits(mode) == 8) { - new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T); + assert(0); + return new_rd_Unknown(irg, get_irn_mode(node)); +} + +/** + * Transform and renumber the Projs from a CopyB. + */ +static ir_node *gen_Proj_CopyB(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *pred = get_Proj_pred(node); + 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) { + case pn_CopyB_M_regular: + if (is_arm_CopyB(new_pred)) { + return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_CopyB_M); + } + break; + default: + break; } - else { - new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T); + assert(0); + return new_rd_Unknown(irg, mode); +} + +/** + * Transform and renumber the Projs from a Quot. + */ +static ir_node *gen_Proj_Quot(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *pred = get_Proj_pred(node); + 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) { + 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); + } + 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); + } + break; + default: + break; } + assert(0); + return new_rd_Unknown(irg, mode); +} - set_ia32_frame_ent(new_op, ent); - set_ia32_use_frame(new_op); +/** + * Transform the Projs of an AddSP. + */ +static ir_node *gen_Proj_be_AddSP(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *pred = get_Proj_pred(node); + ir_node *new_pred = be_transform_node(pred); + ir_graph *irg = current_ir_graph; + 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); + arch_set_irn_register(env_cg->arch_env, res, &arm_gp_regs[REG_SP]); + return res; + } else if (proj == pn_be_AddSP_M) { + return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_AddSP_M); + } - set_ia32_am_support(new_op, ia32_am_Dest); - set_ia32_op_type(new_op, ia32_AddrModeD); - set_ia32_am_flavour(new_op, ia32_B); - set_ia32_ls_mode(new_op, mode); + assert(0); + return new_rd_Unknown(irg, get_irn_mode(node)); +} - SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn)); +/** + * Transform the Projs of a SubSP. + */ +static ir_node *gen_Proj_be_SubSP(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *pred = get_Proj_pred(node); + ir_node *new_pred = be_transform_node(pred); + ir_graph *irg = current_ir_graph; + 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); + 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_op; + assert(0); + return new_rd_Unknown(irg, get_irn_mode(node)); } -#endif +/** + * Transform the Projs from a Cmp. + */ +static ir_node *gen_Proj_Cmp(ir_node *node) { + panic("Psi NYI\n"); +} -// static ir_node *gen_be_Copy(ir_node *irn, arm_code_gen_t *cg) { -// return new_rd_arm_Copy(env->dbg, env->irg, env->block, op, env->mode); -// } - -/********************************************************* - * _ _ _ - * (_) | | (_) - * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __ - * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__| - * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ | - * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_| - * - *********************************************************/ /** - * move constants out of the start block + * Transform the Thread Local Storage Proj. */ -void arm_move_consts(ir_node *node, void *env) { - arm_code_gen_t *cg = env; - int i; +static ir_node *gen_Proj_tls(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = NULL; - if (is_Block(node)) - return; + return new_rd_arm_LdTls(dbgi, irg, block, mode_Iu); +} - if (is_Phi(node)) { - for (i = get_irn_arity(node) - 1; i >= 0; --i) { - ir_node *pred = get_irn_n(node,i); - ir_opcode pred_code = get_irn_opcode(pred); - if (pred_code == iro_Const) { - ir_node *block = get_nodes_block(get_irn_n(get_nodes_block(node),i)); - ir_node *nn = gen_arm_Const(pred, block, cg); - set_irn_n(node, i, nn); - } - else if (pred_code == iro_SymConst) { - /* FIXME: in general, SymConst always require a load, so it - might be better to place them into the first real block - and let the spiller rematerialize them. */ - ident *id = get_sc_ident(pred); - ir_node *symconst_node; - symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred), - current_ir_graph, get_nodes_block(get_irn_n(get_nodes_block(node),i)), - get_irn_mode(pred), id); - set_irn_n(node, i, symconst_node); - } +/** + * Transform a Proj node. + */ +static ir_node *gen_Proj(ir_node *node) { + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *pred = get_Proj_pred(node); + long proj = get_Proj_proj(node); + + if (is_Store(pred) || be_is_FrameStore(pred)) { + if (proj == pn_Store_M) { + return be_transform_node(pred); + } else { + assert(0); + return new_r_Bad(irg); } - return; - } - for (i = 0; i < get_irn_arity(node); i++) { - ir_node *pred = get_irn_n(node,i); - ir_opcode pred_code = get_irn_opcode(pred); - - if (pred_code == iro_Const) { - ir_node *block = get_nodes_block(node); - ir_node *nn = gen_arm_Const(pred, block, cg); - set_irn_n(node, i, nn); - } else if (pred_code == iro_SymConst) { - ident *id = get_sc_ident(pred); - ir_node *symconst_node; - symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred), - current_ir_graph, get_nodes_block(node), - get_irn_mode(pred), id); - set_irn_n(node, i, symconst_node); + } else if (is_Load(pred) || be_is_FrameLoad(pred)) { + return gen_Proj_Load(node); + } else if (is_CopyB(pred)) { + return gen_Proj_CopyB(node); + } else if (is_Quot(pred)) { + return gen_Proj_Quot(node); + } else if (be_is_SubSP(pred)) { + return gen_Proj_be_SubSP(node); + } else if (be_is_AddSP(pred)) { + return gen_Proj_be_AddSP(node); + } else if (is_Cmp(pred)) { + return gen_Proj_Cmp(node); + } else if (get_irn_op(pred) == op_Start) { + 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)) { + return gen_Proj_tls(node); + } + } else { + ir_node *new_pred = be_transform_node(pred); + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_mode *mode = get_irn_mode(node); + if (mode_needs_gp_reg(mode)) { + ir_node *new_proj = new_r_Proj(irg, block, new_pred, mode_Iu, + get_Proj_proj(node)); +#ifdef DEBUG_libfirm + new_proj->node_nr = node->node_nr; +#endif + return new_proj; } } + + return be_duplicate_node(node); } /** - * Do not transform Proj, but check for floating point value. + * Change some phi modes */ -static ir_node *gen_Proj(ir_node *irn, arm_code_gen_t *cg) { - if (mode_is_float(get_irn_mode(irn))) - cg->have_fp = 1; - return NULL; +static ir_node *gen_Phi(ir_node *node) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_mode *mode = get_irn_mode(node); + ir_node *phi; + + if (mode_needs_gp_reg(mode)) { + /* we shouldn't have any 64bit stuff around anymore */ + assert(get_mode_size_bits(mode) <= 32); + /* all integer operations are on 32bit registers now */ + mode = mode_Iu; + } + + /* phi nodes allow loops, so we use the old arguments for now + * and fix this later */ + phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node), get_irn_in(node) + 1); + copy_node_attr(node, phi); + be_duplicate_deps(node, phi); + + be_set_transformed_node(node, phi); + be_enqueue_preds(node); + + return phi; } +/********************************************************* + * _ _ _ + * (_) | | (_) + * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __ + * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__| + * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ | + * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_| + * + *********************************************************/ /** * the BAD transformer. */ -static ir_node *bad_transform(ir_node *irn, arm_code_gen_t *cg) { +static ir_node *bad_transform(ir_node *irn) { panic("ARM backend: Not implemented: %+F\n", irn); - return NULL; + return irn; } -/** - * The type of a transform function. - */ -typedef ir_node *(transform_func)(ir_node *irn, arm_code_gen_t *cg); - /** * Set a node emitter. Make it a bit more type safe. */ -static INLINE void set_transformer(ir_op *op, transform_func arm_transform_func) { +static INLINE void set_transformer(ir_op *op, be_transform_func arm_transform_func) { op->ops.generic = (op_func)arm_transform_func; } /** * Enters all transform functions into the generic pointer */ -void arm_register_transformers(void) { +static void arm_register_transformers(void) { ir_op *op_Max, *op_Min, *op_Mulh; /* first clear the generic function pointer for all ops */ clear_irp_opcodes_generic_func(); -#define FIRM_OP(a) set_transformer(op_##a, gen_##a) -#define BAD(a) set_transformer(op_##a, bad_transform) +#define GEN(a) set_transformer(op_##a, gen_##a) +#define BAD(a) set_transformer(op_##a, bad_transform) #define IGN(a) - FIRM_OP(Add); // done - FIRM_OP(Mul); // done - FIRM_OP(Quot); // done - FIRM_OP(And); // done - FIRM_OP(Or); // done - FIRM_OP(Eor); // done - - FIRM_OP(Sub); // done - FIRM_OP(Shl); // done - FIRM_OP(Shr); // done - FIRM_OP(Shrs); // done - - FIRM_OP(Minus); // done - FIRM_OP(Not); // done - FIRM_OP(Abs); // done - - FIRM_OP(CopyB); // done - BAD(Const); /* should be handled by arm_move_const */ - FIRM_OP(Conv); // TODO: floating point conversions - - FIRM_OP(Load); // done - FIRM_OP(Store); // done - - FIRM_OP(SymConst); - FIRM_OP(Cond); // integer done - - /* TODO: implement these nodes */ - - IGN(Div); // intrinsic lowering - IGN(Mod); // intrinsic lowering - IGN(DivMod); // TODO: implement DivMod - - IGN(Mux); - IGN(Unknown); - IGN(Cmp); // done, implemented in cond - - /* You probably don't need to handle the following nodes */ - - IGN(Call); - FIRM_OP(Proj); - IGN(Alloc); + GEN(Add); + GEN(Sub); + GEN(Mul); + GEN(And); + GEN(Or); + GEN(Eor); + + GEN(Shl); + GEN(Shr); + GEN(Shrs); + BAD(Rot); /* unsupported yet */ + + GEN(Quot); + + /* should be lowered */ + BAD(Div); + BAD(Mod); + BAD(DivMod); + + GEN(Minus); + GEN(Conv); + GEN(Abs); + GEN(Not); + + GEN(Load); + GEN(Store); + GEN(Cond); + + BAD(ASM); /* unsupported yet */ + GEN(CopyB); + BAD(Mux); + BAD(Psi); /* unsupported yet */ + GEN(Proj); + GEN(Phi); IGN(Block); - IGN(Start); IGN(End); - IGN(NoMem); - IGN(Phi); - IGN(IJmp); - IGN(Jmp); // emitter done - IGN(Break); - IGN(Sync); + GEN(Const); + GEN(SymConst); + + /* we should never see these nodes */ BAD(Raise); BAD(Sel); BAD(InstOf); @@ -1307,58 +1563,58 @@ void arm_register_transformers(void) { BAD(Free); BAD(Tuple); BAD(Id); - BAD(Bad); + //BAD(Bad); BAD(Confirm); BAD(Filter); BAD(CallBegin); BAD(EndReg); BAD(EndExcept); - FIRM_OP(be_FrameAddr); + /* handle generic backend nodes */ + 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); + + /* set the register for all Unknown nodes */ + BAD(Unknown); op_Max = get_op_Max(); if (op_Max) - BAD(Max); + BAD(Max); /* unsupported yet */ op_Min = get_op_Min(); if (op_Min) - BAD(Min); + BAD(Min); /* unsupported yet */ op_Mulh = get_op_Mulh(); if (op_Mulh) - BAD(Mulh); + BAD(Mulh); /* unsupported yet */ #undef IGN -#undef FIRM_OP +#undef GEN #undef BAD } /** - * Transforms the given firm node (and maybe some other related nodes) - * into one or more assembler nodes. - * - * @param node the firm node - * @param env the debug module + * Pre-transform all unknown and noreg nodes. */ -void arm_transform_node(ir_node *node, void *env) { - arm_code_gen_t *cg = (arm_code_gen_t *)env; - ir_op *op = get_irn_op(node); - ir_node *asm_node = NULL; - - if (op == op_Block) - return; - - DBG((cg->mod, LEVEL_1, "check %+F ... ", node)); - - if (op->ops.generic) { - transform_func *transform = (transform_func *)op->ops.generic; +static void arm_pretransform_node(void *arch_cg) { + arm_code_gen_t *cg = arch_cg; +} - asm_node = (*transform)(node, cg); - } +/** + * Transform a Firm graph into an ARM graph. + */ +void arm_transform_graph(arm_code_gen_t *cg) { + arm_register_transformers(); + env_cg = cg; + be_transform_graph(cg->birg, /*arm_pretransform_node*/ NULL, cg); +} - if (asm_node) { - exchange(node, asm_node); - DB((cg->mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node)); - } - else { - DB((cg->mod, LEVEL_1, "ignored\n")); - } +void arm_init_transform(void) { + // FIRM_DBG_REGISTER(dbg, "firm.be.arm.transform"); } diff --git a/ir/be/arm/arm_transform.h b/ir/be/arm/arm_transform.h index 27efeaea8..ec4adeb23 100644 --- a/ir/be/arm/arm_transform.h +++ b/ir/be/arm/arm_transform.h @@ -26,9 +26,11 @@ #ifndef FIRM_BE_ARM_ARM_TRANSFORM_H #define FIRM_BE_ARM_ARM_TRANSFORM_H -void arm_move_consts(ir_node *node, void *env); +/** + * Transform a Firm graph into an ARM graph. + */ +void arm_transform_graph(arm_code_gen_t *cg); -void arm_register_transformers(void); -void arm_transform_node(ir_node *node, void *env); +void arm_init_transform(void); #endif diff --git a/ir/be/arm/bearch_arm.c b/ir/be/arm/bearch_arm.c index e0c62739f..15adde907 100644 --- a/ir/be/arm/bearch_arm.c +++ b/ir/be/arm/bearch_arm.c @@ -36,6 +36,7 @@ #include "irprintf.h" #include "ircons.h" #include "irgmod.h" +#include "irgopt.h" #include "lowering.h" #include "bitset.h" @@ -91,30 +92,22 @@ arch_register_req_t *arm_get_irn_reg_req(const void *self, const ir_node *node, FIRM_DBG_REGISTER(firm_dbg_module_t *mod, DEBUG_MODULE); if (is_Block(node) || mode == mode_X || mode == mode_M) { - DBG((mod, LEVEL_1, "ignoring mode_T, mode_M node %+F\n", node)); return arch_no_register_req; } if (mode == mode_T && pos < 0) { - DBG((mod, LEVEL_1, "ignoring request for OUT requirements at %+F\n", node)); return arch_no_register_req; } - DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, node)); - if (is_Proj(node)) { /* in case of a proj, we need to get the correct OUT slot */ /* of the node corresponding to the proj number */ - if (pos == -1) { - node_pos = arm_translate_proj_pos(node); - } - else { - node_pos = pos; + if(pos >= 0) { + return arch_no_register_req; } - node = skip_Proj_const(node); - - DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", node, node_pos)); + node_pos = (pos == -1) ? get_Proj_proj(node) : pos; + node = skip_Proj_const(node); } /* get requirements for our own nodes */ @@ -126,27 +119,23 @@ arch_register_req_t *arm_get_irn_reg_req(const void *self, const ir_node *node, req = get_arm_out_req(node, node_pos); } - DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", node, pos)); return req; } - /* unknown should be tranformed by now */ + /* unknown should be transformed by now */ assert(!is_Unknown(node)); - DB((mod, LEVEL_1, "returning NULL for %+F (node not supported)\n", node)); - return arch_no_register_req; } static void arm_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) { int pos = 0; - if (is_Proj(irn)) { - - if (get_irn_mode(irn) == mode_X) { - return; - } + if (get_irn_mode(irn) == mode_X) { + return; + } - pos = arm_translate_proj_pos(irn); + if (is_Proj(irn)) { + pos = get_Proj_proj(irn); irn = skip_Proj(irn); } @@ -172,7 +161,7 @@ static const arch_register_t *arm_get_irn_reg(const void *self, const ir_node *i return NULL; } - pos = arm_translate_proj_pos(irn); + pos = get_Proj_proj(irn); irn = skip_Proj_const(irn); } @@ -278,12 +267,21 @@ arm_irn_ops_t arm_irn_ops = { static void arm_prepare_graph(void *self) { arm_code_gen_t *cg = self; - arm_register_transformers(); - irg_walk_blkwise_graph(cg->irg, NULL, arm_move_consts, cg); - irg_walk_blkwise_graph(cg->irg, NULL, arm_transform_node, cg); -} + /* transform nodes into assembler instructions */ + arm_transform_graph(cg); + /* do local optimizations (mainly CSE) */ + local_optimize_graph(cg->irg); + if (cg->dump) + be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched); + + /* do code placement, to optimize the position of constants */ + place_code(cg->irg); + + if (cg->dump) + be_dump(cg->irg, "-place", dump_ir_block_graph_sched); +} /** * Called immediately before emit phase. @@ -525,6 +523,7 @@ static void arm_before_abi(void *self) { irg_walk_graph(cg->irg, NULL, handle_calls, cg); } +/* forward */ static void *arm_cg_init(be_irg_t *birg); static const arch_code_generator_if_t arm_code_gen_if = { @@ -553,14 +552,15 @@ static void *arm_cg_init(be_irg_t *birg) { } cg = xmalloc(sizeof(*cg)); - cg->impl = &arm_code_gen_if; - cg->irg = birg->irg; - cg->reg_set = new_set(arm_cmp_irn_reg_assoc, 1024); - cg->arch_env = birg->main_env->arch_env; - cg->isa = isa; - cg->birg = birg; - cg->int_tp = int_tp; - cg->have_fp = 0; + cg->impl = &arm_code_gen_if; + cg->irg = birg->irg; + cg->reg_set = new_set(arm_cmp_irn_reg_assoc, 1024); + cg->arch_env = birg->main_env->arch_env; + cg->isa = isa; + cg->birg = birg; + cg->int_tp = int_tp; + cg->have_fp_insn = 0; + cg->dump = (birg->main_env->options->dump_flags & DUMP_BE) ? 1 : 0; FIRM_DBG_REGISTER(cg->mod, "firm.be.arm.cg"); @@ -744,6 +744,7 @@ static void *arm_init(FILE *file_handle) { be_emit_init_env(&isa->emit, file_handle); arm_create_opcodes(); + arm_register_copy_attr_func(); arm_handle_intrinsics(); /* we mark referenced global entities, so we can only emit those which @@ -782,7 +783,7 @@ static int arm_get_n_reg_class(const void *self) { /* ARGH! is called BEFORE transform */ return 2; - return isa->cg->have_fp ? 2 : 1; + return isa->cg->have_fp_insn ? 2 : 1; } /** @@ -1174,6 +1175,8 @@ void be_init_arch_arm(void) lc_opt_add_table(arm_grp, arm_options); be_register_isa_if("arm", &arm_isa_if); + + arm_init_transform(); } BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_arm); diff --git a/ir/be/arm/bearch_arm_t.h b/ir/be/arm/bearch_arm_t.h index 0a3e73c11..33187a32e 100644 --- a/ir/be/arm/bearch_arm_t.h +++ b/ir/be/arm/bearch_arm_t.h @@ -116,10 +116,10 @@ enum arm_fp_architectures { }; /** Returns non-zero if FPA instructions should be issued. */ -#define USE_FPA(cg) ((cg)->fpu_arch & ARM_FPU_FPA_EXT_V1) +#define USE_FPA(isa) ((isa)->fpu_arch & ARM_FPU_FPA_EXT_V1) /** Returns non-zero if VFP instructions should be issued. */ -#define USE_VFP(cg) ((cg)->fpu_arch & ARM_FPU_VFP_EXT_V1xD) +#define USE_VFP(isa) ((isa)->fpu_arch & ARM_FPU_VFP_EXT_V1xD) /** Types of processor to generate code for. */ enum arm_processor_types { @@ -142,23 +142,24 @@ typedef struct _arm_code_gen_t { arm_isa_t *isa; /**< the isa instance */ be_irg_t *birg; /**< The be-irg (contains additional information about the irg) */ ir_type *int_tp; /**< the int type, needed for Call conversion */ - int have_fp; /**< non-zero, if fp hardware instructions are emitted */ + int have_fp_insn; /**< non-zero, if fp hardware instructions are emitted */ + char dump; /**< set to 1 if graphs should be dumped */ DEBUG_ONLY(firm_dbg_module_t *mod;) /**< debugging module */ } arm_code_gen_t; struct _arm_isa_t { - arch_isa_t arch_isa; /**< must be derived from arch_isa_t */ - int gen_reg_names; /**< use generic register names instead of SP, LR, PC */ - int fpu_arch; /**< FPU architecture */ - arm_code_gen_t *cg; /**< current code generator */ - be_emit_env_t emit; /**< An emitter environment for the GAS emitter. */ + arch_isa_t arch_isa; /**< must be derived from arch_isa_t */ + int gen_reg_names; /**< use generic register names instead of SP, LR, PC */ + int fpu_arch; /**< FPU architecture */ + arm_code_gen_t *cg; /**< current code generator */ + be_emit_env_t emit; /**< An emitter environment for the GAS emitter. */ }; typedef struct _arm_irn_ops_t { const arch_irn_ops_if_t *impl; - arm_code_gen_t *cg; + arm_code_gen_t *cg; } arm_irn_ops_t; -- 2.20.1