added new licence header
[libfirm] / ir / be / mips / mips_emitter.c
index bcd7a20..9f6e98c 100644 (file)
@@ -1,6 +1,24 @@
+/*
+ * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
+ *
+ * This file is part of libFirm.
+ *
+ * This file may be distributed and/or modified under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * Licensees holding valid libFirm Professional Edition licenses may use
+ * this file in accordance with the libFirm Commercial License.
+ * Agreement provided with the Software.
+ *
+ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ */
+
 /* mips emitter */
 /* $Id$ */
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -17,6 +35,7 @@
 #include "irargs_t.h"
 #include "irprog_t.h"
 #include "irouts.h"
+#include "error.h"
 
 #include "../besched.h"
 #include "../benode_t.h"
@@ -97,10 +116,10 @@ static const char *node_const_to_str(ir_node *n)
                assert(attr->tv != NULL);
                if(get_mode_sign(get_tarval_mode(attr->tv))) {
                        long val = get_tarval_long(attr->tv);
-                       snprintf(buf, sizeof(buf), "0x%04X", val & 0xffff);
+                       snprintf(buf, sizeof(buf), "0x%04lX", val & 0xffff);
                } else {
                        unsigned long val = get_tarval_long(attr->tv);
-                       snprintf(buf, sizeof(buf), "0x%04X", val & 0xffff);
+                       snprintf(buf, sizeof(buf), "0x%04lX", val & 0xffff);
                }
 
                return buf;
@@ -109,11 +128,11 @@ static const char *node_const_to_str(ir_node *n)
                if(get_mode_sign(get_tarval_mode(attr->tv))) {
                        long val = get_tarval_long(attr->tv);
                        val = (val & 0xffff0000) >> 16;
-                       snprintf(buf, sizeof(buf), "0x%04X", val & 0xffff);
+                       snprintf(buf, sizeof(buf), "0x%04lX", val & 0xffff);
                } else {
                        unsigned long val = get_tarval_long(attr->tv);
                        val = (val & 0xffff0000) >> 16;
-                       snprintf(buf, sizeof(buf), "0x%04X", val & 0xffff);
+                       snprintf(buf, sizeof(buf), "0x%04lX", val & 0xffff);
                }
 
                return buf;
@@ -332,40 +351,36 @@ static char *get_unique_label(char *buf, size_t buflen, const char *prefix)
        return buf;
 }
 
-
-/**
- * Returns the target label for a control flow node.
- */
-static char *get_cfop_target(const ir_node *irn, char *buf)
-{
-       ir_node *bl = get_irn_link(irn);
-
-       snprintf(buf, SNPRINTF_BUF_LEN, "BLOCK_%ld", get_irn_node_nr(bl));
-       return buf;
-}
-
 /************************************************************************/
-/* ABI Handling
+/* ABI Handling                                                         */
 /************************************************************************/
 
 static void mips_emit_IncSP(const ir_node *node, mips_emit_env_t *env)
 {
-       FILE *F = env->out;
-       int offset = be_get_IncSP_offset(node);
-       if(offset == 0)
+       FILE *F      = env->out;
+       int   offset = be_get_IncSP_offset(node);
+
+       if(offset == 0) {
+               fprintf(F, "\t\t\t\t # omitted IncSP with 0\n");
                return;
+       }
 
-       if(be_get_IncSP_direction(node) != be_stack_dir_expand)
-               offset = -offset;
+       if(offset > 0xffff || offset < -0xffff) {
+               panic("stackframe > 2^16 bytes not supported yet\n");
+       }
 
-       fprintf(F, "\taddi $sp, $sp, %d\n", -offset);
+       if(offset > 0) {
+               fprintf(F, "\tsubu $sp, $sp, %d\n", offset);
+       } else {
+               fprintf(F, "\taddu $sp, $sp, %d\n", -offset);
+       }
 }
 
 static void mips_emit_Copy(const ir_node *node, mips_emit_env_t *env)
 {
        FILE *F = env->out;
 
-       lc_efprintf(mips_get_arg_env(), F, "\tor %1D, $zero, %1S\t\t\t# copy\n", node, node);
+       lc_efprintf(mips_get_arg_env(), F, "\tmove %1D, %1S\t\t\t# copy\n", node, node);
 }
 
 static void mips_emit_Return(const ir_node* node, mips_emit_env_t *env)
