added amd64 backend code (which doesn't do much yet).
authorRobin Redeker <rredeker@ipd.info.uni-karlsruhe.de>
Thu, 29 Apr 2010 11:02:22 +0000 (11:02 +0000)
committerRobin Redeker <rredeker@ipd.info.uni-karlsruhe.de>
Thu, 29 Apr 2010 11:02:22 +0000 (11:02 +0000)
[r27454]

ir/be/amd64/amd64_emitter.c [new file with mode: 0644]
ir/be/amd64/amd64_emitter.h [new file with mode: 0644]
ir/be/amd64/amd64_new_nodes.c [new file with mode: 0644]
ir/be/amd64/amd64_new_nodes.h [new file with mode: 0644]
ir/be/amd64/amd64_nodes_attr.h [new file with mode: 0644]
ir/be/amd64/amd64_spec.pl [new file with mode: 0644]
ir/be/amd64/amd64_transform.c [new file with mode: 0644]
ir/be/amd64/amd64_transform.h [new file with mode: 0644]
ir/be/amd64/bearch_amd64.c [new file with mode: 0644]
ir/be/amd64/bearch_amd64_t.h [new file with mode: 0644]
ir/be/bemodule.c

diff --git a/ir/be/amd64/amd64_emitter.c b/ir/be/amd64/amd64_emitter.c
new file mode 100644 (file)
index 0000000..294867d
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 1995-2008 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.
+ */
+
+/**
+ * @file
+ * @brief   emit assembler for a backend graph
+ * @version $Id: amd64_emitter.c 26746 2009-11-27 08:53:15Z matze $
+ */
+#include "config.h"
+
+#include <limits.h>
+
+#include "xmalloc.h"
+#include "tv.h"
+#include "iredges.h"
+#include "debug.h"
+#include "irgwalk.h"
+#include "irprintf.h"
+#include "irop_t.h"
+#include "irargs_t.h"
+#include "irprog.h"
+
+#include "../besched.h"
+
+#include "amd64_emitter.h"
+#include "gen_amd64_emitter.h"
+#include "amd64_nodes_attr.h"
+#include "amd64_new_nodes.h"
+
+#define SNPRINTF_BUF_LEN 128
+
+/**
+ * Returns the register at in position pos.
+ */
+static const arch_register_t *get_in_reg(const ir_node *node, int pos)
+{
+       ir_node                *op;
+       const arch_register_t  *reg = NULL;
+
+       assert(get_irn_arity(node) > pos && "Invalid IN position");
+
+       /* The out register of the operator at position pos is the
+          in register we need. */
+       op = get_irn_n(node, pos);
+
+       reg = arch_get_irn_register(op);
+
+       assert(reg && "no in register found");
+       return reg;
+}
+
+/**
+ * Returns the register at out position pos.
+ */
+static const arch_register_t *get_out_reg(const ir_node *node, int pos)
+{
+       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_amd64_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;
+}
+
+/*************************************************************
+ *             _       _    __   _          _
+ *            (_)     | |  / _| | |        | |
+ *  _ __  _ __ _ _ __ | |_| |_  | |__   ___| |_ __   ___ _ __
+ * | '_ \| '__| | '_ \| __|  _| | '_ \ / _ \ | '_ \ / _ \ '__|
+ * | |_) | |  | | | | | |_| |   | | | |  __/ | |_) |  __/ |
+ * | .__/|_|  |_|_| |_|\__|_|   |_| |_|\___|_| .__/ \___|_|
+ * | |                                       | |
+ * |_|                                       |_|
+ *************************************************************/
+
+void amd64_emit_immediate(const ir_node *node)
+{
+       (void) node;
+       /* TODO */
+}
+
+void amd64_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));
+}
+
+void amd64_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));
+}
+
+/**
+ * Returns the target label for a control flow node.
+ */
+static void amd64_emit_cfop_target(const ir_node *node)
+{
+       ir_node *block = get_irn_link(node);
+
+       be_emit_irprintf("BLOCK_%ld", get_irn_node_nr(block));
+}
+
+/***********************************************************************************
+ *                  _          __                                             _
+ *                 (_)        / _|                                           | |
+ *  _ __ ___   __ _ _ _ __   | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
+ * | '_ ` _ \ / _` | | '_ \  |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
+ * | | | | | | (_| | | | | | | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
+ * |_| |_| |_|\__,_|_|_| |_| |_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
+ *
+ ***********************************************************************************/
+
+/**
+ * Emits code for a unconditional jump.
+ */
+static void emit_Jmp(const ir_node *node)
+{
+       ir_node *block;
+
+       /* for now, the code works for scheduled and non-schedules blocks */
+       block = get_nodes_block(node);
+
+       be_emit_cstring("\tjmp ");
+       amd64_emit_cfop_target(node);
+       be_emit_finish_line_gas(node);
+}
+
+/**
+ * Enters the emitter functions for handled nodes into the generic
+ * pointer of an opcode.
+ */
+static void amd64_register_emitters(void)
+{
+
+/* some convienience macros to register additional emitter functions
+   (other than the generated ones) */
+#define amd64_EMIT(a) op_amd64_##a->ops.generic = (op_func)emit_amd64_##a
+#define EMIT(a)          op_##a->ops.generic = (op_func)emit_##a
+#define BE_EMIT(a)       op_be_##a->ops.generic = (op_func)emit_be_##a
+
+       /* first clear the generic function pointer for all ops */
+       clear_irp_opcodes_generic_func();
+
+       /* register all emitter functions defined in spec */
+       amd64_register_spec_emitters();
+
+       /* register addtional emitter functions if needed */
+       EMIT(Jmp);
+
+#undef amd64_EMIT
+#undef BE_EMIT
+#undef EMIT
+}
+
+typedef void (*emit_func_ptr) (const ir_node *);
+
+/**
+ * Emits code for a node.
+ */
+static void amd64_emit_node(const ir_node *node)
+{
+       ir_op               *op       = get_irn_op(node);
+
+       if (op->ops.generic) {
+               emit_func_ptr func = (emit_func_ptr) op->ops.generic;
+               (*func) (node);
+       } else {
+               ir_fprintf(stderr, "No emitter for node %+F\n", node);
+       }
+}
+
+/**
+ * Walks over the nodes in a block connected by scheduling edges
+ * and emits code for each node.
+ */
+static void amd64_gen_block(ir_node *block, void *data)
+{
+       ir_node *node;
+       (void) data;
+
+       if (! is_Block(block))
+               return;
+
+       be_emit_cstring("BLOCK_");
+       be_emit_irprintf("%ld:\n", get_irn_node_nr(block));
+       be_emit_write_line();
+
+       sched_foreach(block, node) {
+               amd64_emit_node(node);
+       }
+}
+
+
+/**
+ * Emits code for function start.
+ */
+static void amd64_emit_func_prolog(ir_graph *irg)
+{
+       const char *irg_name = get_entity_name(get_irg_entity(irg));
+
+       /* TODO: emit function header */
+       be_emit_cstring("/* start of ");
+       be_emit_string(irg_name);
+       be_emit_cstring(" */\n");
+       be_emit_write_line();
+}
+
+/**
+ * Emits code for function end
+ */
+static void amd64_emit_func_epilog(ir_graph *irg)
+{
+       const char *irg_name = get_entity_name(get_irg_entity(irg));
+
+       /* TODO: emit function end */
+       be_emit_cstring("/* end of ");
+       be_emit_string(irg_name);
+       be_emit_cstring(" */\n");
+       be_emit_write_line();
+}
+
+/**
+ * Sets labels for control flow nodes (jump target)
+ * TODO: Jump optimization
+ */
+static void amd64_gen_labels(ir_node *block, void *env)
+{
+       ir_node *pred;
+       int n = get_Block_n_cfgpreds(block);
+       (void) env;
+
+       for (n--; n >= 0; n--) {
+               pred = get_Block_cfgpred(block, n);
+               set_irn_link(pred, block);
+       }
+}
+
+/**
+ * Main driver
+ */
+void amd64_gen_routine(const amd64_code_gen_t *cg, ir_graph *irg)
+{
+       (void)cg;
+
+       /* register all emitter functions */
+       amd64_register_emitters();
+
+       amd64_emit_func_prolog(irg);
+       irg_block_walk_graph(irg, amd64_gen_labels, NULL, NULL);
+       irg_walk_blkwise_graph(irg, NULL, amd64_gen_block, NULL);
+       amd64_emit_func_epilog(irg);
+}
diff --git a/ir/be/amd64/amd64_emitter.h b/ir/be/amd64/amd64_emitter.h
new file mode 100644 (file)
index 0000000..7d21ea9
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 1995-2008 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.
+ */
+
+/**
+ * @file
+ * @brief    declarations for emit functions
+ * @version  $Id: amd64_emitter.h 26317 2009-08-05 10:53:46Z matze $
+ */
+#ifndef FIRM_BE_amd64_amd64_EMITTER_H
+#define FIRM_BE_amd64_amd64_EMITTER_H
+
+#include "irargs_t.h"
+#include "irnode.h"
+#include "debug.h"
+
+#include "../bearch.h"
+#include "../beemitter.h"
+
+#include "bearch_amd64_t.h"
+
+void amd64_emit_source_register(const ir_node *node, int pos);
+void amd64_emit_dest_register(const ir_node *node, int pos);
+void amd64_emit_immediate(const ir_node *node);
+
+int get_amd64_reg_nr(ir_node *irn, int posi, int in_out);
+const char *get_amd64_in_reg_name(ir_node *irn, int pos);
+
+
+void amd64_gen_routine(const amd64_code_gen_t *cg, ir_graph *irg);
+
+#endif
diff --git a/ir/be/amd64/amd64_new_nodes.c b/ir/be/amd64/amd64_new_nodes.c
new file mode 100644 (file)
index 0000000..a0d8592
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 1995-2008 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.
+ */
+
+/**
+ * @file
+ * @brief   This file implements the creation of the achitecture specific firm
+ *          opcodes and the coresponding node constructors for the amd64
+ *          assembler irg.
+ * @version $Id: amd64_new_nodes.c 26673 2009-10-01 16:43:13Z matze $
+ */
+#include "config.h"
+
+#include <stdlib.h>
+
+#include "irprog_t.h"
+#include "irgraph_t.h"
+#include "irnode_t.h"
+#include "irmode_t.h"
+#include "ircons_t.h"
+#include "iropt_t.h"
+#include "irop.h"
+#include "irvrfy_t.h"
+#include "irprintf.h"
+#include "xmalloc.h"
+
+#include "../bearch.h"
+
+#include "amd64_nodes_attr.h"
+#include "amd64_new_nodes.h"
+#include "gen_amd64_regalloc_if.h"
+
+/**
+ * Dumper interface for dumping amd64 nodes in vcg.
+ * @param n        the node to dump
+ * @param F        the output file
+ * @param reason   indicates which kind of information should be dumped
+ * @return 0 on success or != 0 on failure
+ */
+static int amd64_dump_node(ir_node *n, FILE *F, dump_reason_t reason)
+{
+       ir_mode *mode = NULL;
+
+       switch (reason) {
+       case dump_node_opcode_txt:
+               fprintf(F, "%s", get_irn_opname(n));
+               break;
+
+       case dump_node_mode_txt:
+               mode = get_irn_mode(n);
+
+               if (mode) {
+                       fprintf(F, "[%s]", get_mode_name(mode));
+               } else {
+                       fprintf(F, "[?NOMODE?]");
+               }
+               break;
+
+       case dump_node_nodeattr_txt:
+
+               /* TODO: dump some attributes which should show up */
+               /* in node name in dump (e.g. consts or the like)  */
+
+               break;
+
+       case dump_node_info_txt:
+               arch_dump_reqs_and_registers(F, n);
+               break;
+       }
+
+       return 0;
+}
+
+const amd64_attr_t *get_amd64_attr_const(const ir_node *node)
+{
+       assert(is_amd64_irn(node) && "need amd64 node to get attributes");
+       return (const amd64_attr_t *)get_irn_generic_attr_const(node);
+}
+
+amd64_attr_t *get_amd64_attr(ir_node *node)
+{
+       assert(is_amd64_irn(node) && "need amd64 node to get attributes");
+       return (amd64_attr_t *)get_irn_generic_attr(node);
+}
+
+static const amd64_immediate_attr_t *get_amd64_immediate_attr_const(const ir_node *node)
+{
+       const amd64_attr_t           *attr     = get_amd64_attr_const(node);
+       const amd64_immediate_attr_t *imm_attr = CONST_CAST_AMD64_ATTR(amd64_immediate_attr_t, attr);
+
+       return imm_attr;
+}
+
+/*
+static amd64_immediate_attr_t *get_amd64_immediate_attr(ir_node *node)
+{
+       amd64_attr_t           *attr     = get_amd64_attr(node);
+       amd64_immediate_attr_t *imm_attr = CAST_AMD64_ATTR(amd64_immediate_attr_t, attr);
+
+       return imm_attr;
+}
+*/
+
+
+/**
+ * Returns the argument register requirements of a amd64 node.
+ */
+const arch_register_req_t **get_amd64_in_req_all(const ir_node *node)
+{
+       const amd64_attr_t *attr = get_amd64_attr_const(node);
+       return attr->in_req;
+}
+
+/**
+ * Returns the argument register requirement at position pos of an amd64 node.
+ */
+const arch_register_req_t *get_amd64_in_req(const ir_node *node, int pos)
+{
+       const amd64_attr_t *attr = get_amd64_attr_const(node);
+       return attr->in_req[pos];
+}
+
+/**
+ * Sets the IN register requirements at position pos.
+ */
+void set_amd64_req_in(ir_node *node, const arch_register_req_t *req, int pos)
+{
+       amd64_attr_t *attr  = get_amd64_attr(node);
+       attr->in_req[pos] = req;
+}
+
+/**
+ * Initializes the nodes attributes.
+ */
+static void init_amd64_attributes(ir_node *node, arch_irn_flags_t flags,
+                              const arch_register_req_t **in_reqs,
+                              const be_execution_unit_t ***execution_units,
+                              int n_res)
+{
+       ir_graph        *irg  = get_irn_irg(node);
+       struct obstack  *obst = get_irg_obstack(irg);
+       amd64_attr_t *attr = get_amd64_attr(node);
+       backend_info_t  *info;
+       (void) execution_units;
+
+       arch_irn_set_flags(node, flags);
+       attr->in_req  = in_reqs;
+
+       info            = be_get_info(node);
+       info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
+       memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
+}
+
+/**
+ * Initialize immediate attributes.
+ */
+static void init_amd64_immediate_attributes(ir_node *node, unsigned imm_value)
+{
+       amd64_immediate_attr_t *attr = get_irn_generic_attr (node);
+       attr->imm_value = imm_value;
+}
+
+/** Compare node attributes for Immediates. */
+static int cmp_amd64_attr_immediate(ir_node *a, ir_node *b)
+{
+       const amd64_immediate_attr_t *attr_a = get_amd64_immediate_attr_const(a);
+       const amd64_immediate_attr_t *attr_b = get_amd64_immediate_attr_const(b);
+
+       if (attr_a->imm_value != attr_b->imm_value)
+               return 1;
+
+       return 0;
+}
+
+static int cmp_amd64_attr(ir_node *a, ir_node *b)
+{
+       const amd64_attr_t *attr_a = get_amd64_attr_const(a);
+       const amd64_attr_t *attr_b = get_amd64_attr_const(b);
+       (void) attr_a;
+       (void) attr_b;
+
+       return 0;
+}
+
+/* Include the generated constructor functions */
+#include "gen_amd64_new_nodes.c.inl"
diff --git a/ir/be/amd64/amd64_new_nodes.h b/ir/be/amd64/amd64_new_nodes.h
new file mode 100644 (file)
index 0000000..901e09e
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 1995-2008 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.
+ */
+
+/**
+ * @file
+ * @brief   Function prototypes for the assembler ir node constructors.
+ * @version $Id: amd64_new_nodes.h 26549 2009-09-18 17:48:23Z matze $
+ */
+#ifndef FIRM_BE_TEMPALTE_amd64_NEW_NODES_H
+#define FIRM_BE_amd64_amd64_NEW_NODES_H
+
+#include "amd64_nodes_attr.h"
+
+/***************************************************************************************************
+ *        _   _                   _       __        _                    _   _               _
+ *       | | | |                 | |     / /       | |                  | | | |             | |
+ *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
+ *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
+ * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
+ *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
+ *                                        __/ |
+ *                                       |___/
+ ***************************************************************************************************/
+
+/**
+ * Returns the attributes of an amd64 node.
+ */
+amd64_attr_t *get_amd64_attr(ir_node *node);
+
+const amd64_attr_t *get_amd64_attr_const(const ir_node *node);
+
+/**
+ * Returns the argument register requirements of an amd64 node.
+ */
+const arch_register_req_t **get_amd64_in_req_all(const ir_node *node);
+
+/**
+ * Returns the argument register requirements of an amd64 node.
+ */
+const arch_register_req_t *get_amd64_in_req(const ir_node *node, int pos);
+
+/**
+ * Sets the IN register requirements at position pos.
+ */
+void set_amd64_req_in(ir_node *node, const arch_register_req_t *req, int pos);
+
+/* Include the generated headers */
+#include "gen_amd64_new_nodes.h"
+
+#endif
diff --git a/ir/be/amd64/amd64_nodes_attr.h b/ir/be/amd64/amd64_nodes_attr.h
new file mode 100644 (file)
index 0000000..a74b8aa
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 1995-2008 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.
+ */
+
+/**
+ * @file
+ * @brief   attributes attached to all amd64 nodes
+ * @version $Id: amd64_nodes_attr.h 26317 2009-08-05 10:53:46Z matze $
+ */
+#ifndef FIRM_BE_amd64_amd64_NODES_ATTR_H
+#define FIRM_BE_amd64_amd64_NODES_ATTR_H
+
+#include "../bearch.h"
+
+typedef struct amd64_attr_t            amd64_attr_t;
+typedef struct amd64_immediate_attr_t  amd64_immediate_attr_t;
+
+struct amd64_attr_t
+{
+       const arch_register_req_t **in_req;  /**< register requirements for arguments */
+       const arch_register_req_t **out_req; /**< register requirements for results */
+};
+
+struct amd64_immediate_attr_t
+{
+       unsigned imm_value; /**< the immediate value to load */
+};
+
+#define CAST_AMD64_ATTR(type,ptr)        ((type *)(ptr))
+#define CONST_CAST_AMD64_ATTR(type,ptr)  ((const type *)(ptr))
+
+#endif
diff --git a/ir/be/amd64/amd64_spec.pl b/ir/be/amd64/amd64_spec.pl
new file mode 100644 (file)
index 0000000..305218b
--- /dev/null
@@ -0,0 +1,188 @@
+# Creation: 2006/02/13
+# $Id: amd64_spec.pl 26673 2009-10-01 16:43:13Z matze $
+
+# the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
+
+$arch = "amd64";
+
+# The node description is done as a perl hash initializer with the
+# following structure:
+#
+# %nodes = (
+#
+# <op-name> => {
+#   op_flags  => "N|L|C|X|I|F|Y|H|c|K",                 # optional
+#   irn_flags => "R|N|I"                                # optional
+#   arity     => "0|1|2|3 ... |variable|dynamic|any",   # optional
+#   state     => "floats|pinned|mem_pinned|exc_pinned", # optional
+#   args      => [
+#                    { type => "type 1", name => "name 1" },
+#                    { type => "type 2", name => "name 2" },
+#                    ...
+#                  ],
+#   comment   => "any comment for constructor",  # optional
+#   reg_req   => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
+#   cmp_attr  => "c source code for comparing node attributes", # optional
+#   outs      => { "out1", "out2" },# optional, creates pn_op_out1, ... consts
+#   ins       => { "in1", "in2" },  # optional, creates n_op_in1, ... consts
+#   mode      => "mode_Iu",         # optional, predefines the mode
+#   emit      => "emit code with templates",   # optional for virtual nodes
+#   attr      => "additional attribute arguments for constructor", # optional
+#   init_attr => "emit attribute initialization template",         # optional
+#   rd_constructor => "c source code which constructs an ir_node", # optional
+#   hash_func => "name of the hash function for this operation",   # optional, get the default hash function else
+#   latency   => "latency of this operation (can be float)"        # optional
+#   attr_type => "name of the attribute struct",                   # optional
+# },
+#
+# ... # (all nodes you need to describe)
+#
+# ); # close the %nodes initializer
+
+# op_flags: flags for the operation, OPTIONAL (default is "N")
+# the op_flags correspond to the firm irop_flags:
+#   N   irop_flag_none
+#   L   irop_flag_labeled
+#   C   irop_flag_commutative
+#   X   irop_flag_cfopcode
+#   I   irop_flag_ip_cfopcode
+#   F   irop_flag_fragile
+#   Y   irop_flag_forking
+#   H   irop_flag_highlevel
+#   c   irop_flag_constlike
+#   K   irop_flag_keep
+#
+# irn_flags: special node flags, OPTIONAL (default is 0)
+# following irn_flags are supported:
+#   R   rematerializeable
+#   N   not spillable
+#   I   ignore for register allocation
+#
+# state: state of the operation, OPTIONAL (default is "floats")
+#
+# arity: arity of the operation, MUST NOT BE OMITTED
+#
+# args:  the OPTIONAL arguments of the node constructor (debug, irg and block
+#        are always the first 3 arguments and are always autmatically
+#        created)
+#        If this key is missing the following arguments will be created:
+#        for i = 1 .. arity: ir_node *op_i
+#        ir_mode *mode
+#
+# outs:  if a node defines more than one output, the names of the projections
+#        nodes having outs having automatically the mode mode_T
+#
+# comment: OPTIONAL comment for the node constructor
+#
+# rd_constructor: for every operation there will be a
+#      new_rd_<arch>_<op-name> function with the arguments from above
+#      which creates the ir_node corresponding to the defined operation
+#      you can either put the complete source code of this function here
+#
+#      This key is OPTIONAL. If omitted, the following constructor will
+#      be created:
+#      if (!op_<arch>_<op-name>) assert(0);
+#      for i = 1 to arity
+#         set in[i] = op_i
+#      done
+#      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
+#      return res
+#
+# NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
+
+# register types:
+#   0 - no special type
+#   1 - caller save (register must be saved by the caller of a function)
+#   2 - callee save (register must be saved by the called function)
+#   4 - ignore (do not assign this register)
+# NOTE: Last entry of each class is the largest Firm-Mode a register can hold
+%reg_classes = (
+       gp => [
+               { name => "rax", type => 1 },
+               { name => "rcx", type => 1 },
+               { name => "rdx", type => 1 },
+               { name => "rbx", type => 2 },
+               { name => "rsi", type => 2 },
+               { name => "rdi", type => 2 },
+               { name => "rbp", type => 2 },
+               { name => "rsp", type => 4 }, # stackpointer?
+               { name => "r8",  type => 1 },
+               { name => "r9",  type => 1 },
+               { name => "r10", type => 1 },
+               { name => "r11", type => 1 },
+               { name => "r12", type => 2 },
+               { name => "r13", type => 2 },
+               { name => "r14", type => 2 },
+               { name => "r15", type => 2 },
+               { mode => "mode_Iu" }
+       ],
+       fp => [
+               { name => "xmm0", type => 1 },
+               { name => "xmm1", type => 1 },
+               { name => "xmm2", type => 1 },
+               { name => "xmm3", type => 1 },
+               { name => "xmm4", type => 1 },
+               { name => "xmm5", type => 1 },
+               { name => "xmm6", type => 1 },
+               { name => "xmm7", type => 1 },
+               { name => "xmm8", type => 1 },
+               { name => "xmm9", type => 1 },
+               { name => "xmm10", type => 1 },
+               { name => "xmm11", type => 1 },
+               { name => "xmm12", type => 1 },
+               { name => "xmm13", type => 1 },
+               { name => "xmm14", type => 1 },
+               { name => "xmm15", type => 1 },
+               { mode => "mode_D" }
+       ]
+);
+
+%emit_templates = (
+       S1 => "${arch}_emit_source_register(node, 0);",
+       S2 => "${arch}_emit_source_register(node, 1);",
+       S3 => "${arch}_emit_source_register(node, 2);",
+       S4 => "${arch}_emit_source_register(node, 3);",
+       S5 => "${arch}_emit_source_register(node, 4);",
+       S6 => "${arch}_emit_source_register(node, 5);",
+       D1 => "${arch}_emit_dest_register(node, 0);",
+       D2 => "${arch}_emit_dest_register(node, 1);",
+       D3 => "${arch}_emit_dest_register(node, 2);",
+       D4 => "${arch}_emit_dest_register(node, 3);",
+       D5 => "${arch}_emit_dest_register(node, 4);",
+       D6 => "${arch}_emit_dest_register(node, 5);",
+       C  => "${arch}_emit_immediate(node);"
+);
+
+%init_attr = (
+       amd64_attr_t           =>
+                "\tinit_amd64_attributes(res, flags, in_reqs, exec_units, n_res);",
+       amd64_immediate_attr_t =>
+               "\tinit_amd64_attributes(res, flags, in_reqs, exec_units, n_res);"
+               . "\tinit_amd64_immediate_attributes(res, imm_value);",
+);
+
+%compare_attr = (
+       amd64_attr_t           => "cmp_amd64_attr",
+       amd64_immediate_attr_t => "cmp_amd64_attr_immediate",
+);
+
+%nodes = (
+Push => {
+       state     => "exc_pinned",
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "rsp" ], out => [ "rsp:I|S", "none" ] },
+       ins       => [ "base", "index", "mem", "val", "stack" ],
+       emit      => '. push %S1',
+       outs      => [ "stack", "M" ],
+       am        => "source,unary",
+       latency   => 2,
+#      units     => [ "GP" ],
+},
+Immediate => {
+       op_flags  => "c",
+       attr      => "unsigned imm_value",
+       attr_type => "amd64_immediate_attr_t",
+       reg_req   => { out => [ "gp" ] },
+       emit      => '. movq %C, %D1',
+       mode      => "mode_Iu",
+},
+);
diff --git a/ir/be/amd64/amd64_transform.c b/ir/be/amd64/amd64_transform.c
new file mode 100644 (file)
index 0000000..bbbd070
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 1995-2008 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.
+ */
+
+/**
+ * @file
+ * @brief   code selection (transform FIRM into amd64 FIRM)
+ * @version $Id: amd64_transform.c 26673 2009-10-01 16:43:13Z matze $
+ */
+#include "config.h"
+
+#include "irnode_t.h"
+#include "irgraph_t.h"
+#include "irmode_t.h"
+#include "irgmod.h"
+#include "iredges.h"
+#include "irvrfy.h"
+#include "ircons.h"
+#include "iropt_t.h"
+#include "debug.h"
+
+#include "../benode.h"
+#include "../betranshlp.h"
+#include "bearch_amd64_t.h"
+
+#include "amd64_nodes_attr.h"
+#include "amd64_transform.h"
+#include "amd64_new_nodes.h"
+
+#include "gen_amd64_regalloc_if.h"
+
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
+
+/** holds the current code generator during transformation */
+static amd64_code_gen_t *env_cg;
+
+/* Some support functions: */
+
+/**
+ * Create a DAG constructing a given Const.
+ *
+ * @param irn  a Firm const
+ */
+static ir_node *create_const_graph(ir_node *irn, ir_node *block)
+{
+       tarval  *tv    = get_Const_tarval(irn);
+       ir_mode *mode  = get_tarval_mode(tv);
+       dbg_info *dbgi = get_irn_dbg_info(irn);
+       unsigned value;
+
+       if (mode_is_reference(mode)) {
+               /* AMD64 is 64bit, 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);
+       printf ("TEST GENERATE %d\n", value);
+
+       return new_bd_amd64_Immediate(dbgi, block, value);
+}
+
+/* Op transformers: */
+
+/**
+ * Transforms a Const node.
+ *
+ * @return The transformed ARM node.
+ */
+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);
+       (void) mode;
+
+       ir_node *res = create_const_graph(node, block);
+       be_dep_on_frame (res);
+
+       return res;
+}
+
+/* Boilerplate code for transformation: */
+
+static void amd64_pretransform_node(void)
+{
+       amd64_code_gen_t *cg = env_cg;
+       (void) cg;
+}
+
+static void set_transformer(ir_op *op, be_transform_func amd64_transform_func)
+{
+       op->ops.generic = (op_func)amd64_transform_func;
+}
+
+static void amd64_register_transformers(void)
+{
+       clear_irp_opcodes_generic_func();
+
+       set_transformer(op_Const,        gen_Const);
+}
+
+
+void amd64_transform_graph(amd64_code_gen_t *cg)
+{
+       amd64_register_transformers();
+       env_cg = cg;
+       be_transform_graph(cg->birg, amd64_pretransform_node);
+}
+
+void amd64_init_transform(void)
+{
+       FIRM_DBG_REGISTER(dbg, "firm.be.amd64.transform");
+}
diff --git a/ir/be/amd64/amd64_transform.h b/ir/be/amd64/amd64_transform.h
new file mode 100644 (file)
index 0000000..baaff96
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 1995-2008 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.
+ */
+
+/**
+ * @file
+ * @brief   declaration for the transform function (code selection)
+ * @version $Id: amd64_transform.h 26542 2009-09-18 09:18:32Z matze $
+ */
+#ifndef FIRM_BE_amd64_amd64_TRANSFORM_H
+#define FIRM_BE_amd64_amd64_TRANSFORM_H
+
+void amd64_init_transform(void);
+
+void amd64_transform_graph(amd64_code_gen_t *cg);
+
+#endif
diff --git a/ir/be/amd64/bearch_amd64.c b/ir/be/amd64/bearch_amd64.c
new file mode 100644 (file)
index 0000000..2733c92
--- /dev/null
@@ -0,0 +1,565 @@
+/*
+ * Copyright (C) 1995-2008 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.
+ */
+
+/**
+ * @file
+ * @brief    The main amd64 backend driver file.
+ * @version  $Id: bearch_amd64.c 26909 2010-01-05 15:56:54Z matze $
+ */
+#include "config.h"
+
+#include "pseudo_irg.h"
+#include "irgwalk.h"
+#include "irprog.h"
+#include "irprintf.h"
+#include "ircons.h"
+#include "irgmod.h"
+
+#include "bitset.h"
+#include "debug.h"
+
+#include "be.h"
+#include "../bearch.h"
+#include "../benode.h"
+#include "../belower.h"
+#include "../besched.h"
+#include "../beabi.h"
+#include "../bemodule.h"
+#include "../begnuas.h"
+#include "../belistsched.h"
+
+#include "bearch_amd64_t.h"
+
+#include "amd64_new_nodes.h"
+#include "gen_amd64_regalloc_if.h"
+#include "amd64_transform.h"
+#include "amd64_emitter.h"
+
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
+
+static arch_irn_class_t amd64_classify(const ir_node *irn)
+{
+       (void) irn;
+       return 0;
+}
+
+static ir_entity *amd64_get_frame_entity(const ir_node *node)
+{
+       (void) node;
+       /* TODO: return the ir_entity assigned to the frame */
+       return NULL;
+}
+
+static void amd64_set_frame_entity(ir_node *node, ir_entity *ent)
+{
+       (void) node;
+       (void) ent;
+       /* TODO: set the ir_entity assigned to the frame */
+}
+
+/**
+ * This function is called by the generic backend to correct offsets for
+ * nodes accessing the stack.
+ */
+static void amd64_set_frame_offset(ir_node *irn, int offset)
+{
+       (void) irn;
+       (void) offset;
+       /* TODO: correct offset if irn accesses the stack */
+}
+
+static int amd64_get_sp_bias(const ir_node *irn)
+{
+       (void) irn;
+       return 0;
+}
+
+/* fill register allocator interface */
+
+static const arch_irn_ops_t amd64_irn_ops = {
+       get_amd64_in_req,
+       amd64_classify,
+       amd64_get_frame_entity,
+       amd64_set_frame_entity,
+       amd64_set_frame_offset,
+       amd64_get_sp_bias,
+       NULL,    /* get_inverse             */
+       NULL,    /* get_op_estimated_cost   */
+       NULL,    /* possible_memory_operand */
+       NULL,    /* perform_memory_operand  */
+};
+
+
+
+/**
+ * Transforms the standard firm graph into
+ * a amd64 firm graph
+ */
+static void amd64_prepare_graph(void *self)
+{
+       amd64_code_gen_t *cg = self;
+
+       amd64_transform_graph (cg);
+
+       if (cg->dump)
+               be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
+}
+
+
+
+/**
+ * Called immediatly before emit phase.
+ */
+static void amd64_finish_irg(void *self)
+{
+       amd64_code_gen_t *cg = self;
+       ir_graph         *irg = cg->irg;
+
+       dump_ir_block_graph_sched(irg, "-amd64-finished");
+}
+
+
+static void amd64_before_ra(void *self)
+{
+       (void) self;
+       /* Some stuff you need to do after scheduling but before register allocation */
+}
+
+static void amd64_after_ra(void *self)
+{
+       (void) self;
+       /* Some stuff you need to do immediatly after register allocation */
+}
+
+
+
+/**
+ * Emits the code, closes the output file and frees
+ * the code generator interface.
+ */
+static void amd64_emit_and_done(void *self)
+{
+       amd64_code_gen_t *cg  = self;
+       ir_graph         *irg = cg->irg;
+
+       amd64_gen_routine(cg, irg);
+
+       /* de-allocate code generator */
+       free(cg);
+}
+
+static void *amd64_cg_init(be_irg_t *birg);
+
+static const arch_code_generator_if_t amd64_code_gen_if = {
+       amd64_cg_init,
+       NULL,                    /* get_pic_base hook */
+       NULL,                    /* before abi introduce hook */
+       amd64_prepare_graph,
+       NULL,                    /* spill hook */
+       amd64_before_ra,      /* before register allocation hook */
+       amd64_after_ra,       /* after register allocation hook */
+       amd64_finish_irg,
+       amd64_emit_and_done
+};
+
+/**
+ * Initializes the code generator.
+ */
+static void *amd64_cg_init(be_irg_t *birg)
+{
+       const arch_env_t    *arch_env = be_get_birg_arch_env(birg);
+       amd64_isa_t      *isa      = (amd64_isa_t *) arch_env;
+       amd64_code_gen_t *cg       = XMALLOC(amd64_code_gen_t);
+
+       cg->impl     = &amd64_code_gen_if;
+       cg->irg      = be_get_birg_irg(birg);
+       cg->isa      = isa;
+       cg->birg     = birg;
+       cg->dump     = (birg->main_env->options->dump_flags & DUMP_BE) ? 1 : 0;
+
+       return (arch_code_generator_t *)cg;
+}
+
+
+
+const arch_isa_if_t amd64_isa_if;
+static amd64_isa_t amd64_isa_template = {
+       {
+               &amd64_isa_if,             /* isa interface implementation */
+               &amd64_gp_regs[REG_RSP],  /* stack pointer register */
+               &amd64_gp_regs[REG_RBP],  /* base pointer register */
+               &amd64_reg_classes[CLASS_amd64_gp],  /* link pointer register class */
+               -1,                          /* stack direction */
+               2,                           /* power of two stack alignment for calls, 2^2 == 4 */
+               NULL,                        /* main environment */
+               7,                           /* costs for a spill instruction */
+               5,                           /* costs for a reload instruction */
+       },
+};
+
+/**
+ * Initializes the backend ISA
+ */
+static arch_env_t *amd64_init(FILE *outfile)
+{
+       static int run_once = 0;
+       amd64_isa_t *isa;
+
+       if(run_once)
+               return NULL;
+       run_once = 1;
+
+       isa = XMALLOC(amd64_isa_t);
+       memcpy(isa, &amd64_isa_template, sizeof(*isa));
+
+       be_emit_init(outfile);
+
+       amd64_register_init();
+       amd64_create_opcodes(&amd64_irn_ops);
+
+       return &isa->arch_env;
+}
+
+
+
+/**
+ * Closes the output file and frees the ISA structure.
+ */
+static void amd64_done(void *self)
+{
+       amd64_isa_t *isa = self;
+
+       /* emit now all global declarations */
+       be_gas_emit_decls(isa->arch_env.main_env);
+
+       be_emit_exit();
+       free(self);
+}
+
+
+static unsigned amd64_get_n_reg_class(void)
+{
+       return N_CLASSES;
+}
+
+static const arch_register_class_t *amd64_get_reg_class(unsigned i)
+{
+       assert(i < N_CLASSES);
+       return &amd64_reg_classes[i];
+}
+
+
+
+/**
+ * Get the register class which shall be used to store a value of a given mode.
+ * @param self The this pointer.
+ * @param mode The mode in question.
+ * @return A register class which can hold values of the given mode.
+ */
+static const arch_register_class_t *amd64_get_reg_class_for_mode(const ir_mode *mode)
+{
+       if (mode_is_float(mode))
+               return &amd64_reg_classes[CLASS_amd64_fp];
+       else
+               return &amd64_reg_classes[CLASS_amd64_gp];
+}
+
+
+
+typedef struct {
+       be_abi_call_flags_bits_t flags;
+       const arch_env_t *arch_env;
+       ir_graph *irg;
+} amd64_abi_env_t;
+
+static void *amd64_abi_init(const be_abi_call_t *call, const arch_env_t *arch_env, ir_graph *irg)
+{
+       amd64_abi_env_t *env = XMALLOC(amd64_abi_env_t);
+       be_abi_call_flags_t fl = be_abi_call_get_flags(call);
+       env->flags    = fl.bits;
+       env->irg      = irg;
+       env->arch_env = arch_env;
+       return env;
+}
+
+/**
+ * Get the between type for that call.
+ * @param self The callback object.
+ * @return The between type of for that call.
+ */
+static ir_type *amd64_get_between_type(void *self)
+{
+       static ir_type *between_type = NULL;
+       static ir_entity *old_bp_ent = NULL;
+       (void) self;
+
+       if(!between_type) {
+               ir_entity *ret_addr_ent;
+               ir_type *ret_addr_type = new_type_primitive(mode_P);
+               ir_type *old_bp_type   = new_type_primitive(mode_P);
+
+               between_type           = new_type_class(new_id_from_str("amd64_between_type"));
+               old_bp_ent             = new_entity(between_type, new_id_from_str("old_bp"), old_bp_type);
+               ret_addr_ent           = new_entity(between_type, new_id_from_str("old_bp"), ret_addr_type);
+
+               set_entity_offset(old_bp_ent, 0);
+               set_entity_offset(ret_addr_ent, get_type_size_bytes(old_bp_type));
+               set_type_size_bytes(between_type, get_type_size_bytes(old_bp_type) + get_type_size_bytes(ret_addr_type));
+       }
+
+       return between_type;
+}
+
+/**
+ * Build the prolog, return the BASE POINTER register
+ */
+static const arch_register_t *amd64_abi_prologue(void *self, ir_node **mem,
+                                                    pmap *reg_map, int *stack_bias)
+{
+       amd64_abi_env_t  *env  = self;
+       const arch_env_t *aenv = env->arch_env;
+       (void) mem;
+       (void) stack_bias;
+       (void) aenv;
+       (void) reg_map;
+
+       if (!env->flags.try_omit_fp) {
+               /* FIXME: maybe later here should be some code to generate
+                * the usual abi prologue */
+               return env->arch_env->bp;
+       }
+
+       return env->arch_env->sp;
+}
+
+/* Build the epilog */
+static void amd64_abi_epilogue(void *self, ir_node *bl, ir_node **mem,
+                               pmap *reg_map)
+{
+       amd64_abi_env_t  *env  = self;
+       const arch_env_t *aenv = env->arch_env;
+       ir_node          *curr_sp  = be_abi_reg_map_get(reg_map, aenv->sp);
+       ir_node          *curr_bp  = be_abi_reg_map_get(reg_map, aenv->bp);
+       (void) bl;
+       (void) mem;
+
+       if (env->flags.try_omit_fp) {
+               curr_sp = be_new_IncSP(aenv->sp, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK, 0);
+       }
+
+       be_abi_reg_map_set(reg_map, aenv->sp, curr_sp);
+       be_abi_reg_map_set(reg_map, aenv->bp, curr_bp);
+}
+
+static const be_abi_callbacks_t amd64_abi_callbacks = {
+       amd64_abi_init,
+       free,
+       amd64_get_between_type,
+       amd64_abi_prologue,
+       amd64_abi_epilogue,
+};
+
+/**
+ * Get the ABI restrictions for procedure calls.
+ * @param self        The this pointer.
+ * @param method_type The type of the method (procedure) in question.
+ * @param abi         The abi object to be modified
+ */
+static void amd64_get_call_abi(const void *self, ir_type *method_type,
+                           be_abi_call_t *abi)
+{
+       ir_type  *tp;
+       ir_mode  *mode;
+       int       i, n = get_method_n_params(method_type);
+       be_abi_call_flags_t call_flags;
+       (void) self;
+
+       /* set abi flags for calls */
+       call_flags.bits.left_to_right         = 0;
+       call_flags.bits.store_args_sequential = 1;
+       call_flags.bits.try_omit_fp           = 1;
+       call_flags.bits.fp_free               = 0;
+       call_flags.bits.call_has_imm          = 1;
+
+       /* set stack parameter passing style */
+       be_abi_call_set_flags(abi, call_flags, &amd64_abi_callbacks);
+
+       for (i = 0; i < n; i++) {
+               /* TODO: implement register parameter: */
+               /* reg = get reg for param i;          */
+               /* be_abi_call_param_reg(abi, i, reg); */
+
+               /* default: all parameters on stack */
+               tp   = get_method_param_type(method_type, i);
+               mode = get_type_mode(tp);
+               be_abi_call_param_stack(abi, i, mode, 4, 0, 0, ABI_CONTEXT_BOTH);
+       }
+
+       /* TODO: set correct return register */
+       /* default: return value is in R0 resp. F0 */
+       if (get_method_n_ress(method_type) > 0) {
+               tp   = get_method_res_type(method_type, 0);
+               mode = get_type_mode(tp);
+
+               /* FIXME: No floating point yet */
+               /* be_abi_call_res_reg(abi, 0,
+                       mode_is_float(mode) ? &amd64_fp_regs[REG_F0] : &amd64_gp_regs[REG_R0], ABI_CONTEXT_BOTH) */;
+
+               be_abi_call_res_reg(abi, 0,
+                       &amd64_gp_regs[REG_RAX], ABI_CONTEXT_BOTH);
+       }
+}
+
+static int amd64_to_appear_in_schedule(void *block_env, const ir_node *irn)
+{
+       (void) block_env;
+
+       if(!is_amd64_irn(irn))
+               return -1;
+
+       return 1;
+}
+
+/**
+ * Initializes the code generator interface.
+ */
+static const arch_code_generator_if_t *amd64_get_code_generator_if(
+               void *self)
+{
+       (void) self;
+       return &amd64_code_gen_if;
+}
+
+list_sched_selector_t amd64_sched_selector;
+
+/**
+ * Returns the reg_pressure scheduler with to_appear_in_schedule() overloaded
+ */
+static const list_sched_selector_t *amd64_get_list_sched_selector(
+               const void *self, list_sched_selector_t *selector)
+{
+       (void) self;
+       (void) selector;
+
+       amd64_sched_selector = trivial_selector;
+       amd64_sched_selector.to_appear_in_schedule = amd64_to_appear_in_schedule;
+       return &amd64_sched_selector;
+}
+
+static const ilp_sched_selector_t *amd64_get_ilp_sched_selector(
+               const void *self)
+{
+       (void) self;
+       return NULL;
+}
+
+/**
+ * Returns the necessary byte alignment for storing a register of given class.
+ */
+static int amd64_get_reg_class_alignment(const arch_register_class_t *cls)
+{
+       ir_mode *mode = arch_register_class_mode(cls);
+       return get_mode_size_bytes(mode);
+}
+
+/**
+ * Returns the libFirm configuration parameter for this backend.
+ */
+static const backend_params *amd64_get_backend_params(void) {
+       static backend_params p = {
+               0,     /* no dword lowering */
+               0,     /* no inline assembly */
+               NULL,  /* will be set later */
+               NULL,  /* no creator function */
+               NULL,  /* context for create_intrinsic_fkt */
+               NULL,  /* parameter for if conversion */
+               NULL,  /* float arithmetic mode */
+               0,     /* no trampoline support: size 0 */
+               0,     /* no trampoline support: align 0 */
+               NULL,  /* no trampoline support: no trampoline builder */
+               4      /* alignment of stack parameter: typically 4 (32bit) or 8 (64bit) */
+       };
+       return &p;
+}
+
+static const be_execution_unit_t ***amd64_get_allowed_execution_units(
+               const ir_node *irn)
+{
+       (void) irn;
+       /* TODO */
+       assert(0);
+       return NULL;
+}
+
+static const be_machine_t *amd64_get_machine(const void *self)
+{
+       (void) self;
+       /* TODO */
+       assert(0);
+       return NULL;
+}
+
+static ir_graph **amd64_get_backend_irg_list(const void *self,
+                                                ir_graph ***irgs)
+{
+       (void) self;
+       (void) irgs;
+       return NULL;
+}
+
+static asm_constraint_flags_t amd64_parse_asm_constraint(const char **c)
+{
+       (void) c;
+       return ASM_CONSTRAINT_FLAG_INVALID;
+}
+
+static int amd64_is_valid_clobber(const char *clobber)
+{
+       (void) clobber;
+       return 0;
+}
+
+const arch_isa_if_t amd64_isa_if = {
+       amd64_init,
+       amd64_done,
+       NULL,                /* handle intrinsics */
+       amd64_get_n_reg_class,
+       amd64_get_reg_class,
+       amd64_get_reg_class_for_mode,
+       amd64_get_call_abi,
+       amd64_get_code_generator_if,
+       amd64_get_list_sched_selector,
+       amd64_get_ilp_sched_selector,
+       amd64_get_reg_class_alignment,
+    amd64_get_backend_params,
+       amd64_get_allowed_execution_units,
+       amd64_get_machine,
+       amd64_get_backend_irg_list,
+       NULL,                    /* mark remat */
+       amd64_parse_asm_constraint,
+       amd64_is_valid_clobber
+};
+
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_amd64);
+void be_init_arch_amd64(void)
+{
+       be_register_isa_if("amd64", &amd64_isa_if);
+       FIRM_DBG_REGISTER(dbg, "firm.be.amd64.cg");
+       amd64_init_transform();
+}
diff --git a/ir/be/amd64/bearch_amd64_t.h b/ir/be/amd64/bearch_amd64_t.h
new file mode 100644 (file)
index 0000000..6880d83
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 1995-2008 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.
+ */
+
+/**
+ * @file
+ * @brief   declarations for TEMPALTE backend -- private header
+ * @version $Id: bearch_amd64_t.h 26542 2009-09-18 09:18:32Z matze $
+ */
+#ifndef FIRM_BE_amd64_BEARCH_amd64_T_H
+#define FIRM_BE_amd64_BEARCH_amd64_T_H
+
+#include "debug.h"
+#include "amd64_nodes_attr.h"
+#include "be.h"
+#include "../beemitter.h"
+#include "set.h"
+
+typedef struct amd64_isa_t            amd64_isa_t;
+typedef struct amd64_code_gen_t       amd64_code_gen_t;
+typedef struct amd64_transform_env_t  amd64_transform_env_t;
+
+struct amd64_code_gen_t {
+       const arch_code_generator_if_t *impl;           /**< implementation */
+       ir_graph                       *irg;            /**< current irg */
+       amd64_isa_t                    *isa;            /**< the isa instance */
+       be_irg_t                       *birg;           /**< The be-irg (contains additional information about the irg) */
+       char                            dump;           /**< set to 1 if graphs should be dumped */
+};
+
+struct amd64_isa_t {
+       arch_env_t  arch_env;      /**< must be derived from arch_isa */
+};
+
+/**
+ * this is a struct to minimize the number of parameters
+ * for transformation walker
+ */
+struct amd64_transform_env_t {
+       dbg_info *dbg;      /**< The node debug info */
+       ir_graph *irg;      /**< The irg, the node should be created in */
+       ir_node  *block;    /**< The block, the node should belong to */
+       ir_node  *irn;      /**< The irn, to be transformed */
+       ir_mode  *mode;     /**< The mode of the irn */
+};
+
+#endif
index 7eaa41e..e72bdbe 100644 (file)
@@ -58,6 +58,7 @@ void be_init_arch_ppc32(void);
 void be_init_arch_mips(void);
 void be_init_arch_arm(void);
 void be_init_arch_sparc(void);
+void be_init_arch_amd64(void);
 void be_init_arch_sta(void);
 void be_init_arch_sparc(void);
 void be_init_arch_TEMPLATE(void);
@@ -139,6 +140,7 @@ void be_init_modules(void)
        be_init_arch_mips();
        be_init_arch_arm();
        be_init_arch_sparc();
+       be_init_arch_amd64();
        be_init_arch_TEMPLATE();
 
 #ifdef WITH_ILP