simply use long long
[libfirm] / ir / be / arm / arm_emitter.c
index 3027b3b..7d1c215 100644 (file)
 #include "raw_bitset.h"
 #include "dbginfo.h"
 
-#include "../besched.h"
-#include "../beblocksched.h"
-#include "../beirg.h"
-#include "../begnuas.h"
-#include "../be_dbgout.h"
+#include "besched.h"
+#include "beblocksched.h"
+#include "beirg.h"
+#include "begnuas.h"
+#include "be_dbgout.h"
 
 #include "arm_emitter.h"
 #include "arm_optimize.h"
@@ -56,7 +56,7 @@
 #include "arm_map_regs.h"
 #include "gen_arm_regalloc_if.h"
 
-#include "../benode.h"
+#include "benode.h"
 
 #define SNPRINTF_BUF_LEN 128
 
@@ -65,85 +65,21 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 static set       *sym_or_tv;
 static arm_isa_t *isa;
 
-/**
- * Returns the register at in position pos.
- */
-static const arch_register_t *get_in_reg(const ir_node *irn, int pos)
-{
-       ir_node                *op;
-       const arch_register_t  *reg = NULL;
-
-       assert(get_irn_arity(irn) > pos && "Invalid IN position");
-
-       /* The out register of the operator at position pos is the
-          in register we need. */
-       op = get_irn_n(irn, pos);
-
-       reg = arch_get_irn_register(op);
-
-       assert(reg && "no in register found");
-
-       /* in case of a joker register: just return a valid register */
-       if (reg->type & arch_register_type_joker) {
-               const arch_register_req_t *req = arch_get_register_req(irn, pos);
-
-               if (arch_register_req_is(req, limited)) {
-                       /* in case of limited requirements: get the first allowed register */
-                       unsigned idx = rbitset_next(req->limited, 0, 1);
-                       reg = arch_register_for_index(req->cls, idx);
-               } else {
-                       /* otherwise get first register in class */
-                       reg = arch_register_for_index(req->cls, 0);
-               }
-       }
-       return reg;
-}
-
-
-/**
- * Returns the register at out position pos.
- */
-static const arch_register_t *get_out_reg(const ir_node *node, int pos)
+static void arm_emit_register(const arch_register_t *reg)
 {
-    ir_node                *proj;
-    const arch_register_t  *reg = NULL;
-
-    /* 1st case: irn is not of mode_T, so it has only                 */
-    /*           one OUT register -> good                             */
-    /* 2nd case: irn is of mode_T -> collect all Projs and ask the    */
-    /*           Proj with the corresponding projnum for the register */
-
-    if (get_irn_mode(node) != mode_T) {
-        reg = arch_get_irn_register(node);
-    } else if (is_arm_irn(node)) {
-        reg = arch_irn_get_register(node, pos);
-    } else {
-        const ir_edge_t *edge;
-
-        foreach_out_edge(node, edge) {
-            proj = get_edge_src_irn(edge);
-            assert(is_Proj(proj) && "non-Proj from mode_T node");
-            if (get_Proj_proj(proj) == pos) {
-                reg = arch_get_irn_register(proj);
-                break;
-            }
-        }
-    }
-
-    assert(reg && "no out register found");
-    return reg;
+       be_emit_string(arch_register_get_name(reg));
 }
 
 void arm_emit_source_register(const ir_node *node, int pos)
 {
-       const arch_register_t *reg = get_in_reg(node, pos);
-       be_emit_string(arch_register_get_name(reg));
+       const arch_register_t *reg = arch_get_irn_register_in(node, pos);
+       arm_emit_register(reg);
 }
 
 void arm_emit_dest_register(const ir_node *node, int pos)
 {
-       const arch_register_t *reg = get_out_reg(node, pos);
-       be_emit_string(arch_register_get_name(reg));
+       const arch_register_t *reg = arch_get_irn_register_out(node, pos);
+       arm_emit_register(reg);
 }
 
 void arm_emit_offset(const ir_node *node)
@@ -324,7 +260,6 @@ static void emit_arm_SymConst(const ir_node *irn)
 {
        const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(irn);
        sym_or_tv_t key, *entry;
-       unsigned label;
 
        key.u.entity  = attr->entity;
        key.is_entity = true;
@@ -334,7 +269,6 @@ static void emit_arm_SymConst(const ir_node *irn)
                /* allocate a label */
                entry->label = get_unique_label();
        }
-       label = entry->label;
 
        /* load the symbol indirect */
        be_emit_cstring("\tldr ");
@@ -363,7 +297,6 @@ static void emit_arm_FrameAddr(const ir_node *irn)
 static void emit_arm_fConst(const ir_node *irn)
 {
        sym_or_tv_t key, *entry;
-       unsigned label;
        ir_mode *mode;
 
        key.u.tv      = get_fConst_value(irn);
@@ -374,7 +307,6 @@ static void emit_arm_fConst(const ir_node *irn)
                /* allocate a label */
                entry->label = get_unique_label();
        }
-       label = entry->label;
 
        /* load the tarval indirect */
        mode = get_irn_mode(irn);
@@ -509,16 +441,16 @@ static void emit_arm_CopyB(const ir_node *irn)
        const arm_CopyB_attr_t *attr = get_arm_CopyB_attr_const(irn);
        unsigned size = attr->size;
 