@@ -385,9 +400,9 @@ static void mips_emit_nops(FILE* F, int n)
 
 static void mips_emit_Perm(const ir_node *node, mips_emit_env_t *env)
 {
-       FILEF = env->out;
+       FILE *F = env->out;
 
-       assert(/*get_irn_n_outs(node) == 2 &&*/ get_irn_arity(node) == 2);
+       assert(get_irn_arity(node) == 2);
 
        lc_efprintf(mips_get_arg_env(), F, "\txor %1S, %1S, %2S\t\t\t# perm\n", node, node, node);
        mips_emit_nops(F, 3);
@@ -399,23 +414,22 @@ static void mips_emit_Perm(const ir_node *node, mips_emit_env_t *env)
 
 static void mips_emit_Spill(const ir_node* node, mips_emit_env_t *env)
 {
-       FILE* F = env->out;
+       FILE      *F   = env->out;
+       ir_entity *ent = be_get_frame_entity(node);
 
-       ir_node* context = be_get_Spill_context(node);
-       entity* ent = be_get_spill_entity(node);
-       lc_efprintf(mips_get_arg_env(), F, "\tsw %1S, %d($fp)\n", node, get_entity_offset_bytes(ent));
+       lc_efprintf(mips_get_arg_env(), F, "\tsw %1S, %d($fp)\n", node, get_entity_offset(ent));
 }
 
 static void mips_emit_Reload(const ir_node* node, mips_emit_env_t *env)
 {
-       FILE* F = env->out;
+       FILE      *F   = env->out;
+       ir_entity *ent = be_get_frame_entity(node);
 
-       entity* ent = be_get_spill_entity(node);
-       lc_efprintf(mips_get_arg_env(), F, "\tlw %1D, %d($fp)\n", node, get_entity_offset_bytes(ent));
+       lc_efprintf(mips_get_arg_env(), F, "\tlw %1D, %d($fp)\n", node, get_entity_offset(ent));
 }
 
 /************************************************************************/
-/* Calls
+/* Calls                                                                */
 /************************************************************************/
 
 static void mips_emit_Call(ir_node *node, mips_emit_env_t *env)
@@ -424,7 +438,7 @@ static void mips_emit_Call(ir_node *node, mips_emit_env_t *env)
        const arch_register_t *callee_reg;
 
        // call to imediate value (label)
-       entity *callee = be_Call_get_entity(node);
+       ir_entity *callee = be_Call_get_entity(node);
        if(callee != NULL) {
                fprintf(F, "\tjal %s\n", get_entity_name(callee));
                return;
@@ -533,15 +547,11 @@ const char* mips_get_jumptbl_label(const ir_node* switchjmp)
  * possible otherwise a cmp-jmp cascade). Stolen from ia32
  */
 void emit_mips_jump_table(const ir_node *irn, FILE* F) {
-       int                 lastval, i, pn, do_jmp_tbl = 1;
-       jmp_tbl_t           tbl;
-       ir_node            *proj;
-       const ir_edge_t    *edge;
-       const lc_arg_env_t *env = mips_get_arg_env();
-       mips_attr_t *attr;
-       int i2;
-
-       attr = get_mips_attr(irn);
+       int              lastval, i, i2, pn;
+       jmp_tbl_t        tbl;
+       ir_node         *proj;
+       const ir_edge_t *edge;
+       mips_attr_t     *attr = get_mips_attr(irn);
 
        /* fill the table structure */
        tbl.label        = xmalloc(SNPRINTF_BUF_LEN);
@@ -646,6 +656,7 @@ void mips_register_emitters(void)
        op_be_RegParams->ops.generic = (op_func) mips_emit_nothing;
        op_be_Spill->ops.generic = (op_func) mips_emit_Spill;
        op_be_Reload->ops.generic = (op_func) mips_emit_Reload;
+       op_be_Perm->ops.generic = (op_func) mips_emit_Perm;
 
        op_Start->ops.generic = (op_func) mips_emit_nothing;
        op_Proj->ops.generic = (op_func) mips_emit_nothing;
@@ -662,10 +673,10 @@ typedef void (*emit_func) (const ir_node *, mips_emit_env_t *);
  */
 static void mips_emit_node(ir_node *irn, mips_emit_env_t* env)
 {
-       mips_emit_env_t        *emit_env = env;
-       firm_dbg_module_t *mod      = emit_env->mod;
+       mips_emit_env_t   *emit_env = env;
        FILE              *F        = emit_env->out;
        ir_op             *op       = get_irn_op(irn);
+       DEBUG_ONLY(firm_dbg_module_t *mod = emit_env->mod;)
 
        DBG((mod, LEVEL_1, "emitting code for %+F\n", irn));
 
@@ -712,8 +723,14 @@ void mips_emit_start(FILE *F, ir_graph *irg)
        irg_walk_graph(irg, NULL, dump_jump_tables, F);
 
        fprintf(F, "\n\n");
-       fprintf(F, "# Function Start of %s\n", irg_name);
+       fprintf(F, "\t.balign\t4\n");
+       fprintf(F, "\t.global\t%s\n", irg_name);
+       fprintf(F, "\t.set\tnomips16\n");
+       fprintf(F, "\t.ent\t%s\n", irg_name);
        fprintf(F, "%s:\n", irg_name);
+       fprintf(F, "\t.frame\t$fp, 24, $ra\n");
+       fprintf(F, "\t.mask\t0xc0000000, -4\n");
+       fprintf(F, "\t.fmask\t0x00000000, 0\n");
 }
 
 /**
@@ -722,9 +739,7 @@ void mips_emit_start(FILE *F, ir_graph *irg)
 void mips_emit_end(FILE *F, ir_graph *irg)
 {
        const char *irg_name = get_entity_name(get_irg_entity(irg));
-
-       fprintf(F, "# End of function %s we should never get here...\n", irg_name);
-       fprintf(F, "\tjal exit\n");
+       fprintf(F, "\t.end\t%s\n", irg_name);
 }
 
 /**
@@ -750,10 +765,10 @@ void mips_gen_routine(FILE *F, ir_graph *irg, const mips_code_gen_t *cg)
        mips_emit_env_t emit_env;
        int i, n;
 
-       emit_env.mod      = firm_dbg_register("firm.be.mips.emit");
        emit_env.out      = F;
        emit_env.arch_env = cg->arch_env;
        emit_env.cg       = cg;
+       FIRM_DBG_REGISTER(emit_env.mod, "firm.be.mips.emit");
 
        /* set the global arch_env (needed by print hooks) */
        arch_env = cg->arch_env;