-       const char *tgt = arch_register_get_name(get_in_reg(irn, 0));
-       const char *src = arch_register_get_name(get_in_reg(irn, 1));
+       const char *tgt = arch_register_get_name(arch_get_irn_register_in(irn, 0));
+       const char *src = arch_register_get_name(arch_get_irn_register_in(irn, 1));
        const char *t0, *t1, *t2, *t3;
 
        const arch_register_t *tmpregs[4];
 
        /* collect the temporary registers and sort them, we need ascending order */
-       tmpregs[0] = get_in_reg(irn, 2);
-       tmpregs[1] = get_in_reg(irn, 3);
-       tmpregs[2] = get_in_reg(irn, 4);
+       tmpregs[0] = arch_get_irn_register_in(irn, 2);
+       tmpregs[1] = arch_get_irn_register_in(irn, 3);
+       tmpregs[2] = arch_get_irn_register_in(irn, 4);
        tmpregs[3] = &arm_registers[REG_R12];
 
        /* Note: R12 is always the last register because the RA did not assign higher ones */
@@ -739,18 +671,18 @@ static void emit_be_IncSP(const ir_node *irn)
                be_emit_cstring(", ");
                arm_emit_source_register(irn, 0);
                be_emit_irprintf(", #0x%X", offs);
+               be_emit_finish_line_gas(irn);
        } else {
                /* omitted IncSP(0) */
                return;
        }
-       be_emit_finish_line_gas(irn);
 }
 
 static void emit_be_Copy(const ir_node *irn)
 {
        ir_mode *mode = get_irn_mode(irn);
 
-       if (get_in_reg(irn, 0) == get_out_reg(irn, 0)) {
+       if (arch_get_irn_register_in(irn, 0) == arch_get_irn_register_out(irn, 0)) {
                /* omitted Copy */
                return;
        }
@@ -847,8 +779,39 @@ static void emit_be_MemPerm(const ir_node *node)
        assert(sp_change == 0);
 }
 
+static void emit_be_Start(const ir_node *node)
+{
+       ir_graph *irg        = get_irn_irg(node);
+       ir_type  *frame_type = get_irg_frame_type(irg);
+       unsigned  size       = get_type_size_bytes(frame_type);
+
+       /* allocate stackframe */
+       if (size > 0) {
+               be_emit_cstring("\tsub ");
+               arm_emit_register(&arm_registers[REG_SP]);
+               be_emit_cstring(", ");
+               arm_emit_register(&arm_registers[REG_SP]);
+               be_emit_irprintf(", #0x%X", size);
+               be_emit_finish_line_gas(node);
+       }
+}
+
 static void emit_be_Return(const ir_node *node)
 {
+       ir_graph *irg        = get_irn_irg(node);
+       ir_type  *frame_type = get_irg_frame_type(irg);
+       unsigned  size       = get_type_size_bytes(frame_type);
+
+       /* deallocate stackframe */
+       if (size > 0) {
+               be_emit_cstring("\tadd ");
+               arm_emit_register(&arm_registers[REG_SP]);
+               be_emit_cstring(", ");
+               arm_emit_register(&arm_registers[REG_SP]);
+               be_emit_irprintf(", #0x%X", size);
+               be_emit_finish_line_gas(node);
+       }
+
        be_emit_cstring("\tmov pc, lr");
        be_emit_finish_line_gas(node);
 }
@@ -918,11 +881,11 @@ static void arm_register_emitters(void)
        set_emitter(op_be_MemPerm,    emit_be_MemPerm);
        set_emitter(op_be_Perm,       emit_be_Perm);
        set_emitter(op_be_Return,     emit_be_Return);
+       set_emitter(op_be_Start,      emit_be_Start);
 
        /* no need to emit anything for the following nodes */
        set_emitter(op_Phi,           emit_nothing);
        set_emitter(op_be_Keep,       emit_nothing);
-       set_emitter(op_be_Start,      emit_nothing);
 }
 
 /**
@@ -1098,16 +1061,17 @@ void arm_gen_routine(ir_graph *irg)
                                be_emit_write_line();
                        } else {
                                ir_tarval *tv = entry->u.tv;
-                               int i, size = get_mode_size_bytes(get_tarval_mode(tv));
-                               unsigned v;
+                               int vi;
+                               int size = get_mode_size_bytes(get_tarval_mode(tv));
 
                                /* beware: ARM fpa uses big endian format */
-                               for (i = ((size + 3) & ~3) - 4; i >= 0; i -= 4) {
+                               for (vi = ((size + 3) & ~3) - 4; vi >= 0; vi -= 4) {
                                        /* get 32 bits */
-                                       v =            get_tarval_sub_bits(tv, i+3);
-                                       v = (v << 8) | get_tarval_sub_bits(tv, i+2);
-                                       v = (v << 8) | get_tarval_sub_bits(tv, i+1);
-                                       v = (v << 8) | get_tarval_sub_bits(tv, i+0);
+                                       unsigned v;
+                                       v =            get_tarval_sub_bits(tv, vi+3);
+                                       v = (v << 8) | get_tarval_sub_bits(tv, vi+2);
+                                       v = (v << 8) | get_tarval_sub_bits(tv, vi+1);
+                                       v = (v << 8) | get_tarval_sub_bits(tv, vi+0);
                                        be_emit_irprintf("\t.word\t%u\n", v);
                                        be_emit_write_line();
                                }