initaler checkin SPARC backend
authorHannes Rapp <rapp@ipd.info.uni-karlsruhe.de>
Tue, 15 Dec 2009 14:43:15 +0000 (14:43 +0000)
committerHannes Rapp <rapp@ipd.info.uni-karlsruhe.de>
Tue, 15 Dec 2009 14:43:15 +0000 (14:43 +0000)
[r26793]

19 files changed:
ir/be/sparc/bearch_sparc.c [new file with mode: 0644]
ir/be/sparc/bearch_sparc.h [new file with mode: 0644]
ir/be/sparc/bearch_sparc_t.h [new file with mode: 0644]
ir/be/sparc/gen_sparc_emitter.c [new file with mode: 0644]
ir/be/sparc/gen_sparc_emitter.h [new file with mode: 0644]
ir/be/sparc/gen_sparc_machine.c [new file with mode: 0644]
ir/be/sparc/gen_sparc_machine.h [new file with mode: 0644]
ir/be/sparc/gen_sparc_new_nodes.c.inl [new file with mode: 0644]
ir/be/sparc/gen_sparc_new_nodes.h [new file with mode: 0644]
ir/be/sparc/gen_sparc_regalloc_if.c [new file with mode: 0644]
ir/be/sparc/gen_sparc_regalloc_if.h [new file with mode: 0644]
ir/be/sparc/sparc_emitter.c [new file with mode: 0644]
ir/be/sparc/sparc_emitter.h [new file with mode: 0644]
ir/be/sparc/sparc_new_nodes.c [new file with mode: 0644]
ir/be/sparc/sparc_new_nodes.h [new file with mode: 0644]
ir/be/sparc/sparc_nodes_attr.h [new file with mode: 0644]
ir/be/sparc/sparc_spec.pl [new file with mode: 0644]
ir/be/sparc/sparc_transform.c [new file with mode: 0644]
ir/be/sparc/sparc_transform.h [new file with mode: 0644]

diff --git a/ir/be/sparc/bearch_sparc.c b/ir/be/sparc/bearch_sparc.c
new file mode 100644 (file)
index 0000000..7b31c1f
--- /dev/null
@@ -0,0 +1,589 @@
+/*
+ * 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 sparc backend driver file.
+ * @version  $Id: bearch_TEMPLATE.c 26673 2009-10-01 16:43:13Z matze $
+ */
+
+#include "config.h"
+
+#include "lc_opts.h"
+#include "lc_opts_enum.h"
+
+#include "pseudo_irg.h"
+#include "irgwalk.h"
+#include "irprog.h"
+#include "irprintf.h"
+#include "ircons.h"
+#include "irgmod.h"
+#include "irgopt.h"
+#include "iroptimize.h"
+#include "lowering.h"
+#include "error.h"
+
+#include "bitset.h"
+#include "debug.h"
+#include "array_t.h"
+#include "irtools.h"
+
+#include "../bearch.h"
+#include "../benode.h"
+#include "../belower.h"
+#include "../besched.h"
+#include "be.h"
+#include "../beabi.h"
+#include "../bemachine.h"
+#include "../beilpsched.h"
+#include "../bemodule.h"
+#include "../beirg.h"
+#include "../bespillslots.h"
+#include "../begnuas.h"
+#include "../belistsched.h"
+#include "../beflags.h"
+
+#include "bearch_sparc_t.h"
+
+#include "sparc_new_nodes.h"
+#include "gen_sparc_regalloc_if.h"
+#include "sparc_transform.h"
+#include "sparc_emitter.h"
+
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
+
+static arch_irn_class_t sparc_classify(const ir_node *irn)
+{
+       (void) irn;
+       return 0;
+}
+
+static ir_entity *sparc_get_frame_entity(const ir_node *node)
+{
+       (void) node;
+       /* TODO: return the ir_entity assigned to the frame */
+       return NULL;
+}
+
+static void sparc_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 sparc_set_frame_offset(ir_node *irn, int offset)
+{
+       (void) irn;
+       (void) offset;
+       /* TODO: correct offset if irn accesses the stack */
+}
+
+static int sparc_get_sp_bias(const ir_node *irn)
+{
+       (void) irn;
+       return 0;
+}
+
+/* fill register allocator interface */
+
+static const arch_irn_ops_t sparc_irn_ops = {
+       get_sparc_in_req,
+       sparc_classify,
+       sparc_get_frame_entity,
+       sparc_set_frame_entity,
+       sparc_set_frame_offset,
+       sparc_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 SPARC firm graph
+ */
+static void sparc_prepare_graph(void *self)
+{
+       sparc_code_gen_t *cg = self;
+
+       /* transform FIRM into SPARC asm nodes */
+       sparc_transform_graph(cg);
+
+       if (cg->dump)
+               be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
+}
+
+
+
+/**
+ * Called immediatly before emit phase.
+ */
+static void sparc_finish_irg(void *self)
+{
+       sparc_code_gen_t *cg = self;
+       ir_graph            *irg = cg->irg;
+
+       dump_ir_block_graph_sched(irg, "-sparc-finished");
+}
+
+
+static ir_node *sparc_flags_remat(ir_node *node, ir_node *after)
+{
+       ir_node *block;
+       ir_node *copy;
+
+       if (is_Block(after)) {
+               block = after;
+       } else {
+               block = get_nodes_block(after);
+       }
+       copy = exact_copy(node);
+       set_nodes_block(copy, block);
+       sched_add_after(after, copy);
+       return copy;
+}
+
+static void sparc_before_ra(void *self)
+{
+       (void) self;
+       sparc_code_gen_t *cg = self;
+       /* fixup flags register */
+       be_sched_fix_flags(cg->birg, &sparc_reg_classes[CLASS_sparc_flags], &sparc_flags_remat);
+}
+
+static void sparc_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 sparc_emit_and_done(void *self)
+{
+       sparc_code_gen_t *cg = self;
+       ir_graph           *irg = cg->irg;
+
+       sparc_gen_routine(cg, irg);
+
+       /* de-allocate code generator */
+       free(cg);
+}
+
+static void *sparc_cg_init(be_irg_t *birg);
+
+static const arch_code_generator_if_t sparc_code_gen_if = {
+       sparc_cg_init,
+       NULL,                    /* get_pic_base hook */
+       NULL,                    /* before abi introduce hook */
+       sparc_prepare_graph,
+       NULL,                    /* spill hook */
+       sparc_before_ra,      /* before register allocation hook */
+       sparc_after_ra,       /* after register allocation hook */
+       sparc_finish_irg,
+       sparc_emit_and_done
+};
+
+/**
+ * Initializes the code generator.
+ */
+static void *sparc_cg_init(be_irg_t *birg)
+{
+       static ir_type *int_tp = NULL;
+       sparc_isa_t      *isa = (sparc_isa_t *)birg->main_env->arch_env;
+       sparc_code_gen_t *cg;
+
+       if (! int_tp) {
+               /* create an integer type with machine size */
+               int_tp = new_type_primitive(new_id_from_chars("int", 3), mode_Is);
+       }
+
+       cg                               = XMALLOC(sparc_code_gen_t);
+       cg->impl                                = &sparc_code_gen_if;
+       cg->irg                         = birg->irg;
+       //cg->reg_set                           = new_set(arm_cmp_irn_reg_assoc, 1024);
+       cg->isa                         = isa;
+       cg->birg                                = birg;
+       //cg->int_tp                            = int_tp;
+       //cg->have_fp_insn      = 0;
+       //cg->unknown_gp                = NULL;
+       //cg->unknown_fpa               = NULL;
+       cg->dump                                = (birg->main_env->options->dump_flags & DUMP_BE) ? 1 : 0;
+
+       FIRM_DBG_REGISTER(cg->mod, "firm.be.sparc.cg");
+
+       /* enter the current code generator */
+       isa->cg = cg;
+
+       return (arch_code_generator_t *)cg;
+}
+
+
+
+const arch_isa_if_t sparc_isa_if;
+static sparc_isa_t sparc_isa_template = {
+       {
+               &sparc_isa_if,             /* isa interface implementation */
+               &sparc_gp_regs[REG_SP],  /* stack pointer register */
+               &sparc_gp_regs[REG_FP],  /* base pointer register */
+               &sparc_reg_classes[CLASS_sparc_gp],  /* link pointer register class */
+               -1,                          /* stack direction */
+               1,                           /* 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 */
+       },
+       NULL                                            /* current code generator */
+};
+
+/**
+ * Initializes the backend ISA
+ */
+static arch_env_t *sparc_init(FILE *outfile)
+{
+       static int run_once = 0;
+       sparc_isa_t *isa;
+
+       if(run_once)
+               return NULL;
+       run_once = 1;
+
+       isa = XMALLOC(sparc_isa_t);
+       memcpy(isa, &sparc_isa_template, sizeof(*isa));
+
+       be_emit_init(outfile);
+
+       sparc_register_init();
+       sparc_create_opcodes(&sparc_irn_ops);
+
+       return &isa->arch_env;
+}
+
+
+
+/**
+ * Closes the output file and frees the ISA structure.
+ */
+static void sparc_done(void *self)
+{
+       sparc_isa_t *isa = self;
+
+       /* emit now all global declarations */
+       be_gas_emit_decls(isa->arch_env.main_env, 0);
+
+       be_emit_exit();
+       free(self);
+}
+
+
+static unsigned sparc_get_n_reg_class(void)
+{
+       return N_CLASSES;
+}
+
+static const arch_register_class_t *sparc_get_reg_class(unsigned i)
+{
+       assert(i < N_CLASSES);
+       return &sparc_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.
+ */
+const arch_register_class_t *sparc_get_reg_class_for_mode(const ir_mode *mode)
+{
+       if (mode_is_float(mode))
+               return &sparc_reg_classes[CLASS_sparc_fp];
+       else
+               return &sparc_reg_classes[CLASS_sparc_gp];
+}
+
+
+
+typedef struct {
+       be_abi_call_flags_bits_t flags;
+       const arch_env_t *arch_env;
+       ir_graph *irg;
+} sparc_abi_env_t;
+
+static void *sparc_abi_init(const be_abi_call_t *call, const arch_env_t *arch_env, ir_graph *irg)
+{
+       sparc_abi_env_t *env = XMALLOC(sparc_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 *sparc_get_between_type(void *self)
+{
+       static ir_type *between_type = NULL;
+       (void) self;
+
+       if (between_type == NULL) {
+               between_type = new_type_class(new_id_from_str("sparc_between_type"));
+               set_type_size_bytes(between_type, 0);
+       }
+
+       return between_type;
+}
+
+/**
+ * Build the prolog, return the BASE POINTER register
+ */
+static const arch_register_t *sparc_abi_prologue(void *self, ir_node **mem,
+                                                    pmap *reg_map, int *stack_bias)
+{
+       sparc_abi_env_t *env = self;
+       (void) reg_map;
+       (void) mem;
+       (void) stack_bias;
+
+       if(env->flags.try_omit_fp)
+               return env->arch_env->sp;
+
+       //panic("framepointer not implemented yet");
+       return env->arch_env->bp;
+}
+
+/* Build the epilog */
+static void sparc_abi_epilogue(void *self, ir_node *bl, ir_node **mem,
+                                  pmap *reg_map)
+{
+       (void) self;
+       (void) bl;
+       (void) mem;
+       (void) reg_map;
+}
+
+static const be_abi_callbacks_t sparc_abi_callbacks = {
+       sparc_abi_init,
+       free,
+       sparc_get_between_type,
+       sparc_abi_prologue,
+       sparc_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
+ */
+void sparc_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, &sparc_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);
+       }
+
+       /* TODO: set correct return register */
+       /* default: return value is in O0 resp. F0 */
+       if (get_method_n_ress(method_type) > 0) {
+               tp   = get_method_res_type(method_type, 0);
+               mode = get_type_mode(tp);
+
+               be_abi_call_res_reg(abi, 0,
+                       mode_is_float(mode) ? &sparc_fp_regs[REG_F0] : &sparc_gp_regs[REG_O0]);
+       }
+}
+
+int sparc_to_appear_in_schedule(void *block_env, const ir_node *irn)
+{
+       (void) block_env;
+
+       if(!is_sparc_irn(irn))
+               return -1;
+
+       return 1;
+}
+
+/**
+ * Initializes the code generator interface.
+ */
+static const arch_code_generator_if_t *sparc_get_code_generator_if(
+               void *self)
+{
+       (void) self;
+       return &sparc_code_gen_if;
+}
+
+list_sched_selector_t sparc_sched_selector;
+
+/**
+ * Returns the reg_pressure scheduler with to_appear_in_schedule() overloaded
+ */
+static const list_sched_selector_t *sparc_get_list_sched_selector(
+               const void *self, list_sched_selector_t *selector)
+{
+       (void) self;
+       (void) selector;
+
+       sparc_sched_selector = trivial_selector;
+       sparc_sched_selector.to_appear_in_schedule = sparc_to_appear_in_schedule;
+       return &sparc_sched_selector;
+}
+
+static const ilp_sched_selector_t *sparc_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 sparc_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 *sparc_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 ***sparc_get_allowed_execution_units(
+               const ir_node *irn)
+{
+       (void) irn;
+       /* TODO */
+       assert(0);
+       return NULL;
+}
+
+static const be_machine_t *sparc_get_machine(const void *self)
+{
+       (void) self;
+       /* TODO */
+       assert(0);
+       return NULL;
+}
+
+static ir_graph **sparc_get_backend_irg_list(const void *self,
+                                                ir_graph ***irgs)
+{
+       (void) self;
+       (void) irgs;
+       return NULL;
+}
+
+static asm_constraint_flags_t sparc_parse_asm_constraint(const char **c)
+{
+       (void) c;
+       return ASM_CONSTRAINT_FLAG_INVALID;
+}
+
+static int sparc_is_valid_clobber(const char *clobber)
+{
+       (void) clobber;
+       return 0;
+}
+
+const arch_isa_if_t sparc_isa_if = {
+       sparc_init,
+       sparc_done,
+       NULL,                /* handle intrinsics */
+       sparc_get_n_reg_class,
+       sparc_get_reg_class,
+       sparc_get_reg_class_for_mode,
+       sparc_get_call_abi,
+       sparc_get_code_generator_if,
+       sparc_get_list_sched_selector,
+       sparc_get_ilp_sched_selector,
+       sparc_get_reg_class_alignment,
+    sparc_get_backend_params,
+       sparc_get_allowed_execution_units,
+       sparc_get_machine,
+       sparc_get_backend_irg_list,
+       NULL,                    /* mark remat */
+       sparc_parse_asm_constraint,
+       sparc_is_valid_clobber
+};
+
+void be_init_arch_sparc(void)
+{
+       be_register_isa_if("sparc", &sparc_isa_if);
+       FIRM_DBG_REGISTER(dbg, "firm.be.sparc.cg");
+       sparc_init_transform();
+       sparc_init_emitter();
+}
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_sparc);
diff --git a/ir/be/sparc/bearch_sparc.h b/ir/be/sparc/bearch_sparc.h
new file mode 100644 (file)
index 0000000..d4c50b1
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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 arm backend
+ * @author  Hannes Rapp
+ * @version $Id: bearch_arm.h 26317 2009-08-05 10:53:46Z matze $
+ */
+#ifndef FIRM_BE_SPARC_BEARCH_SPARC_H
+#define FIRM_BE_SPARC_BEARCH_SPARC_H
+
+#include "../bearch.h"
+
+extern const arch_isa_if_t sparc_isa_if;
+
+#endif
diff --git a/ir/be/sparc/bearch_sparc_t.h b/ir/be/sparc/bearch_sparc_t.h
new file mode 100644 (file)
index 0000000..ef28b1a
--- /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   declarations for SPARC backend -- private header
+ * @version $Id: bearch_TEMPLATE_t.h 26542 2009-09-18 09:18:32Z matze $
+ */
+#ifndef FIRM_BE_SPARC_BEARCH_TEMPLATE_T_H
+#define FIRM_BE_SPARC_BEARCH_TEMPLATE_T_H
+
+#include "debug.h"
+#include "sparc_nodes_attr.h"
+#include "be.h"
+#include "../beemitter.h"
+#include "set.h"
+
+typedef struct sparc_transform_env_t  sparc_transform_env_t;
+typedef struct _sparc_isa_t sparc_isa_t;
+
+typedef struct _sparc_code_gen_t {
+    const arch_code_generator_if_t *impl;           /**< implementation */
+    ir_graph                       *irg;            /**< current irg */
+    set                            *reg_set;        /**< set to memorize registers for FIRM nodes (e.g. phi) */
+    sparc_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 */
+    firm_dbg_module_t                          *mod;            /**< debugging module */
+} sparc_code_gen_t;
+
+
+struct _sparc_isa_t {
+    arch_env_t     arch_env;      /**< must be derived from arch_env_t */
+    sparc_code_gen_t *cg;           /**< current code generator */
+};
+
+
+/**
+ * this is a struct to minimize the number of parameters
+ * for transformation walker
+ */
+struct sparc_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
diff --git a/ir/be/sparc/gen_sparc_emitter.c b/ir/be/sparc/gen_sparc_emitter.c
new file mode 100644 (file)
index 0000000..205c4c1
--- /dev/null
@@ -0,0 +1,126 @@
+/**
+ * @file
+ * @brief     Generated functions to emit code for assembler ir nodes.
+ * @note      DO NOT EDIT THIS FILE, your changes will be lost.
+ *            Edit libfirm/ir/be/sparc/sparc_spec.pl instead.
+ *            created by: libfirm/ir/be/scripts/generate_emitter.pl libfirm/ir/be/sparc/sparc_spec.pl libfirm/ir/be/sparc
+ * @date      Tue Dec 15 15:19:15 2009
+ */
+#include "config.h"
+
+#include <stdio.h>
+
+#include "irnode.h"
+#include "irop_t.h"
+#include "irprog_t.h"
+
+#include "gen_sparc_emitter.h"
+#include "sparc_new_nodes.h"
+#include "sparc_emitter.h"
+
+static void emit_sparc_SubSP(const ir_node *node) {
+       be_emit_cstring("\tadd ");
+       sparc_emit_source_register(node, 0);
+       be_emit_cstring(", ");
+       sparc_emit_source_register(node, 1);
+       be_emit_cstring(", ");
+       sparc_emit_dest_register(node, 0);
+       be_emit_finish_line_gas(node);
+}
+
+static void emit_sparc_Add(const ir_node *node) {
+       be_emit_cstring("\tadd ");
+       sparc_emit_source_register(node, 0);
+       be_emit_cstring(", ");
+       sparc_emit_reg_or_imm(node, 1);
+       be_emit_cstring(", ");
+       sparc_emit_dest_register(node, 0);
+       be_emit_finish_line_gas(node);
+}
+
+static void emit_sparc_Store(const ir_node *node) {
+       be_emit_cstring("\tst");
+       sparc_emit_store_mode(node);
+       be_emit_char(' ');
+       sparc_emit_source_register(node, 0);
+       be_emit_cstring(", [");
+       sparc_emit_dest_register(node, 0);
+       sparc_emit_offset(node);
+       be_emit_char(']');
+       be_emit_finish_line_gas(node);
+}
+
+static void emit_sparc_Mov(const ir_node *node) {
+       be_emit_cstring("\tmov ");
+       sparc_emit_reg_or_imm(node, 0);
+       be_emit_cstring(", ");
+       sparc_emit_dest_register(node, 0);
+       be_emit_finish_line_gas(node);
+}
+
+static void emit_sparc_Tst(const ir_node *node) {
+       be_emit_cstring("\ttst ");
+       sparc_emit_source_register(node, 0);
+       be_emit_finish_line_gas(node);
+}
+
+static void emit_sparc_Cmp(const ir_node *node) {
+       be_emit_cstring("\tcmp ");
+       sparc_emit_source_register(node, 0);
+       be_emit_cstring(", ");
+       sparc_emit_reg_or_imm(node, 1);
+       be_emit_finish_line_gas(node);
+}
+
+static void emit_sparc_Sub(const ir_node *node) {
+       be_emit_cstring("\tsub ");
+       sparc_emit_source_register(node, 0);
+       be_emit_cstring(", ");
+       sparc_emit_reg_or_imm(node, 1);
+       be_emit_cstring(", ");
+       sparc_emit_dest_register(node, 0);
+       be_emit_finish_line_gas(node);
+}
+
+static void emit_sparc_Load(const ir_node *node) {
+       be_emit_cstring("\tld");
+       sparc_emit_load_mode(node);
+       be_emit_cstring(" [");
+       sparc_emit_source_register(node, 0);
+       sparc_emit_offset(node);
+       be_emit_cstring("], ");
+       sparc_emit_dest_register(node, 0);
+       be_emit_finish_line_gas(node);
+}
+
+static void emit_sparc_AddSP(const ir_node *node) {
+       be_emit_cstring("\tsub ");
+       sparc_emit_source_register(node, 0);
+       be_emit_cstring(", ");
+       sparc_emit_source_register(node, 1);
+       be_emit_cstring(", ");
+       sparc_emit_dest_register(node, 0);
+       be_emit_finish_line_gas(node);
+}
+
+/**
+ * Enters the emitter functions for handled nodes into the generic
+ * pointer of an opcode.
+ */
+void sparc_register_spec_emitters(void) {
+
+#define BE_EMIT(a) op_sparc_##a->ops.generic = (op_func)emit_sparc_##a
+
+  /* generated emitter functions */
+  BE_EMIT(SubSP);
+  BE_EMIT(Add);
+  BE_EMIT(Store);
+  BE_EMIT(Mov);
+  BE_EMIT(Tst);
+  BE_EMIT(Cmp);
+  BE_EMIT(Sub);
+  BE_EMIT(Load);
+  BE_EMIT(AddSP);
+
+#undef BE_EMIT
+}
diff --git a/ir/be/sparc/gen_sparc_emitter.h b/ir/be/sparc/gen_sparc_emitter.h
new file mode 100644 (file)
index 0000000..f612ec5
--- /dev/null
@@ -0,0 +1,17 @@
+/**
+ * @file
+ * @brief Function prototypes for the emitter functions.
+ * @note  DO NOT EDIT THIS FILE, your changes will be lost.
+ *        Edit libfirm/ir/be/sparc/sparc_spec.pl instead.
+ *        created by: libfirm/ir/be/scripts/generate_emitter.pl libfirm/ir/be/sparc/sparc_spec.pl libfirm/ir/be/sparc
+ * @date  Tue Dec 15 15:19:15 2009
+ */
+#ifndef FIRM_BE_SPARC_GEN_SPARC_EMITTER_H
+#define FIRM_BE_SPARC_GEN_SPARC_EMITTER_H
+
+#include "irnode.h"
+#include "sparc_emitter.h"
+
+void sparc_register_spec_emitters(void);
+
+#endif
diff --git a/ir/be/sparc/gen_sparc_machine.c b/ir/be/sparc/gen_sparc_machine.c
new file mode 100644 (file)
index 0000000..16e60df
--- /dev/null
@@ -0,0 +1,40 @@
+/**
+ * @file
+ * @brief     Generated functions for machine description interface.
+ * @note      DO NOT EDIT THIS FILE, your changes will be lost.
+ *            Edit libfirm/ir/be/sparc/sparc_spec.pl instead.
+ *            created by: libfirm/ir/be/scripts/generate_machine.pl libfirm/ir/be/sparc/sparc_spec.pl libfirm/ir/be/sparc
+ * @date      Tue Dec 15 15:19:15 2009
+ */
+#include "config.h"
+
+#include "gen_sparc_machine.h"
+
+
+be_execution_unit_type_t sparc_execution_unit_types[] = {
+};
+
+be_machine_t sparc_cpu = {
+       3,
+       1,
+       0,
+       sparc_execution_unit_types
+};
+
+/**
+ * Returns the sparc machines description
+ */
+const be_machine_t *sparc_init_machine_description(void) {
+       static int initialized = 0;
+
+       if (! initialized) {
+               be_execution_unit_type_t *cur_unit_tp;
+               (void) cur_unit_tp; /* avoid warning */
+
+               be_machine_init_dummy_unit();
+
+               initialized = 1;
+       }
+
+       return &sparc_cpu;
+}
diff --git a/ir/be/sparc/gen_sparc_machine.h b/ir/be/sparc/gen_sparc_machine.h
new file mode 100644 (file)
index 0000000..b6975ab
--- /dev/null
@@ -0,0 +1,21 @@
+/**
+ * @file
+ * @brief     Function prototypes for the machine description.
+ * @note      DO NOT EDIT THIS FILE, your changes will be lost.
+ *            Edit libfirm/ir/be/sparc/sparc_spec.pl instead.
+ *            created by: libfirm/ir/be/scripts/generate_machine.pl libfirm/ir/be/sparc/sparc_spec.pl libfirm/ir/be/sparc
+ * @date      Tue Dec 15 15:19:15 2009
+ */
+#ifndef FIRM_BE_SPARC_GEN_SPARC_MACHINE_H
+#define FIRM_BE_SPARC_GEN_SPARC_MACHINE_H
+
+#include "../bemachine.h"
+
+/**
+ * Returns the sparc machine description.
+ */
+const be_machine_t *sparc_init_machine_description(void);
+
+
+
+#endif
diff --git a/ir/be/sparc/gen_sparc_new_nodes.c.inl b/ir/be/sparc/gen_sparc_new_nodes.c.inl
new file mode 100644 (file)
index 0000000..e9f71b2
--- /dev/null
@@ -0,0 +1,1028 @@
+#include "gen_sparc_regalloc_if.h"
+
+
+ir_op *op_sparc_SubSP = NULL;
+ir_op *op_sparc_Add = NULL;
+ir_op *op_sparc_FrameAddr = NULL;
+ir_op *op_sparc_Store = NULL;
+ir_op *op_sparc_Branch = NULL;
+ir_op *op_sparc_Mov = NULL;
+ir_op *op_sparc_Tst = NULL;
+ir_op *op_sparc_SwitchJmp = NULL;
+ir_op *op_sparc_Cmp = NULL;
+ir_op *op_sparc_SymConst = NULL;
+ir_op *op_sparc_Sub = NULL;
+ir_op *op_sparc_Load = NULL;
+ir_op *op_sparc_AddSP = NULL;
+
+ir_op *get_op_sparc_SubSP(void)         { return op_sparc_SubSP; }
+int    is_sparc_SubSP(const ir_node *n) { return get_sparc_irn_opcode(n) == iro_sparc_SubSP; }
+
+ir_op *get_op_sparc_Add(void)         { return op_sparc_Add; }
+int    is_sparc_Add(const ir_node *n) { return get_sparc_irn_opcode(n) == iro_sparc_Add; }
+
+ir_op *get_op_sparc_FrameAddr(void)         { return op_sparc_FrameAddr; }
+int    is_sparc_FrameAddr(const ir_node *n) { return get_sparc_irn_opcode(n) == iro_sparc_FrameAddr; }
+
+ir_op *get_op_sparc_Store(void)         { return op_sparc_Store; }
+int    is_sparc_Store(const ir_node *n) { return get_sparc_irn_opcode(n) == iro_sparc_Store; }
+
+ir_op *get_op_sparc_Branch(void)         { return op_sparc_Branch; }
+int    is_sparc_Branch(const ir_node *n) { return get_sparc_irn_opcode(n) == iro_sparc_Branch; }
+
+ir_op *get_op_sparc_Mov(void)         { return op_sparc_Mov; }
+int    is_sparc_Mov(const ir_node *n) { return get_sparc_irn_opcode(n) == iro_sparc_Mov; }
+
+ir_op *get_op_sparc_Tst(void)         { return op_sparc_Tst; }
+int    is_sparc_Tst(const ir_node *n) { return get_sparc_irn_opcode(n) == iro_sparc_Tst; }
+
+ir_op *get_op_sparc_SwitchJmp(void)         { return op_sparc_SwitchJmp; }
+int    is_sparc_SwitchJmp(const ir_node *n) { return get_sparc_irn_opcode(n) == iro_sparc_SwitchJmp; }
+
+ir_op *get_op_sparc_Cmp(void)         { return op_sparc_Cmp; }
+int    is_sparc_Cmp(const ir_node *n) { return get_sparc_irn_opcode(n) == iro_sparc_Cmp; }
+
+ir_op *get_op_sparc_SymConst(void)         { return op_sparc_SymConst; }
+int    is_sparc_SymConst(const ir_node *n) { return get_sparc_irn_opcode(n) == iro_sparc_SymConst; }
+
+ir_op *get_op_sparc_Sub(void)         { return op_sparc_Sub; }
+int    is_sparc_Sub(const ir_node *n) { return get_sparc_irn_opcode(n) == iro_sparc_Sub; }
+
+ir_op *get_op_sparc_Load(void)         { return op_sparc_Load; }
+int    is_sparc_Load(const ir_node *n) { return get_sparc_irn_opcode(n) == iro_sparc_Load; }
+
+ir_op *get_op_sparc_AddSP(void)         { return op_sparc_AddSP; }
+int    is_sparc_AddSP(const ir_node *n) { return get_sparc_irn_opcode(n) == iro_sparc_AddSP; }
+
+
+
+static int sparc_opcode_start = -1;
+static int sparc_opcode_end   = -1;
+
+
+/** A tag for the sparc opcodes. Note that the address is used as a tag value, NOT the FOURCC code. */
+#define sparc_op_tag FOURCC('S', 'P', 'A', 'R')
+
+/** Return the opcode number of the first sparc opcode. */
+int get_sparc_opcode_first(void) {
+       return sparc_opcode_start;
+}
+
+/** Return the opcode number of the last sparc opcode + 1. */
+int get_sparc_opcode_last(void) {
+       return sparc_opcode_end;
+}
+
+/** Return 1 if the given opcode is a sparc machine op, 0 otherwise */
+int is_sparc_op(const ir_op *op) {
+       return get_op_tag(op) == sparc_op_tag;
+}
+
+/** Return 1 if the given node is a sparc machine node, 0 otherwise */
+int is_sparc_irn(const ir_node *node) {
+       return is_sparc_op(get_irn_op(node));
+}
+
+int get_sparc_irn_opcode(const ir_node *node) {
+       if (is_sparc_irn(node))
+               return get_irn_opcode(node) - sparc_opcode_start;
+       return -1;
+}
+
+#ifdef BIT
+#undef BIT
+#endif
+#define BIT(x)  (1 << (x % 32))
+
+static const unsigned sparc_limit_gp_sp[] = { BIT(REG_SP), 0 };
+
+static const arch_register_req_t sparc_requirements_gp_sp = {
+       arch_register_req_type_limited,
+       & sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limit_gp_sp,
+       0,        /* same pos */
+       0        /* different pos */
+};
+
+
+static const arch_register_req_t sparc_requirements_gp_gp = {
+       arch_register_req_type_normal,
+       & sparc_reg_classes[CLASS_sparc_gp],
+       NULL,        /* limit bitset */
+       0,           /* same pos */
+       0            /* different pos */
+};
+
+
+static const arch_register_req_t sparc_requirements_gp_sp_I_S = {
+       arch_register_req_type_ignore | arch_register_req_type_produces_sp | arch_register_req_type_limited,
+       & sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limit_gp_sp,
+       0,        /* same pos */
+       0        /* different pos */
+};
+
+
+static const arch_register_req_t sparc_requirements__none = {
+       arch_register_req_type_none,
+       NULL,                         /* regclass */
+       NULL,                         /* limit bitset */
+       0,                            /* same pos */
+       0                             /* different pos */
+};
+
+
+static const arch_register_req_t sparc_requirements_flags_flags = {
+       arch_register_req_type_normal,
+       & sparc_reg_classes[CLASS_sparc_flags],
+       NULL,        /* limit bitset */
+       0,           /* same pos */
+       0            /* different pos */
+};
+
+
+
+/**
+ * free stack space
+ */
+ir_node *new_bd_sparc_SubSP(dbg_info *dbgi, ir_node *block, ir_node *stack, ir_node *size, ir_node *mem)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_SubSP;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 3;
+       ir_node        *in[3];
+       int             n_res   = 2;
+       ir_mode        *mode    = mode_T;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t *in_reqs[] =
+       {
+               & sparc_requirements_gp_sp,
+               & sparc_requirements_gp_gp,
+               & sparc_requirements__none,
+       };
+
+       /* construct in array */
+       in[0] = stack;
+       in[1] = size;
+       in[2] = mem;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements_gp_sp_I_S;
+info->out_infos[1].req = &sparc_requirements__none;
+
+
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+/**
+ * construct Add node
+ */
+ir_node *new_bd_sparc_Add_imm(dbg_info *dbgi, ir_node *block, ir_node *left, int immediate_value)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_Add;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 1;
+       ir_node        *in[1];
+       int             n_res   = 1;
+       ir_mode        *mode    = mode_Iu;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t *in_reqs[] =
+       {
+               & sparc_requirements_gp_gp,
+       };
+
+       /* construct in array */
+       in[0] = left;
+
+       /* flags */
+       flags |= arch_irn_flags_rematerializable;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+       sparc_set_attr_imm(res, immediate_value);
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements_gp_gp;
+
+
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+/**
+ * construct Add node
+ */
+ir_node *new_bd_sparc_Add_reg(dbg_info *dbgi, ir_node *block, ir_node *left, ir_node *right)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_Add;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 2;
+       ir_node        *in[2];
+       int             n_res   = 1;
+       ir_mode        *mode    = mode_Iu;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t *in_reqs[] =
+       {
+               & sparc_requirements_gp_gp,
+               & sparc_requirements_gp_gp,
+       };
+
+       /* construct in array */
+       in[0] = left;
+       in[1] = right;
+
+       /* flags */
+       flags |= arch_irn_flags_rematerializable;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements_gp_gp;
+
+
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+/**
+ * construct FrameAddr node
+ */
+ir_node *new_bd_sparc_FrameAddr(dbg_info *dbgi, ir_node *block, ir_node *base, ir_entity *entity)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_FrameAddr;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 1;
+       ir_node        *in[1];
+       int             n_res   = 1;
+       ir_mode        *mode    = mode_Iu;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t *in_reqs[] =
+       {
+               & sparc_requirements_gp_gp,
+       };
+
+       /* construct in array */
+       in[0] = base;
+
+       /* flags */
+       flags |= arch_irn_flags_rematerializable;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+       init_sparc_symconst_attributes(res, entity);
+
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements_gp_gp;
+
+
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+/**
+ * construct Store: Store(ptr, val, mem) = ST ptr,val
+ */
+ir_node *new_bd_sparc_Store(dbg_info *dbgi, ir_node *block, ir_node *ptr, ir_node *val, ir_node *mem, ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_Store;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 3;
+       ir_node        *in[3];
+       int             n_res   = 1;
+       ir_mode        *mode    = mode_M;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t *in_reqs[] =
+       {
+               & sparc_requirements_gp_gp,
+               & sparc_requirements_gp_gp,
+               & sparc_requirements__none,
+       };
+
+       /* construct in array */
+       in[0] = ptr;
+       in[1] = val;
+       in[2] = mem;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+       init_sparc_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);
+
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements__none;
+
+
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+/**
+ * construct Branch node
+ */
+ir_node *new_bd_sparc_Branch(dbg_info *dbgi, ir_node *block, ir_node *op0, int proj_num)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_Branch;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 1;
+       ir_node        *in[1];
+       int             n_res   = 2;
+       ir_mode        *mode    = mode_T;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t *in_reqs[] =
+       {
+               & sparc_requirements_flags_flags,
+       };
+       sparc_jmp_cond_attr_t *attr;
+
+       /* construct in array */
+       in[0] = op0;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements__none;
+info->out_infos[1].req = &sparc_requirements__none;
+
+
+       attr = get_irn_generic_attr(res);
+               set_sparc_jmp_cond_proj_num(res, proj_num);
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+/**
+ * construct Mov node
+ */
+ir_node *new_bd_sparc_Mov_imm(dbg_info *dbgi, ir_node *block, int immediate_value)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_Mov;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 0;
+       ir_node       **in      = NULL;
+       int             n_res   = 1;
+       ir_mode        *mode    = mode_Iu;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t **in_reqs = NULL;
+
+       /* flags */
+       flags |= arch_irn_flags_rematerializable;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+       sparc_set_attr_imm(res, immediate_value);
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements_gp_gp;
+
+
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+/**
+ * construct Mov node
+ */
+ir_node *new_bd_sparc_Mov_reg(dbg_info *dbgi, ir_node *block, ir_node *op0)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_Mov;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 1;
+       ir_node        *in[1];
+       int             n_res   = 1;
+       ir_mode        *mode    = mode_Iu;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t *in_reqs[] =
+       {
+               & sparc_requirements_gp_gp,
+       };
+
+       /* construct in array */
+       in[0] = op0;
+
+       /* flags */
+       flags |= arch_irn_flags_rematerializable;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements_gp_gp;
+
+
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+/**
+ * construct Tst node
+ */
+ir_node *new_bd_sparc_Tst(dbg_info *dbgi, ir_node *block, ir_node *left, bool ins_permuted, bool is_unsigned)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_Tst;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 1;
+       ir_node        *in[1];
+       int             n_res   = 1;
+       ir_mode        *mode    = mode_Bu;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t *in_reqs[] =
+       {
+               & sparc_requirements_gp_gp,
+       };
+
+       /* construct in array */
+       in[0] = left;
+
+       /* flags */
+       flags |= arch_irn_flags_rematerializable;
+       flags |= arch_irn_flags_modify_flags;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+
+       init_sparc_cmp_attr(res, ins_permuted, is_unsigned);
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements_flags_flags;
+
+
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+/**
+ * construct SwitchJmp node
+ */
+ir_node *new_bd_sparc_SwitchJmp(dbg_info *dbgi, ir_node *block, ir_node *op0, int n_projs, long def_proj_num)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_SwitchJmp;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 1;
+       ir_node        *in[1];
+       int             n_res   = 1;
+       ir_mode        *mode    = mode_T;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t *in_reqs[] =
+       {
+               & sparc_requirements_gp_gp,
+       };
+       sparc_jmp_switch_attr_t *attr;
+
+       /* construct in array */
+       in[0] = op0;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements__none;
+
+
+       attr = get_irn_generic_attr(res);
+               set_sparc_jmp_switch_n_projs(res, n_projs);
+       set_sparc_jmp_switch_default_proj_num(res, def_proj_num);
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+/**
+ * construct Cmp node
+ */
+ir_node *new_bd_sparc_Cmp_imm(dbg_info *dbgi, ir_node *block, ir_node *left, int immediate_value, bool ins_permuted, bool is_unsigned)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_Cmp;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 1;
+       ir_node        *in[1];
+       int             n_res   = 1;
+       ir_mode        *mode    = mode_Bu;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t *in_reqs[] =
+       {
+               & sparc_requirements_gp_gp,
+       };
+
+       /* construct in array */
+       in[0] = left;
+
+       /* flags */
+       flags |= arch_irn_flags_rematerializable;
+       flags |= arch_irn_flags_modify_flags;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+
+       sparc_set_attr_imm(res, immediate_value);       init_sparc_cmp_attr(res, ins_permuted, is_unsigned);
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements_flags_flags;
+
+
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+/**
+ * construct Cmp node
+ */
+ir_node *new_bd_sparc_Cmp_reg(dbg_info *dbgi, ir_node *block, ir_node *left, ir_node *right, bool ins_permuted, bool is_unsigned)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_Cmp;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 2;
+       ir_node        *in[2];
+       int             n_res   = 1;
+       ir_mode        *mode    = mode_Bu;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t *in_reqs[] =
+       {
+               & sparc_requirements_gp_gp,
+               & sparc_requirements_gp_gp,
+       };
+
+       /* construct in array */
+       in[0] = left;
+       in[1] = right;
+
+       /* flags */
+       flags |= arch_irn_flags_rematerializable;
+       flags |= arch_irn_flags_modify_flags;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+
+       init_sparc_cmp_attr(res, ins_permuted, is_unsigned);
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements_flags_flags;
+
+
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+/**
+ * construct SymConst node
+ */
+ir_node *new_bd_sparc_SymConst(dbg_info *dbgi, ir_node *block, ir_entity *entity)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_SymConst;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 0;
+       ir_node       **in      = NULL;
+       int             n_res   = 1;
+       ir_mode        *mode    = mode_Iu;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t **in_reqs = NULL;
+
+       /* flags */
+       flags |= arch_irn_flags_rematerializable;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+       init_sparc_symconst_attributes(res, entity);
+
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements_gp_gp;
+
+
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+/**
+ * construct Sub node
+ */
+ir_node *new_bd_sparc_Sub_imm(dbg_info *dbgi, ir_node *block, ir_node *left, int immediate_value)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_Sub;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 1;
+       ir_node        *in[1];
+       int             n_res   = 1;
+       ir_mode        *mode    = mode_Iu;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t *in_reqs[] =
+       {
+               & sparc_requirements_gp_gp,
+       };
+
+       /* construct in array */
+       in[0] = left;
+
+       /* flags */
+       flags |= arch_irn_flags_rematerializable;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+       sparc_set_attr_imm(res, immediate_value);
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements_gp_gp;
+
+
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+/**
+ * construct Sub node
+ */
+ir_node *new_bd_sparc_Sub_reg(dbg_info *dbgi, ir_node *block, ir_node *left, ir_node *right)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_Sub;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 2;
+       ir_node        *in[2];
+       int             n_res   = 1;
+       ir_mode        *mode    = mode_Iu;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t *in_reqs[] =
+       {
+               & sparc_requirements_gp_gp,
+               & sparc_requirements_gp_gp,
+       };
+
+       /* construct in array */
+       in[0] = left;
+       in[1] = right;
+
+       /* flags */
+       flags |= arch_irn_flags_rematerializable;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements_gp_gp;
+
+
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+/**
+ * construct Load: Load(ptr, mem) = LD ptr -> reg
+ */
+ir_node *new_bd_sparc_Load(dbg_info *dbgi, ir_node *block, ir_node *ptr, ir_node *mem, ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_Load;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 2;
+       ir_node        *in[2];
+       int             n_res   = 2;
+       ir_mode        *mode    = mode_T;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t *in_reqs[] =
+       {
+               & sparc_requirements_gp_gp,
+               & sparc_requirements__none,
+       };
+
+       /* construct in array */
+       in[0] = ptr;
+       in[1] = mem;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+       init_sparc_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);
+
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements_gp_gp;
+info->out_infos[1].req = &sparc_requirements__none;
+
+
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+/**
+ * alloc stack space
+ */
+ir_node *new_bd_sparc_AddSP(dbg_info *dbgi, ir_node *block, ir_node *stack, ir_node *size, ir_node *mem)
+{
+       ir_node        *res;
+       ir_op          *op      = op_sparc_AddSP;
+       int             flags   = 0;
+       backend_info_t *info;
+       int             arity   = 3;
+       ir_node        *in[3];
+       int             n_res   = 3;
+       ir_mode        *mode    = mode_T;
+       static const be_execution_unit_t ***exec_units = NULL;
+       static const arch_register_req_t *in_reqs[] =
+       {
+               & sparc_requirements_gp_sp,
+               & sparc_requirements_gp_gp,
+               & sparc_requirements__none,
+       };
+
+       /* construct in array */
+       in[0] = stack;
+       in[1] = size;
+       in[2] = mem;
+
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+               init_sparc_attributes(res, flags, in_reqs, exec_units, n_res);
+
+       info = be_get_info(res);
+       info->out_infos[0].req = &sparc_requirements_gp_sp_I_S;
+info->out_infos[1].req = &sparc_requirements_gp_gp;
+info->out_infos[2].req = &sparc_requirements__none;
+
+
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+}
+
+
+
+/**
+ * Creates the sparc specific Firm machine operations
+ * needed for the assembler irgs.
+ */
+void sparc_create_opcodes(const arch_irn_ops_t *be_ops) {
+#define N   irop_flag_none
+#define L   irop_flag_labeled
+#define C   irop_flag_commutative
+#define X   irop_flag_cfopcode
+#define I   irop_flag_ip_cfopcode
+#define F   irop_flag_fragile
+#define Y   irop_flag_forking
+#define H   irop_flag_highlevel
+#define c   irop_flag_constlike
+#define K   irop_flag_keep
+#define M   irop_flag_machine
+#define O   irop_flag_machine_op
+#define NB  irop_flag_dump_noblock
+#define NI  irop_flag_dump_noinput
+#define R   (irop_flag_user << 0)
+
+       ir_op_ops  ops;
+       int        cur_opcode;
+       static int run_once = 0;
+
+       if (run_once)
+               return;
+       run_once = 1;
+
+       cur_opcode = get_next_ir_opcodes(iro_sparc_last);
+
+       sparc_opcode_start = cur_opcode;
+
+       memset(&ops, 0, sizeof(ops));
+       ops.be_ops        = be_ops;
+       ops.dump_node     = sparc_dump_node;
+       ops.node_cmp_attr = cmp_attr_sparc;
+       ops.copy_attr = sparc_copy_attr;
+       op_sparc_SubSP = new_ir_op(cur_opcode + iro_sparc_SubSP, "sparc_SubSP", op_pin_state_floats, N|M, oparity_trinary, 0, sizeof(sparc_attr_t), &ops);
+       set_op_tag(op_sparc_SubSP, sparc_op_tag);
+
+       memset(&ops, 0, sizeof(ops));
+       ops.be_ops        = be_ops;
+       ops.dump_node     = sparc_dump_node;
+       ops.node_cmp_attr = cmp_attr_sparc;
+       ops.copy_attr = sparc_copy_attr;
+       op_sparc_Add = new_ir_op(cur_opcode + iro_sparc_Add, "sparc_Add", op_pin_state_floats, C|M, oparity_zero, 0, sizeof(sparc_attr_t), &ops);
+       set_op_tag(op_sparc_Add, sparc_op_tag);
+
+       memset(&ops, 0, sizeof(ops));
+       ops.be_ops        = be_ops;
+       ops.dump_node     = sparc_dump_node;
+       ops.node_cmp_attr = cmp_attr_sparc_symconst;
+       ops.copy_attr = sparc_copy_attr;
+       op_sparc_FrameAddr = new_ir_op(cur_opcode + iro_sparc_FrameAddr, "sparc_FrameAddr", op_pin_state_floats, c|M, oparity_unary, 0, sizeof(sparc_symconst_attr_t), &ops);
+       set_op_tag(op_sparc_FrameAddr, sparc_op_tag);
+
+       memset(&ops, 0, sizeof(ops));
+       ops.be_ops        = be_ops;
+       ops.dump_node     = sparc_dump_node;
+       ops.node_cmp_attr = cmp_attr_sparc_load_store;
+       ops.copy_attr = sparc_copy_attr;
+       op_sparc_Store = new_ir_op(cur_opcode + iro_sparc_Store, "sparc_Store", op_pin_state_exc_pinned, L|F|M, oparity_trinary, 0, sizeof(sparc_load_store_attr_t), &ops);
+       set_op_tag(op_sparc_Store, sparc_op_tag);
+
+       memset(&ops, 0, sizeof(ops));
+       ops.be_ops        = be_ops;
+       ops.dump_node     = sparc_dump_node;
+       ops.node_cmp_attr = cmp_attr_sparc_jmp_cond;
+       ops.copy_attr = sparc_copy_attr;
+       op_sparc_Branch = new_ir_op(cur_opcode + iro_sparc_Branch, "sparc_Branch", op_pin_state_pinned, L|X|Y|M, oparity_unary, 0, sizeof(sparc_jmp_cond_attr_t), &ops);
+       set_op_tag(op_sparc_Branch, sparc_op_tag);
+
+       memset(&ops, 0, sizeof(ops));
+       ops.be_ops        = be_ops;
+       ops.dump_node     = sparc_dump_node;
+       ops.node_cmp_attr = cmp_attr_sparc;
+       ops.copy_attr = sparc_copy_attr;
+       op_sparc_Mov = new_ir_op(cur_opcode + iro_sparc_Mov, "sparc_Mov", op_pin_state_floats, N|M, oparity_variable, 0, sizeof(sparc_attr_t), &ops);
+       set_op_tag(op_sparc_Mov, sparc_op_tag);
+
+       memset(&ops, 0, sizeof(ops));
+       ops.be_ops        = be_ops;
+       ops.dump_node     = sparc_dump_node;
+       ops.node_cmp_attr = cmp_attr_sparc_cmp;
+       ops.copy_attr = sparc_copy_attr;
+       op_sparc_Tst = new_ir_op(cur_opcode + iro_sparc_Tst, "sparc_Tst", op_pin_state_floats, N|M, oparity_unary, 0, sizeof(sparc_cmp_attr_t), &ops);
+       set_op_tag(op_sparc_Tst, sparc_op_tag);
+
+       memset(&ops, 0, sizeof(ops));
+       ops.be_ops        = be_ops;
+       ops.dump_node     = sparc_dump_node;
+       ops.node_cmp_attr = cmp_attr_sparc_jmp_switch;
+       ops.copy_attr = sparc_copy_attr;
+       op_sparc_SwitchJmp = new_ir_op(cur_opcode + iro_sparc_SwitchJmp, "sparc_SwitchJmp", op_pin_state_pinned, L|X|Y|M, oparity_unary, 0, sizeof(sparc_jmp_switch_attr_t), &ops);
+       set_op_tag(op_sparc_SwitchJmp, sparc_op_tag);
+
+       memset(&ops, 0, sizeof(ops));
+       ops.be_ops        = be_ops;
+       ops.dump_node     = sparc_dump_node;
+       ops.node_cmp_attr = cmp_attr_sparc_cmp;
+       ops.copy_attr = sparc_copy_attr;
+       op_sparc_Cmp = new_ir_op(cur_opcode + iro_sparc_Cmp, "sparc_Cmp", op_pin_state_floats, N|M, oparity_zero, 0, sizeof(sparc_cmp_attr_t), &ops);
+       set_op_tag(op_sparc_Cmp, sparc_op_tag);
+
+       memset(&ops, 0, sizeof(ops));
+       ops.be_ops        = be_ops;
+       ops.dump_node     = sparc_dump_node;
+       ops.node_cmp_attr = cmp_attr_sparc_symconst;
+       ops.copy_attr = sparc_copy_attr;
+       op_sparc_SymConst = new_ir_op(cur_opcode + iro_sparc_SymConst, "sparc_SymConst", op_pin_state_floats, c|M, oparity_zero, 0, sizeof(sparc_symconst_attr_t), &ops);
+       set_op_tag(op_sparc_SymConst, sparc_op_tag);
+
+       memset(&ops, 0, sizeof(ops));
+       ops.be_ops        = be_ops;
+       ops.dump_node     = sparc_dump_node;
+       ops.node_cmp_attr = cmp_attr_sparc;
+       ops.copy_attr = sparc_copy_attr;
+       op_sparc_Sub = new_ir_op(cur_opcode + iro_sparc_Sub, "sparc_Sub", op_pin_state_floats, N|M, oparity_binary, 0, sizeof(sparc_attr_t), &ops);
+       set_op_tag(op_sparc_Sub, sparc_op_tag);
+
+       memset(&ops, 0, sizeof(ops));
+       ops.be_ops        = be_ops;
+       ops.dump_node     = sparc_dump_node;
+       ops.node_cmp_attr = cmp_attr_sparc_load_store;
+       ops.copy_attr = sparc_copy_attr;
+       op_sparc_Load = new_ir_op(cur_opcode + iro_sparc_Load, "sparc_Load", op_pin_state_exc_pinned, L|F|M, oparity_binary, 0, sizeof(sparc_load_store_attr_t), &ops);
+       set_op_tag(op_sparc_Load, sparc_op_tag);
+
+       memset(&ops, 0, sizeof(ops));
+       ops.be_ops        = be_ops;
+       ops.dump_node     = sparc_dump_node;
+       ops.node_cmp_attr = cmp_attr_sparc;
+       ops.copy_attr = sparc_copy_attr;
+       op_sparc_AddSP = new_ir_op(cur_opcode + iro_sparc_AddSP, "sparc_AddSP", op_pin_state_floats, N|M, oparity_trinary, 0, sizeof(sparc_attr_t), &ops);
+       set_op_tag(op_sparc_AddSP, sparc_op_tag);
+
+       sparc_opcode_end = cur_opcode + iro_sparc_last;
+}
diff --git a/ir/be/sparc/gen_sparc_new_nodes.h b/ir/be/sparc/gen_sparc_new_nodes.h
new file mode 100644 (file)
index 0000000..164bb55
--- /dev/null
@@ -0,0 +1,210 @@
+/**
+ * @file
+ * @brief Function prototypes for the new opcode functions.
+ * @note  DO NOT EDIT THIS FILE, your changes will be lost.
+ *        Edit libfirm/ir/be/sparc/sparc_spec.pl instead.
+ *        created by: libfirm/ir/be/scripts/generate_new_opcodes.pl libfirm/ir/be/sparc/sparc_spec.pl libfirm/ir/be/sparc
+ * @date  Tue Dec 15 15:19:15 2009
+ */
+#ifndef FIRM_BE_SPARC_GEN_SPARC_NEW_NODES_H
+#define FIRM_BE_SPARC_GEN_SPARC_NEW_NODES_H
+
+typedef enum _sparc_opcodes {
+       iro_sparc_SubSP,
+       iro_sparc_Add,
+       iro_sparc_FrameAddr,
+       iro_sparc_Store,
+       iro_sparc_Branch,
+       iro_sparc_Mov,
+       iro_sparc_Tst,
+       iro_sparc_SwitchJmp,
+       iro_sparc_Cmp,
+       iro_sparc_SymConst,
+       iro_sparc_Sub,
+       iro_sparc_Load,
+       iro_sparc_AddSP,
+       iro_sparc_last_generated,
+       iro_sparc_last = iro_sparc_last_generated
+} sparc_opcodes;
+
+int is_sparc_irn(const ir_node *node);
+
+int get_sparc_opcode_first(void);
+int get_sparc_opcode_last(void);
+int get_sparc_irn_opcode(const ir_node *node);
+void sparc_create_opcodes(const arch_irn_ops_t *be_ops);
+extern ir_op *op_sparc_SubSP;
+ir_op *get_op_sparc_SubSP(void);
+int is_sparc_SubSP(const ir_node *n);
+/**
+ * free stack space
+ */
+ir_node *new_bd_sparc_SubSP(dbg_info *dbgi, ir_node *block, ir_node *stack, ir_node *size, ir_node *mem);
+
+extern ir_op *op_sparc_Add;
+ir_op *get_op_sparc_Add(void);
+int is_sparc_Add(const ir_node *n);
+/**
+ * construct Add node
+ */
+ir_node *new_bd_sparc_Add_imm(dbg_info *dbgi, ir_node *block, ir_node *left, int immediate_value);
+/**
+ * construct Add node
+ */
+ir_node *new_bd_sparc_Add_reg(dbg_info *dbgi, ir_node *block, ir_node *left, ir_node *right);
+
+extern ir_op *op_sparc_FrameAddr;
+ir_op *get_op_sparc_FrameAddr(void);
+int is_sparc_FrameAddr(const ir_node *n);
+/**
+ * construct FrameAddr node
+ */
+ir_node *new_bd_sparc_FrameAddr(dbg_info *dbgi, ir_node *block, ir_node *base, ir_entity *entity);
+
+extern ir_op *op_sparc_Store;
+ir_op *get_op_sparc_Store(void);
+int is_sparc_Store(const ir_node *n);
+/**
+ * construct Store: Store(ptr, val, mem) = ST ptr,val
+ */
+ir_node *new_bd_sparc_Store(dbg_info *dbgi, ir_node *block, ir_node *ptr, ir_node *val, ir_node *mem, ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity);
+
+extern ir_op *op_sparc_Branch;
+ir_op *get_op_sparc_Branch(void);
+int is_sparc_Branch(const ir_node *n);
+/**
+ * construct Branch node
+ */
+ir_node *new_bd_sparc_Branch(dbg_info *dbgi, ir_node *block, ir_node *op0, int proj_num);
+
+extern ir_op *op_sparc_Mov;
+ir_op *get_op_sparc_Mov(void);
+int is_sparc_Mov(const ir_node *n);
+/**
+ * construct Mov node
+ */
+ir_node *new_bd_sparc_Mov_imm(dbg_info *dbgi, ir_node *block, int immediate_value);
+/**
+ * construct Mov node
+ */
+ir_node *new_bd_sparc_Mov_reg(dbg_info *dbgi, ir_node *block, ir_node *op0);
+
+extern ir_op *op_sparc_Tst;
+ir_op *get_op_sparc_Tst(void);
+int is_sparc_Tst(const ir_node *n);
+/**
+ * construct Tst node
+ */
+ir_node *new_bd_sparc_Tst(dbg_info *dbgi, ir_node *block, ir_node *left, bool ins_permuted, bool is_unsigned);
+
+extern ir_op *op_sparc_SwitchJmp;
+ir_op *get_op_sparc_SwitchJmp(void);
+int is_sparc_SwitchJmp(const ir_node *n);
+/**
+ * construct SwitchJmp node
+ */
+ir_node *new_bd_sparc_SwitchJmp(dbg_info *dbgi, ir_node *block, ir_node *op0, int n_projs, long def_proj_num);
+
+extern ir_op *op_sparc_Cmp;
+ir_op *get_op_sparc_Cmp(void);
+int is_sparc_Cmp(const ir_node *n);
+/**
+ * construct Cmp node
+ */
+ir_node *new_bd_sparc_Cmp_imm(dbg_info *dbgi, ir_node *block, ir_node *left, int immediate_value, bool ins_permuted, bool is_unsigned);
+/**
+ * construct Cmp node
+ */
+ir_node *new_bd_sparc_Cmp_reg(dbg_info *dbgi, ir_node *block, ir_node *left, ir_node *right, bool ins_permuted, bool is_unsigned);
+
+extern ir_op *op_sparc_SymConst;
+ir_op *get_op_sparc_SymConst(void);
+int is_sparc_SymConst(const ir_node *n);
+/**
+ * construct SymConst node
+ */
+ir_node *new_bd_sparc_SymConst(dbg_info *dbgi, ir_node *block, ir_entity *entity);
+
+extern ir_op *op_sparc_Sub;
+ir_op *get_op_sparc_Sub(void);
+int is_sparc_Sub(const ir_node *n);
+/**
+ * construct Sub node
+ */
+ir_node *new_bd_sparc_Sub_imm(dbg_info *dbgi, ir_node *block, ir_node *left, int immediate_value);
+/**
+ * construct Sub node
+ */
+ir_node *new_bd_sparc_Sub_reg(dbg_info *dbgi, ir_node *block, ir_node *left, ir_node *right);
+
+extern ir_op *op_sparc_Load;
+ir_op *get_op_sparc_Load(void);
+int is_sparc_Load(const ir_node *n);
+/**
+ * construct Load: Load(ptr, mem) = LD ptr -> reg
+ */
+ir_node *new_bd_sparc_Load(dbg_info *dbgi, ir_node *block, ir_node *ptr, ir_node *mem, ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity);
+
+extern ir_op *op_sparc_AddSP;
+ir_op *get_op_sparc_AddSP(void);
+int is_sparc_AddSP(const ir_node *n);
+/**
+ * alloc stack space
+ */
+ir_node *new_bd_sparc_AddSP(dbg_info *dbgi, ir_node *block, ir_node *stack, ir_node *size, ir_node *mem);
+
+
+
+enum pn_sparc_SubSP {
+       pn_sparc_SubSP_stack = 0,
+       pn_sparc_SubSP_M = 1,
+};
+
+enum n_sparc_SubSP {
+       n_sparc_SubSP_stack = 0,
+       n_sparc_SubSP_size = 1,
+       n_sparc_SubSP_mem = 2,
+};
+
+enum n_sparc_FrameAddr {
+       n_sparc_FrameAddr_base = 0,
+};
+
+enum pn_sparc_Store {
+       pn_sparc_Store_mem = 0,
+};
+
+enum n_sparc_Store {
+       n_sparc_Store_ptr = 0,
+       n_sparc_Store_val = 1,
+       n_sparc_Store_mem = 2,
+};
+
+enum n_sparc_Tst {
+       n_sparc_Tst_left = 0,
+};
+
+enum pn_sparc_Load {
+       pn_sparc_Load_res = 0,
+       pn_sparc_Load_M = 1,
+};
+
+enum n_sparc_Load {
+       n_sparc_Load_ptr = 0,
+       n_sparc_Load_mem = 1,
+};
+
+enum pn_sparc_AddSP {
+       pn_sparc_AddSP_stack = 0,
+       pn_sparc_AddSP_addr = 1,
+       pn_sparc_AddSP_M = 2,
+};
+
+enum n_sparc_AddSP {
+       n_sparc_AddSP_stack = 0,
+       n_sparc_AddSP_size = 1,
+       n_sparc_AddSP_mem = 2,
+};
+
+
+#endif
diff --git a/ir/be/sparc/gen_sparc_regalloc_if.c b/ir/be/sparc/gen_sparc_regalloc_if.c
new file mode 100644 (file)
index 0000000..13951ae
--- /dev/null
@@ -0,0 +1,1039 @@
+/**
+ * @file
+ * @brief  The generated interface for the register allocator.
+ *          Contains register classes and types and register constraints
+ *          for all nodes where constraints were given in spec.
+ * @note    DO NOT EDIT THIS FILE, your changes will be lost.
+ *          Edit libfirm/ir/be/sparc/sparc_spec.pl instead.
+ *          created by: libfirm/ir/be/scripts/generate_regalloc_if.pl libfirm/ir/be/sparc/sparc_spec.pl libfirm/ir/be/sparc
+ * $date    Tue Dec 15 15:19:15 2009
+ */
+#include "config.h"
+
+#include "gen_sparc_regalloc_if.h"
+#include "gen_sparc_machine.h"
+#include "bearch_sparc_t.h"
+#include "irmode.h"
+
+static const arch_register_req_t sparc_class_reg_req_flags;
+static const arch_register_req_t sparc_class_reg_req_gp;
+static const arch_register_req_t sparc_class_reg_req_fp;
+
+arch_register_class_t sparc_reg_classes[] = {
+       { 0, "sparc_flags", N_sparc_flags_REGS, NULL, sparc_flags_regs, arch_register_class_flag_manual_ra, &sparc_class_reg_req_flags },
+       { 1, "sparc_gp", N_sparc_gp_REGS, NULL, sparc_gp_regs, 0, &sparc_class_reg_req_gp },
+       { 2, "sparc_fp", N_sparc_fp_REGS, NULL, sparc_fp_regs, 0, &sparc_class_reg_req_fp }
+};
+
+static const arch_register_req_t sparc_class_reg_req_flags = {
+       arch_register_req_type_normal,
+       &sparc_reg_classes[CLASS_sparc_flags],
+       NULL,
+       0,
+       0
+};
+static const unsigned sparc_limited_flags_y [] = { (1 << REG_Y) };
+static const arch_register_req_t sparc_single_reg_req_flags_y = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_flags],
+       sparc_limited_flags_y,
+       0,
+       0
+};
+static const arch_register_req_t sparc_class_reg_req_gp = {
+       arch_register_req_type_normal,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       NULL,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_g0 [] = { (1 << REG_G0), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_g0 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_g0,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_g1 [] = { (1 << REG_G1), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_g1 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_g1,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_g2 [] = { (1 << REG_G2), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_g2 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_g2,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_g3 [] = { (1 << REG_G3), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_g3 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_g3,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_g4 [] = { (1 << REG_G4), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_g4 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_g4,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_g5 [] = { (1 << REG_G5), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_g5 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_g5,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_g6 [] = { (1 << REG_G6), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_g6 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_g6,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_g7 [] = { (1 << REG_G7), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_g7 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_g7,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_o0 [] = { (1 << REG_O0), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_o0 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_o0,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_o1 [] = { (1 << REG_O1), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_o1 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_o1,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_o2 [] = { (1 << REG_O2), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_o2 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_o2,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_o3 [] = { (1 << REG_O3), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_o3 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_o3,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_o4 [] = { (1 << REG_O4), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_o4 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_o4,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_o5 [] = { (1 << REG_O5), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_o5 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_o5,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_sp [] = { (1 << REG_SP), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_sp = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_sp,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_o7 [] = { (1 << REG_O7), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_o7 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_o7,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_l0 [] = { (1 << REG_L0), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_l0 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_l0,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_l1 [] = { (1 << REG_L1), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_l1 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_l1,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_l2 [] = { (1 << REG_L2), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_l2 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_l2,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_l3 [] = { (1 << REG_L3), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_l3 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_l3,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_l4 [] = { (1 << REG_L4), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_l4 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_l4,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_l5 [] = { (1 << REG_L5), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_l5 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_l5,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_l6 [] = { (1 << REG_L6), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_l6 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_l6,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_l7 [] = { (1 << REG_L7), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_l7 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_l7,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_i0 [] = { (1 << REG_I0), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_i0 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_i0,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_i1 [] = { (1 << REG_I1), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_i1 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_i1,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_i2 [] = { (1 << REG_I2), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_i2 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_i2,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_i3 [] = { (1 << REG_I3), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_i3 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_i3,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_i4 [] = { (1 << REG_I4), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_i4 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_i4,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_i5 [] = { (1 << REG_I5), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_i5 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_i5,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_fp [] = { (1 << REG_FP), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_fp = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_fp,
+       0,
+       0
+};
+static const unsigned sparc_limited_gp_i7 [] = { (1 << REG_I7), 0 };
+static const arch_register_req_t sparc_single_reg_req_gp_i7 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_gp],
+       sparc_limited_gp_i7,
+       0,
+       0
+};
+static const arch_register_req_t sparc_class_reg_req_fp = {
+       arch_register_req_type_normal,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       NULL,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f0 [] = { (1 << REG_F0), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f0 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f0,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f1 [] = { (1 << REG_F1), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f1 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f1,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f2 [] = { (1 << REG_F2), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f2 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f2,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f3 [] = { (1 << REG_F3), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f3 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f3,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f4 [] = { (1 << REG_F4), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f4 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f4,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f5 [] = { (1 << REG_F5), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f5 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f5,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f6 [] = { (1 << REG_F6), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f6 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f6,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f7 [] = { (1 << REG_F7), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f7 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f7,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f8 [] = { (1 << REG_F8), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f8 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f8,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f9 [] = { (1 << REG_F9), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f9 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f9,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f10 [] = { (1 << REG_F10), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f10 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f10,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f11 [] = { (1 << REG_F11), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f11 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f11,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f12 [] = { (1 << REG_F12), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f12 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f12,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f13 [] = { (1 << REG_F13), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f13 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f13,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f14 [] = { (1 << REG_F14), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f14 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f14,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f15 [] = { (1 << REG_F15), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f15 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f15,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f16 [] = { (1 << REG_F16), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f16 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f16,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f17 [] = { (1 << REG_F17), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f17 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f17,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f18 [] = { (1 << REG_F18), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f18 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f18,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f19 [] = { (1 << REG_F19), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f19 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f19,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f20 [] = { (1 << REG_F20), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f20 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f20,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f21 [] = { (1 << REG_F21), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f21 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f21,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f22 [] = { (1 << REG_F22), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f22 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f22,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f23 [] = { (1 << REG_F23), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f23 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f23,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f24 [] = { (1 << REG_F24), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f24 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f24,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f25 [] = { (1 << REG_F25), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f25 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f25,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f26 [] = { (1 << REG_F26), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f26 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f26,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f27 [] = { (1 << REG_F27), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f27 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f27,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f28 [] = { (1 << REG_F28), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f28 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f28,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f29 [] = { (1 << REG_F29), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f29 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f29,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f30 [] = { (1 << REG_F30), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f30 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f30,
+       0,
+       0
+};
+static const unsigned sparc_limited_fp_f31 [] = { (1 << REG_F31), 0 };
+static const arch_register_req_t sparc_single_reg_req_fp_f31 = {
+       arch_register_req_type_limited,
+       &sparc_reg_classes[CLASS_sparc_fp],
+       sparc_limited_fp_f31,
+       0,
+       0
+};
+
+const arch_register_t sparc_flags_regs[N_sparc_flags_REGS] = {
+       {
+               "y",
+               &sparc_reg_classes[CLASS_sparc_flags],
+               REG_Y,
+               arch_register_type_ignore,
+               &sparc_single_reg_req_flags_y
+       },
+};
+const arch_register_t sparc_gp_regs[N_sparc_gp_REGS] = {
+       {
+               "r0",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_G0,
+               arch_register_type_ignore,
+               &sparc_single_reg_req_gp_g0
+       },
+       {
+               "r1",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_G1,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_gp_g1
+       },
+       {
+               "r2",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_G2,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_gp_g2
+       },
+       {
+               "r3",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_G3,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_gp_g3
+       },
+       {
+               "r4",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_G4,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_gp_g4
+       },
+       {
+               "r5",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_G5,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_gp_g5
+       },
+       {
+               "r6",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_G6,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_gp_g6
+       },
+       {
+               "r7",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_G7,
+               arch_register_type_callee_save,
+               &sparc_single_reg_req_gp_g7
+       },
+       {
+               "r8",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_O0,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_gp_o0
+       },
+       {
+               "r9",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_O1,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_gp_o1
+       },
+       {
+               "r10",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_O2,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_gp_o2
+       },
+       {
+               "r11",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_O3,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_gp_o3
+       },
+       {
+               "r12",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_O4,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_gp_o4
+       },
+       {
+               "r13",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_O5,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_gp_o5
+       },
+       {
+               "r14",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_SP,
+               arch_register_type_ignore,
+               &sparc_single_reg_req_gp_sp
+       },
+       {
+               "r15",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_O7,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_gp_o7
+       },
+       {
+               "r16",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_L0,
+               arch_register_type_callee_save,
+               &sparc_single_reg_req_gp_l0
+       },
+       {
+               "r17",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_L1,
+               arch_register_type_callee_save,
+               &sparc_single_reg_req_gp_l1
+       },
+       {
+               "r18",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_L2,
+               arch_register_type_callee_save,
+               &sparc_single_reg_req_gp_l2
+       },
+       {
+               "r19",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_L3,
+               arch_register_type_callee_save,
+               &sparc_single_reg_req_gp_l3
+       },
+       {
+               "r20",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_L4,
+               arch_register_type_callee_save,
+               &sparc_single_reg_req_gp_l4
+       },
+       {
+               "r21",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_L5,
+               arch_register_type_callee_save,
+               &sparc_single_reg_req_gp_l5
+       },
+       {
+               "r22",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_L6,
+               arch_register_type_callee_save,
+               &sparc_single_reg_req_gp_l6
+       },
+       {
+               "r23",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_L7,
+               arch_register_type_callee_save,
+               &sparc_single_reg_req_gp_l7
+       },
+       {
+               "r24",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_I0,
+               arch_register_type_callee_save,
+               &sparc_single_reg_req_gp_i0
+       },
+       {
+               "r25",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_I1,
+               arch_register_type_callee_save,
+               &sparc_single_reg_req_gp_i1
+       },
+       {
+               "r26",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_I2,
+               arch_register_type_callee_save,
+               &sparc_single_reg_req_gp_i2
+       },
+       {
+               "r27",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_I3,
+               arch_register_type_callee_save,
+               &sparc_single_reg_req_gp_i3
+       },
+       {
+               "r28",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_I4,
+               arch_register_type_callee_save,
+               &sparc_single_reg_req_gp_i4
+       },
+       {
+               "r29",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_I5,
+               arch_register_type_callee_save,
+               &sparc_single_reg_req_gp_i5
+       },
+       {
+               "r30",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_FP,
+               arch_register_type_ignore,
+               &sparc_single_reg_req_gp_fp
+       },
+       {
+               "r31",
+               &sparc_reg_classes[CLASS_sparc_gp],
+               REG_I7,
+               arch_register_type_callee_save,
+               &sparc_single_reg_req_gp_i7
+       },
+};
+const arch_register_t sparc_fp_regs[N_sparc_fp_REGS] = {
+       {
+               "f0",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F0,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f0
+       },
+       {
+               "f1",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F1,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f1
+       },
+       {
+               "f2",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F2,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f2
+       },
+       {
+               "f3",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F3,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f3
+       },
+       {
+               "f4",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F4,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f4
+       },
+       {
+               "f5",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F5,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f5
+       },
+       {
+               "f6",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F6,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f6
+       },
+       {
+               "f7",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F7,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f7
+       },
+       {
+               "f8",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F8,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f8
+       },
+       {
+               "f9",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F9,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f9
+       },
+       {
+               "f10",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F10,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f10
+       },
+       {
+               "f11",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F11,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f11
+       },
+       {
+               "f12",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F12,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f12
+       },
+       {
+               "f13",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F13,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f13
+       },
+       {
+               "f14",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F14,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f14
+       },
+       {
+               "f15",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F15,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f15
+       },
+       {
+               "f16",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F16,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f16
+       },
+       {
+               "f17",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F17,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f17
+       },
+       {
+               "f18",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F18,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f18
+       },
+       {
+               "f19",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F19,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f19
+       },
+       {
+               "f20",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F20,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f20
+       },
+       {
+               "f21",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F21,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f21
+       },
+       {
+               "f22",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F22,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f22
+       },
+       {
+               "f23",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F23,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f23
+       },
+       {
+               "f24",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F24,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f24
+       },
+       {
+               "f25",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F25,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f25
+       },
+       {
+               "f26",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F26,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f26
+       },
+       {
+               "f27",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F27,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f27
+       },
+       {
+               "f28",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F28,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f28
+       },
+       {
+               "f29",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F29,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f29
+       },
+       {
+               "f30",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F30,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f30
+       },
+       {
+               "f31",
+               &sparc_reg_classes[CLASS_sparc_fp],
+               REG_F31,
+               arch_register_type_caller_save,
+               &sparc_single_reg_req_fp_f31
+       },
+};
+
+
+void sparc_register_init(void)
+{
+       sparc_reg_classes[CLASS_sparc_flags].mode = mode_Bu;
+       sparc_reg_classes[CLASS_sparc_gp].mode = mode_Iu;
+       sparc_reg_classes[CLASS_sparc_fp].mode = mode_D;
+
+}
diff --git a/ir/be/sparc/gen_sparc_regalloc_if.h b/ir/be/sparc/gen_sparc_regalloc_if.h
new file mode 100644 (file)
index 0000000..3b5bcc9
--- /dev/null
@@ -0,0 +1,111 @@
+/**
+ * @file
+ * @brief Contains additional external requirements defs for external includes.
+ * @note   DO NOT EDIT THIS FILE, your changes will be lost.
+ *         Edit libfirm/ir/be/sparc/sparc_spec.pl instead.
+ *         created by: libfirm/ir/be/scripts/generate_regalloc_if.pl libfirm/ir/be/sparc/sparc_spec.pl libfirm/ir/be/sparc
+ * @date   Tue Dec 15 15:19:15 2009
+ */
+#ifndef FIRM_BE_SPARC_GEN_SPARC_REGALLOC_IF_H
+#define FIRM_BE_SPARC_GEN_SPARC_REGALLOC_IF_H
+
+#include "../bearch.h"
+#include "sparc_nodes_attr.h"
+
+enum reg_sparc_flags_indices {
+       REG_Y,
+       N_sparc_flags_REGS = 1
+};
+
+enum reg_sparc_gp_indices {
+       REG_G0,
+       REG_G1,
+       REG_G2,
+       REG_G3,
+       REG_G4,
+       REG_G5,
+       REG_G6,
+       REG_G7,
+       REG_O0,
+       REG_O1,
+       REG_O2,
+       REG_O3,
+       REG_O4,
+       REG_O5,
+       REG_SP,
+       REG_O7,
+       REG_L0,
+       REG_L1,
+       REG_L2,
+       REG_L3,
+       REG_L4,
+       REG_L5,
+       REG_L6,
+       REG_L7,
+       REG_I0,
+       REG_I1,
+       REG_I2,
+       REG_I3,
+       REG_I4,
+       REG_I5,
+       REG_FP,
+       REG_I7,
+       N_sparc_gp_REGS = 32
+};
+
+enum reg_sparc_fp_indices {
+       REG_F0,
+       REG_F1,
+       REG_F2,
+       REG_F3,
+       REG_F4,
+       REG_F5,
+       REG_F6,
+       REG_F7,
+       REG_F8,
+       REG_F9,
+       REG_F10,
+       REG_F11,
+       REG_F12,
+       REG_F13,
+       REG_F14,
+       REG_F15,
+       REG_F16,
+       REG_F17,
+       REG_F18,
+       REG_F19,
+       REG_F20,
+       REG_F21,
+       REG_F22,
+       REG_F23,
+       REG_F24,
+       REG_F25,
+       REG_F26,
+       REG_F27,
+       REG_F28,
+       REG_F29,
+       REG_F30,
+       REG_F31,
+       N_sparc_fp_REGS = 32
+};
+
+
+enum reg_classes {
+       CLASS_sparc_flags = 0,
+       CLASS_sparc_gp = 1,
+       CLASS_sparc_fp = 2,
+       N_CLASSES = 3
+};
+
+
+extern const arch_register_t sparc_flags_regs[N_sparc_flags_REGS];
+extern const arch_register_t sparc_gp_regs[N_sparc_gp_REGS];
+extern const arch_register_t sparc_fp_regs[N_sparc_fp_REGS];
+
+
+extern arch_register_class_t sparc_reg_classes[N_CLASSES];
+
+void sparc_register_init(void);
+unsigned sparc_get_n_regs(void);
+
+#endif
diff --git a/ir/be/sparc/sparc_emitter.c b/ir/be/sparc/sparc_emitter.c
new file mode 100644 (file)
index 0000000..b3e9cb4
--- /dev/null
@@ -0,0 +1,634 @@
+/*
+ * 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: sparc_emitter.c 26542 2009-09-18 09:18:32Z 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 "irargs_t.h"
+#include "error.h"
+#include "raw_bitset.h"
+#include "dbginfo.h"
+
+#include "../besched.h"
+#include "../beblocksched.h"
+#include "../beirg.h"
+#include "../begnuas.h"
+#include "../be_dbgout.h"
+#include "../benode.h"
+
+#include "sparc_emitter.h"
+#include "gen_sparc_emitter.h"
+#include "sparc_nodes_attr.h"
+#include "sparc_new_nodes.h"
+
+#define SNPRINTF_BUF_LEN 128
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
+
+static set *sym_or_tv;
+
+/**
+ * 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_sparc_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 sparc_emit_immediate(const ir_node *node)
+{
+       // TODO: make sure it's a valid simm13 ?
+       const sparc_attr_t *attr = get_sparc_attr_const(node);
+       be_emit_irprintf("%d", attr->immediate_value);
+}
+
+void sparc_emit_source_register(const ir_node *node, int pos)
+{
+       const arch_register_t *reg = get_in_reg(node, pos);
+       be_emit_char('%');
+       be_emit_string(arch_register_get_name(reg));
+}
+
+void sparc_emit_dest_register(const ir_node *node, int pos)
+{
+       const arch_register_t *reg = get_out_reg(node, pos);
+       be_emit_char('%');
+       be_emit_string(arch_register_get_name(reg));
+}
+
+/**
+ * Emits either a imm or register depending on arity of node
+ * @param node
+ * @param register no (-1 if no register)
+ */
+void sparc_emit_reg_or_imm(const ir_node *node, int pos)
+{
+       if (get_irn_arity(node) > pos) {
+               // we have reg input
+               sparc_emit_source_register(node, pos);
+       } else {
+               // we have a imm input
+               sparc_emit_immediate(node);
+       }
+}
+
+void sparc_emit_offset(const ir_node *node)
+{
+       (void) node;
+}
+
+/**
+ *  Emit load mode char
+ */
+void sparc_emit_load_mode(const ir_node *node)
+{
+       const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
+    ir_mode *mode      = attr->load_store_mode;
+    int      bits      = get_mode_size_bits(mode);
+    bool     is_signed = mode_is_signed(mode);
+
+    if (bits == 16) {
+        be_emit_string(is_signed ? "sh" : "uh");
+    } else if (bits == 8) {
+        be_emit_string(is_signed ? "sb" : "ub");
+    } else if (bits == 64) {
+        be_emit_string("d");
+    } else {
+        assert(bits == 32);
+    }
+}
+
+/**
+ * Emit store mode char
+ */
+void sparc_emit_store_mode(const ir_node *node)
+{
+       const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
+    ir_mode *mode      = attr->load_store_mode;
+    int      bits      = get_mode_size_bits(mode);
+
+    if (bits == 16) {
+        be_emit_string("h");
+    } else if (bits == 8) {
+        be_emit_string("b");
+    } else if (bits == 64) {
+        be_emit_string("d");
+    } else {
+        assert(bits == 32);
+    }
+}
+
+/**
+ * Returns the target label for a control flow node.
+ */
+static void sparc_emit_cfop_target(const ir_node *node)
+{
+       ir_node *block = get_irn_link(node);
+       be_emit_irprintf("BLOCK_%ld", get_irn_node_nr(block));
+}
+
+/**
+ * Emit single entity
+ */
+static void sparc_emit_entity(ir_entity *entity)
+{
+       set_entity_backend_marked(entity, 1);
+       be_emit_ident(get_entity_ld_ident(entity));
+}
+
+/***********************************************************************************
+ *                  _          __                                             _
+ *                 (_)        / _|                                           | |
+ *  _ __ ___   __ _ _ _ __   | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
+ * | '_ ` _ \ / _` | | '_ \  |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
+ * | | | | | | (_| | | | | | | | | | | (_| | | | | | |  __/\ 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 ");
+       sparc_emit_cfop_target(node);
+       be_emit_finish_line_gas(node);
+}
+
+
+/**
+ * Emits code for stack space management
+ */
+static void emit_be_IncSP(const ir_node *irn)
+{
+       int offs = -be_get_IncSP_offset(irn);
+
+       if (offs != 0) {
+               /* SPARC stack grows downwards */
+               if (offs < 0) {
+                       be_emit_cstring("\tadd ");
+                       offs = -offs;
+               } else {
+                       be_emit_cstring("\tsub ");
+               }
+
+               sparc_emit_source_register(irn, 0);
+               be_emit_irprintf(", %d", offs);
+               be_emit_cstring(", ");
+               sparc_emit_dest_register(irn, 0);
+       } else {
+               // ignore IncSP(0)
+               //be_emit_cstring("\t/* IncSP(0) skipped */");
+               be_emit_cstring("\t/* ");
+               be_emit_cstring("sub ");
+               offs = -offs;
+               sparc_emit_source_register(irn, 0);
+               be_emit_irprintf(", %d", offs);
+               be_emit_cstring(", ");
+               sparc_emit_dest_register(irn, 0);
+               be_emit_cstring(" ignored */ ");
+       }
+
+       be_emit_finish_line_gas(irn);
+}
+
+/**
+ * Emits code for return node
+ */
+static void emit_be_Return(const ir_node *irn)
+{
+       be_emit_cstring("\tret");
+       be_emit_finish_line_gas(irn);
+}
+
+/**
+ * Emits code for Call node
+ */
+static void emit_be_Call(const ir_node *irn)
+{
+       ir_entity *entity = be_Call_get_entity(irn);
+
+       if (entity != NULL) {
+               be_emit_cstring("\tcall ");
+           sparc_emit_entity(entity);
+               be_emit_finish_line_gas(irn);
+               be_emit_cstring("\tnop\t /* TODO: use delay slot */\n ");
+       } else {
+               be_emit_cstring("\tnop\t /* TODO: Entity == NULL */\n ");
+               /*
+               be_emit_cstring("\tmov lr, pc");
+               be_emit_finish_line_gas(irn);
+               be_emit_cstring("\tmov pc, ");
+               sparc_emit_source_register(irn, be_pos_Call_ptr);
+               */
+               be_emit_finish_line_gas(irn);
+       }
+}
+
+/** An entry in the sym_or_tv set. */
+typedef struct sym_or_tv_t {
+       union {
+               ident  *id;          /**< An ident. */
+               tarval *tv;          /**< A tarval. */
+               const void *generic; /**< For generic compare. */
+       } u;
+       unsigned label;      /**< the associated label. */
+       char is_ident;       /**< Non-zero if an ident is stored. */
+} sym_or_tv_t;
+
+/**
+ * Returns a unique label. This number will not be used a second time.
+ */
+static unsigned get_unique_label(void) {
+       static unsigned id = 0;
+       return ++id;
+}
+
+/**
+ * Emit a SymConst.
+ */
+static void emit_sparc_SymConst(const ir_node *irn)
+{
+       const sparc_symconst_attr_t *attr = get_sparc_symconst_attr_const(irn);
+       sym_or_tv_t key, *entry;
+       unsigned label;
+
+       set_entity_backend_marked(attr->entity, 1);
+
+       key.u.id     = get_entity_ld_ident(attr->entity);
+       key.is_ident = 1;
+       key.label    = 0;
+       entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
+       if (entry->label == 0) {
+               /* allocate a label */
+               entry->label = get_unique_label();
+       }
+
+       label = entry->label;
+
+       /* load the symbol indirect */
+       be_emit_cstring("\tld ");
+       be_emit_irprintf(".L%u, ", label);
+       sparc_emit_dest_register(irn, 0);
+       be_emit_finish_line_gas(irn);
+}
+
+
+/**
+ * Emits code for FrameAddr fix
+ */
+static void emit_sparc_FrameAddr(const ir_node *irn)
+{
+       const sparc_symconst_attr_t *attr = get_irn_generic_attr_const(irn);
+       be_emit_cstring("\tadd ");
+       sparc_emit_source_register(irn, 0);
+       be_emit_cstring(", ");
+       sparc_emit_dest_register(irn, 0);
+       be_emit_cstring(", ");
+       be_emit_irprintf("#0x%X", attr->fp_offset);
+       be_emit_finish_line_gas(irn);
+}
+
+
+/**
+ * Emits code for Branch
+ */
+static void emit_sparc_Branch(const ir_node *irn)
+{
+       (void) irn;
+}
+
+/**
+ * dummy emitter for ignored nodes
+ */
+static void emit_nothing(const ir_node *irn)
+{
+       (void) irn;
+}
+
+
+
+/**
+ * type of emitter function
+ */
+typedef void (*emit_func) (const ir_node *);
+
+/**
+ * Set a node emitter. Make it a bit more type safe.
+ */
+static inline void set_emitter(ir_op *op, emit_func sparc_emit_node)
+{
+       op->ops.generic = (op_func)sparc_emit_node;
+}
+
+/**
+ * Enters the emitter functions for handled nodes into the generic
+ * pointer of an opcode.
+ */
+static void sparc_register_emitters(void)
+{
+
+       /* first clear the generic function pointer for all ops */
+       clear_irp_opcodes_generic_func();
+
+       /* register all emitter functions defined in spec */
+       sparc_register_spec_emitters();
+
+       /* custom emitter */
+    set_emitter(op_be_IncSP,       emit_be_IncSP);
+    set_emitter(op_be_Return,      emit_be_Return);
+    set_emitter(op_be_Call,        emit_be_Call);
+    set_emitter(op_sparc_FrameAddr,  emit_sparc_FrameAddr);
+    set_emitter(op_sparc_Branch,   emit_sparc_Branch);
+    set_emitter(op_sparc_SymConst,   emit_sparc_SymConst);
+
+/*
+    set_emitter(op_arm_B,          emit_arm_B);
+    set_emitter(op_arm_CopyB,      emit_arm_CopyB);
+    set_emitter(op_arm_fpaConst,   emit_arm_fpaConst);
+    set_emitter(op_arm_fpaDbl2GP,  emit_arm_fpaDbl2GP);
+    set_emitter(op_arm_Jmp,        emit_arm_Jmp);
+    set_emitter(op_arm_LdTls,      emit_arm_LdTls);
+    set_emitter(op_arm_SwitchJmp,  emit_arm_SwitchJmp);
+    set_emitter(op_be_Copy,        emit_be_Copy);
+    set_emitter(op_be_CopyKeep,    emit_be_Copy);
+    set_emitter(op_be_MemPerm,     emit_be_MemPerm);
+    set_emitter(op_be_Perm,        emit_be_Perm);
+*/
+    /* 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);
+       set_emitter(op_be_Barrier,     emit_nothing);
+
+}
+
+/**
+ * Emits code for a node.
+ */
+void sparc_emit_node(const ir_node *node)
+{
+       ir_op               *op       = get_irn_op(node);
+
+       if (op->ops.generic) {
+               emit_func func = (emit_func) op->ops.generic;
+               be_dbg_set_dbg_info(get_irn_dbg_info(node));
+               (*func) (node);
+       } else {
+               panic("Error: No emit handler for node %+F (graph %+F)\n",
+                       node, current_ir_graph);
+       }
+}
+
+/**
+ * Walks over the nodes in a block connected by scheduling edges
+ * and emits code for each node.
+ */
+void sparc_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) {
+               sparc_emit_node(node);
+       }
+}
+
+
+/**
+ * Emits code for function start.
+ */
+void sparc_emit_func_prolog(ir_graph *irg) {
+       ir_entity *ent = get_irg_entity(irg);
+       const char *irg_name = get_entity_ld_name(ent);
+
+       /* TODO: emit function header */
+       be_emit_cstring("# -- Begin ");
+       be_emit_string(irg_name);
+       be_emit_cstring("\n");
+
+
+       be_emit_write_line();
+       be_gas_emit_switch_section(GAS_SECTION_TEXT);
+       be_emit_cstring("\t.align  4\n");
+
+       if (get_entity_visibility(ent) == visibility_external_visible)
+               be_emit_irprintf("\t.global %s\n", irg_name);
+
+       be_emit_cstring("\t/* .proc  n - n specifies which registers will contain the return value upon return from the procedure */\n");
+       be_emit_irprintf("\t.type %s, #function\n", irg_name);
+
+       be_emit_irprintf("%s:\n", irg_name);
+       // TODO: fetch reg names via API func
+       // TODO: move value to SPARC_MIN_STACKSIZE const
+       be_emit_cstring("\tsave %r14, -64, %r14");
+       be_emit_cstring("\t/* incr CWP and alloc min. required stack space */\n");
+       be_emit_write_line();
+}
+
+/**
+ * Emits code for function end
+ */
+void sparc_emit_func_epilog(ir_graph *irg) {
+       ir_entity *ent = get_irg_entity(irg);
+       const char *irg_name = get_entity_ld_name(ent);
+
+       be_emit_cstring("\trestore");
+       be_emit_cstring("\t/* decr CWP */\n");
+       be_emit_irprintf("\t.size  %s, .-%s\n", irg_name, irg_name);
+       be_emit_cstring("# -- End ");
+       be_emit_string(irg_name);
+       be_emit_cstring("\n");
+       be_emit_write_line();
+}
+
+/**
+ * Sets labels for control flow nodes (jump target)
+ * TODO: Jump optimization
+ */
+void sparc_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);
+       }
+}
+
+/**
+ * Compare two entries of the symbol or tarval set.
+ */
+static int cmp_sym_or_tv(const void *elt, const void *key, size_t size) {
+       const sym_or_tv_t *p1 = elt;
+       const sym_or_tv_t *p2 = key;
+       (void) size;
+
+       /* as an identifier NEVER can point to a tarval, it's enough
+               to compare it this way */
+       return p1->u.generic != p2->u.generic;
+}
+
+void gen_symconst_values()
+{
+       sym_or_tv = new_set(cmp_sym_or_tv, 8);
+
+       /* emit SymConst values */
+       if (set_count(sym_or_tv) > 0) {
+               sym_or_tv_t *entry;
+
+               be_emit_cstring("\t.align 2\n");
+
+               foreach_set(sym_or_tv, entry) {
+                       be_emit_irprintf(".L%u:\n", entry->label);
+
+                       if (entry->is_ident) {
+                               be_emit_cstring("\t.word\t");
+                               be_emit_ident(entry->u.id);
+                               be_emit_char('\n');
+                               be_emit_write_line();
+                       } else {
+                               tarval *tv = entry->u.tv;
+                               int i, size = get_mode_size_bytes(get_tarval_mode(tv));
+                               unsigned v;
+
+                               /* TODO: beware: ARM fpa uses big endian format */
+                               for (i = ((size + 3) & ~3) - 4; i >= 0; i -= 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);
+                                       be_emit_irprintf("\t.word\t%u\n", v);
+                                       be_emit_write_line();
+                               }
+                       }
+               }
+               be_emit_char('\n');
+               be_emit_write_line();
+       }
+       del_set(sym_or_tv);
+}
+
+/**
+ * Main driver
+ */
+void sparc_gen_routine(const sparc_code_gen_t *cg, ir_graph *irg)
+{
+       ir_entity *entity     = get_irg_entity(irg);
+
+       /* register all emitter functions */
+       sparc_register_emitters();
+       be_dbg_method_begin(entity, be_abi_get_stack_layout(cg->birg->abi));
+       sparc_emit_func_prolog(irg);
+       irg_block_walk_graph(irg, sparc_gen_labels, NULL, NULL);
+       irg_walk_blkwise_graph(irg, NULL, sparc_gen_block, NULL);
+       sparc_emit_func_epilog(irg);
+
+       gen_symconst_values();
+}
+
+void sparc_init_emitter(void)
+{
+       FIRM_DBG_REGISTER(dbg, "firm.be.sparc.emit");
+}
diff --git a/ir/be/sparc/sparc_emitter.h b/ir/be/sparc/sparc_emitter.h
new file mode 100644 (file)
index 0000000..e2637c9
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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: TEMPLATE_emitter.h 26317 2009-08-05 10:53:46Z matze $
+ */
+#ifndef FIRM_BE_TEMPLATE_TEMPLATE_EMITTER_H
+#define FIRM_BE_TEMPLATE_TEMPLATE_EMITTER_H
+
+#include "irargs_t.h"
+#include "irnode.h"
+#include "debug.h"
+
+#include "../bearch.h"
+#include "../beemitter.h"
+
+#include "bearch_sparc_t.h"
+
+//int get_TEMPLATE_reg_nr(ir_node *irn, int posi, int in_out);
+//const char *get_TEMPLATE_in_reg_name(ir_node *irn, int pos);
+
+void sparc_emit_immediate(const ir_node *node);
+void sparc_emit_mode(const ir_node *node);
+void sparc_emit_source_register(const ir_node *node, int pos);
+void sparc_emit_reg_or_imm(const ir_node *node, int pos);
+void sparc_emit_dest_register(const ir_node *node, int pos);
+void sparc_emit_offset(const ir_node *node);
+void sparc_emit_load_mode(const ir_node *node);
+void sparc_emit_store_mode(const ir_node *node);
+
+void sparc_gen_routine(const sparc_code_gen_t *cg, ir_graph *irg);
+
+void sparc_init_emitter(void);
+
+#endif
diff --git a/ir/be/sparc/sparc_new_nodes.c b/ir/be/sparc/sparc_new_nodes.c
new file mode 100644 (file)
index 0000000..02d275e
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * 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 sparc
+ *          assembler irg.
+ * @version $Id: TEMPLATE_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 "sparc_nodes_attr.h"
+#include "sparc_new_nodes.h"
+#include "gen_sparc_regalloc_if.h"
+
+/**
+ * Dumper interface for dumping sparc 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 sparc_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;
+}
+
+/* ATTRIBUTE INIT SETTERS / HELPERS */
+static void sparc_set_attr_imm(ir_node *res, int immediate_value)
+{
+       sparc_attr_t *attr = get_irn_generic_attr(res);
+       attr->immediate_value = immediate_value;
+}
+
+static void set_sparc_jmp_cond_proj_num(ir_node *node, int proj_num)
+{
+       sparc_jmp_cond_attr_t *attr = get_sparc_jmp_cond_attr(node);
+       attr->proj_num = proj_num;
+}
+
+static void set_sparc_jmp_switch_n_projs(ir_node *node, int n_projs)
+{
+       sparc_jmp_switch_attr_t *attr = get_sparc_jmp_switch_attr(node);
+       attr->n_projs = n_projs;
+}
+
+static void set_sparc_jmp_switch_default_proj_num(ir_node *node, long def_proj_num)
+{
+       sparc_jmp_switch_attr_t *attr = get_sparc_jmp_switch_attr(node);
+       attr->default_proj_num = def_proj_num;
+}
+
+
+/* ATTRIBUTE GETTERS */
+sparc_attr_t *get_sparc_attr(ir_node *node)
+{
+       assert(is_sparc_irn(node) && "need sparc node to get attributes");
+       return (sparc_attr_t *)get_irn_generic_attr(node);
+}
+
+const sparc_attr_t *get_sparc_attr_const(const ir_node *node)
+{
+       assert(is_sparc_irn(node) && "need sparc node to get attributes");
+       return (const sparc_attr_t *)get_irn_generic_attr_const(node);
+}
+
+
+
+sparc_load_store_attr_t *get_sparc_load_store_attr(ir_node *node)
+{
+       assert(is_sparc_irn(node) && "need sparc node to get attributes");
+       return (sparc_load_store_attr_t *)get_irn_generic_attr_const(node);
+}
+
+const sparc_load_store_attr_t *get_sparc_load_store_attr_const(const ir_node *node)
+{
+       assert(is_sparc_irn(node) && "need sparc node to get attributes");
+       return (const sparc_load_store_attr_t *)get_irn_generic_attr_const(node);
+}
+
+
+
+sparc_symconst_attr_t *get_sparc_symconst_attr(ir_node *node)
+{
+       assert((is_sparc_SymConst(node)  || is_sparc_FrameAddr(node)) && "need sparc SymConst/FrameAddr node to get attributes");
+       return (sparc_symconst_attr_t *)get_irn_generic_attr_const(node);
+}
+
+const sparc_symconst_attr_t *get_sparc_symconst_attr_const(const ir_node *node)
+{
+       assert((is_sparc_SymConst(node)  || is_sparc_FrameAddr(node)) && "need sparc SymConst/FrameAddr node to get attributes");
+       return (const sparc_symconst_attr_t *)get_irn_generic_attr_const(node);
+}
+
+
+sparc_jmp_cond_attr_t *get_sparc_jmp_cond_attr(ir_node *node)
+{
+       assert(is_sparc_Branch(node) && "need sparc B node to get attributes");
+       return (sparc_jmp_cond_attr_t *)get_irn_generic_attr_const(node);
+}
+
+const sparc_jmp_cond_attr_t *get_sparc_jmp_cond_attr_const(const ir_node *node)
+{
+       assert(is_sparc_Branch(node) && "need sparc B node to get attributes");
+       return (const sparc_jmp_cond_attr_t *)get_irn_generic_attr_const(node);
+}
+
+
+sparc_jmp_switch_attr_t *get_sparc_jmp_switch_attr(ir_node *node)
+{
+       assert(is_sparc_SwitchJmp(node) && "need sparc SwitchJmp node to get attributes");
+       return (sparc_jmp_switch_attr_t *)get_irn_generic_attr_const(node);
+}
+
+const sparc_jmp_switch_attr_t *get_sparc_jmp_switch_attr_const(const ir_node *node)
+{
+       assert(is_sparc_SwitchJmp(node) && "need sparc SwitchJmp node to get attributes");
+       return (const sparc_jmp_switch_attr_t *)get_irn_generic_attr_const(node);
+}
+
+
+sparc_cmp_attr_t *get_sparc_cmp_attr(ir_node *node)
+{
+       assert(is_sparc_irn(node) && "need sparc node to get attributes");
+       return (sparc_cmp_attr_t *)get_irn_generic_attr_const(node);
+}
+
+const sparc_cmp_attr_t *get_sparc_cmp_attr_const(const ir_node *node)
+{
+       assert(is_sparc_irn(node) && "need sparc node to get attributes");
+       return (const sparc_cmp_attr_t *)get_irn_generic_attr_const(node);
+}
+
+/**
+ * Returns the argument register requirements of a sparc node.
+ */
+const arch_register_req_t **get_sparc_in_req_all(const ir_node *node)
+{
+       const sparc_attr_t *attr = get_sparc_attr_const(node);
+       return attr->in_req;
+}
+
+/**
+ * Returns the argument register requirement at position pos of an sparc node.
+ */
+const arch_register_req_t *get_sparc_in_req(const ir_node *node, int pos)
+{
+       const sparc_attr_t *attr = get_sparc_attr_const(node);
+       return attr->in_req[pos];
+}
+
+/**
+ * Sets the IN register requirements at position pos.
+ */
+void set_sparc_req_in(ir_node *node, const arch_register_req_t *req, int pos)
+{
+       sparc_attr_t *attr  = get_sparc_attr(node);
+       attr->in_req[pos] = req;
+}
+
+/**
+ * Initializes the nodes attributes.
+ */
+void init_sparc_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);
+       sparc_attr_t *attr = get_sparc_attr(node);
+       backend_info_t  *info;
+       (void) execution_units;
+
+       arch_irn_set_flags(node, flags);
+       attr->in_req  = in_reqs;
+       attr->is_load_store = false;
+
+       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]));
+}
+
+/* CUSTOM ATTRIBUTE INIT FUNCTIONS */
+static void init_sparc_load_store_attributes(ir_node *res, ir_mode *ls_mode,
+                                                                                       ir_entity *entity,
+                                                                                       int entity_sign, long offset,
+                                                                                       bool is_frame_entity)
+{
+       sparc_load_store_attr_t *attr = get_irn_generic_attr(res);
+    attr->load_store_mode    = ls_mode;
+       attr->entity             = entity;
+       attr->entity_sign        = entity_sign;
+       attr->is_frame_entity    = is_frame_entity;
+       attr->offset             = offset;
+       attr->base.is_load_store = true;
+}
+
+static void init_sparc_cmp_attr(ir_node *res, bool ins_permuted, bool is_unsigned)
+{
+       sparc_cmp_attr_t *attr = get_irn_generic_attr(res);
+       attr->ins_permuted = ins_permuted;
+       attr->is_unsigned  = is_unsigned;
+}
+
+static void init_sparc_symconst_attributes(ir_node *res, ir_entity *entity)
+{
+       sparc_symconst_attr_t *attr = get_irn_generic_attr(res);
+       attr->entity    = entity;
+       attr->fp_offset = 0;
+}
+
+/**
+ * copies sparc attributes of  node
+ */
+static void sparc_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 sparc_attr_t *attr_old = get_sparc_attr_const(old_node);
+       sparc_attr_t       *attr_new = get_sparc_attr(new_node);
+       backend_info_t    *old_info = be_get_info(old_node);
+       backend_info_t    *new_info = be_get_info(new_node);
+
+       /* copy the attributes */
+       memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
+       /* copy out flags */
+       new_info->out_infos =
+               DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
+}
+
+
+/**
+ * compare some node's attributes
+ */
+static int cmp_attr_sparc(ir_node *a, ir_node *b)
+{
+       const sparc_attr_t *attr_a = get_sparc_attr_const(a);
+       const sparc_attr_t *attr_b = get_sparc_attr_const(b);
+       (void) attr_a;
+       (void) attr_b;
+
+       return 0;
+}
+
+
+/* CUSTOM ATTRIBUTE CMP FUNCTIONS */
+static int cmp_attr_sparc_load_store(ir_node *a, ir_node *b)
+{
+       return 0;
+}
+
+static int cmp_attr_sparc_symconst(ir_node *a, ir_node *b)
+{
+       return 0;
+}
+
+static int cmp_attr_sparc_jmp_cond(ir_node *a, ir_node *b)
+{
+       return 0;
+}
+
+static int cmp_attr_sparc_jmp_switch(ir_node *a, ir_node *b)
+{
+       return 0;
+}
+
+static int cmp_attr_sparc_cmp(ir_node *a, ir_node *b)
+{
+       return 0;
+}
+
+/* Include the generated constructor functions */
+#include "gen_sparc_new_nodes.c.inl"
diff --git a/ir/be/sparc/sparc_new_nodes.h b/ir/be/sparc/sparc_new_nodes.h
new file mode 100644 (file)
index 0000000..0b43580
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * 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: TEMPLATE_new_nodes.h 26549 2009-09-18 17:48:23Z matze $
+ */
+#ifndef FIRM_BE_SPARC_SPARC_NEW_NODES_H
+#define FIRM_BE_SPARC_SPARC_NEW_NODES_H
+
+#include "sparc_nodes_attr.h"
+
+/***************************************************************************************************
+ *        _   _                   _       __        _                    _   _               _
+ *       | | | |                 | |     / /       | |                  | | | |             | |
+ *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
+ *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
+ * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
+ *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
+ *                                        __/ |
+ *                                       |___/
+ ***************************************************************************************************/
+
+/**
+ * Returns the attributes of an sparc node.
+ */
+sparc_attr_t *get_sparc_attr(ir_node *node);
+const sparc_attr_t *get_sparc_attr_const(const ir_node *node);
+
+sparc_load_store_attr_t *get_sparc_load_store_attr(ir_node *node);
+const sparc_load_store_attr_t *get_sparc_load_store_attr_const(const ir_node *node);
+
+sparc_symconst_attr_t *get_sparc_symconst_attr(ir_node *node);
+const sparc_symconst_attr_t *get_sparc_symconst_attr_const(const ir_node *node);
+
+sparc_jmp_cond_attr_t *get_sparc_jmp_cond_attr(ir_node *node);
+const sparc_jmp_cond_attr_t *get_sparc_jmp_cond_attr_const(const ir_node *node);
+
+sparc_jmp_switch_attr_t *get_sparc_jmp_switch_attr(ir_node *node);
+const sparc_jmp_switch_attr_t *get_sparc_jmp_switch_attr_const(const ir_node *node);
+
+sparc_cmp_attr_t *get_sparc_cmp_attr(ir_node *node);
+const sparc_cmp_attr_t *get_sparc_cmp_attr_const(const ir_node *node);
+
+/**
+ * Returns the argument register requirements of an sparc node.
+ */
+const arch_register_req_t **get_sparc_in_req_all(const ir_node *node);
+
+/**
+ * Returns the argument register requirements of an sparc node.
+ */
+const arch_register_req_t *get_sparc_in_req(const ir_node *node, int pos);
+
+/**
+ * Sets the IN register requirements at position pos.
+ */
+void set_sparc_req_in(ir_node *node, const arch_register_req_t *req, int pos);
+
+/* Include the generated headers */
+#include "gen_sparc_new_nodes.h"
+
+#endif
diff --git a/ir/be/sparc/sparc_nodes_attr.h b/ir/be/sparc/sparc_nodes_attr.h
new file mode 100644 (file)
index 0000000..5f9621c
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * 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 sparc nodes
+ * @version $Id: TEMPLATE_nodes_attr.h 26317 2009-08-05 10:53:46Z matze $
+ */
+#ifndef FIRM_BE_SPARC_SPARC_NODES_ATTR_H
+#define FIRM_BE_SPARC_SPARC_NODES_ATTR_H
+
+#include "../bearch.h"
+
+typedef struct sparc_attr_t  sparc_attr_t;
+
+/**
+ * base SPARC attribute
+ */
+struct sparc_attr_t
+{
+       except_attr                                     exc;                            /**< the exception attribute. MUST be the first one. */
+       const arch_register_req_t       **in_req;                       /**< register requirements for arguments */
+       int                                                     immediate_value;        /* immediate values */
+       bool                                            is_load_store;
+};
+
+
+/**
+ * attributes for load/store adressing modes
+ */
+typedef struct sparc_load_store_attr_t sparc_load_store_attr_t;
+struct sparc_load_store_attr_t {
+       sparc_attr_t    base;    /**< generic attribute */
+       ir_mode                 *load_store_mode;
+       ir_entity               *entity;
+       int                     entity_sign;
+       long                    offset;
+       bool                    is_frame_entity;
+};
+
+/**
+ * attributes for SymConsts
+ */
+typedef struct sparc_symconst_attr_t sparc_symconst_attr_t;
+struct sparc_symconst_attr_t {
+       sparc_attr_t    base;    /**< generic attribute */
+       ir_entity               *entity;
+       int                             fp_offset;
+};
+
+/**
+ * attributes for conditional jumps
+ */
+typedef struct sparc_jmp_cond_attr_t sparc_jmp_cond_attr_t;
+struct sparc_jmp_cond_attr_t {
+       sparc_attr_t    base;    /**< generic attribute */
+       int                             proj_num;
+};
+
+/**
+ * attributes for switch jumps
+ */
+typedef struct sparc_jmp_switch_attr_t sparc_jmp_switch_attr_t;
+struct sparc_jmp_switch_attr_t {
+       sparc_attr_t    base;    /**< generic attribute */
+       int                             n_projs;
+       long                    default_proj_num;
+};
+
+/**
+ * attributes for Cmp
+ */
+typedef struct sparc_cmp_attr_t sparc_cmp_attr_t;
+struct sparc_cmp_attr_t {
+       sparc_attr_t    base;    /**< generic attribute */
+       bool                    ins_permuted : 1;
+       bool                    is_unsigned  : 1;
+};
+
+#endif
diff --git a/ir/be/sparc/sparc_spec.pl b/ir/be/sparc/sparc_spec.pl
new file mode 100644 (file)
index 0000000..89272f0
--- /dev/null
@@ -0,0 +1,693 @@
+# Creation: 2006/02/13
+# $Id: TEMPLATE_spec.pl 24066 2008-11-27 14:51:14Z mallon $
+# This is a template specification for the Firm-Backend
+
+$new_emit_syntax = 1;
+
+# the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
+
+$arch = "sparc";
+
+$mode_gp      = "mode_Iu";
+$mode_flags   = "mode_Bu";
+$mode_fp      = "mode_D";
+
+# 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
+
+# available SPARC registers: 8 globals, 24 window regs (8 ins, 8 outs, 8 locals)
+%reg_classes = (
+       gp => [
+               { name => "g0", realname => "r0", type => 4 }, # hardwired 0, behaves like /dev/null
+               { name => "g1", realname => "r1", type => 1 }, # temp. value
+               { name => "g2", realname => "r2", type => 1 },
+               { name => "g3", realname => "r3", type => 1 },
+               { name => "g4", realname => "r4", type => 1 },
+               { name => "g5", realname => "r5", type => 1 }, # reserved by SPARC ABI
+               { name => "g6", realname => "r6", type => 1 }, # reserved by SPARC ABI
+               { name => "g7", realname => "r7", type => 2 }, # reserved by SPARC ABI
+
+               # window's out registers
+               { name => "o0", realname => "r8", type => 1 }, # param 1 / return value from callee
+               { name => "o1", realname => "r9", type => 1 }, # param 2
+               { name => "o2", realname => "r10", type => 1 }, # param 3
+               { name => "o3", realname => "r11", type => 1 }, # param 4
+               { name => "o4", realname => "r12", type => 1 }, # param 5
+               { name => "o5", realname => "r13", type => 1 }, # param 6
+               { name => "sp", realname => "r14", type => 4 }, # our stackpointer
+               { name => "o7", realname => "r15", type => 1 }, # temp. value / address of CALL instr.
+
+               # window's local registers
+               { name => "l0", realname => "r16", type => 2 },
+               { name => "l1", realname => "r17", type => 2 },
+               { name => "l2", realname => "r18", type => 2 },
+               { name => "l3", realname => "r19", type => 2 },
+               { name => "l4", realname => "r20", type => 2 },
+               { name => "l5", realname => "r21", type => 2 },
+               { name => "l6", realname => "r22", type => 2 },
+               { name => "l7", realname => "r23", type => 2 },
+
+               # window's in registers
+               { name => "i0", realname => "r24", type => 2 }, # incoming param1 / return value to caller
+               { name => "i1", realname => "r25", type => 2 }, # param 2
+               { name => "i2", realname => "r26", type => 2 }, # param 3
+               { name => "i3", realname => "r27", type => 2 }, # param 4
+               { name => "i4", realname => "r28", type => 2 }, # param 5
+               { name => "i5", realname => "r29", type => 2 }, # param 6
+               { name => "fp", realname => "r30", type => 4 }, # our framepointer
+               { name => "i7", realname => "r31", type => 2 }, # return address - 8
+               { mode => $mode_gp }
+       ],
+       flags => [
+               { name => "y", realname => "y", type => 4 },  # the multiply/divide state register
+               { mode => $mode_flags, flags => "manual_ra" }
+       ],
+#      cpu => [
+#              { name => "psr", realname => "psr", type => 4 },  # the processor state register
+#              { name => "wim", realname => "wim", type => 4 },  # the window invalid mask register
+#              { name => "tbr", realname => "tbr", type => 4 },  # the trap base register
+#              { name => "pc", realname => "pc", type => 4 },  # the program counter register
+#              { name => "npc", realname => "npc", type => 4 },  # the next instruction addr. (PC + 1) register
+#              { mode => "mode_Iu", flags => "manual_ra" }
+#      ],
+
+       # fp registers can be accessed any time
+       fp  => [
+               { name => "f0", type => 1 },
+               { name => "f1", type => 1 },
+               { name => "f2", type => 1 },
+               { name => "f3", type => 1 },
+               { name => "f4", type => 1 },
+               { name => "f5", type => 1 },
+               { name => "f6", type => 1 },
+               { name => "f7", type => 1 },
+               { name => "f8", type => 1 },
+               { name => "f9", type => 1 },
+               { name => "f10", type => 1 },
+               { name => "f11", type => 1 },
+               { name => "f12", type => 1 },
+               { name => "f13", type => 1 },
+               { name => "f14", type => 1 },
+               { name => "f15", type => 1 },
+               { name => "f16", type => 1 },
+               { name => "f17", type => 1 },
+               { name => "f18", type => 1 },
+               { name => "f19", type => 1 },
+               { name => "f20", type => 1 },
+               { name => "f21", type => 1 },
+               { name => "f22", type => 1 },
+               { name => "f23", type => 1 },
+               { name => "f24", type => 1 },
+               { name => "f25", type => 1 },
+               { name => "f26", type => 1 },
+               { name => "f27", type => 1 },
+               { name => "f28", type => 1 },
+               { name => "f29", type => 1 },
+               { name => "f30", type => 1 },
+               { name => "f31", type => 1 },
+               { mode => $mode_fp }
+       ]
+); # %reg_classes
+
+%emit_templates = (
+# emit source reg or imm dep. on node's arity
+    RI => "${arch}_emit_reg_or_imm(node, -1);",
+    R1I => "${arch}_emit_reg_or_imm(node, 0);",
+    R2I => "${arch}_emit_reg_or_imm(node, 1);",
+    R3I => "${arch}_emit_reg_or_imm(node, 2);",
+# simple reg emitters
+    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);",
+# more custom emitters
+       C  => "${arch}_emit_immediate(node);",
+       LM  => "${arch}_emit_load_mode(node);",
+       SM  => "${arch}_emit_store_mode(node);",
+       O  => "${arch}_emit_offset(node);",
+);
+
+#--------------------------------------------------#
+#                        _                         #
+#                       (_)                        #
+#  _ __   _____      __  _ _ __    ___  _ __  ___  #
+# | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
+# | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
+# |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
+#                                      | |         #
+#                                      |_|         #
+#--------------------------------------------------#
+
+$default_attr_type = "sparc_attr_t";
+$default_copy_attr = "sparc_copy_attr";
+
+
+%init_attr = (
+                   sparc_attr_t                                => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
+                   sparc_load_store_attr_t         => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
+                                                                                       "\tinit_sparc_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);",
+                   sparc_symconst_attr_t                       => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
+                                                                                               "\tinit_sparc_symconst_attributes(res, entity);",
+                       sparc_cmp_attr_t                                => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n",
+                       sparc_jmp_cond_attr_t                   => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
+                       sparc_jmp_switch_attr_t                 => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
+
+);
+
+%compare_attr = (
+                   sparc_attr_t            => "cmp_attr_sparc",
+                   sparc_load_store_attr_t => "cmp_attr_sparc_load_store",
+                   sparc_symconst_attr_t   => "cmp_attr_sparc_symconst",
+                   sparc_jmp_cond_attr_t       => "cmp_attr_sparc_jmp_cond",
+                   sparc_jmp_switch_attr_t     => "cmp_attr_sparc_jmp_switch",
+                   sparc_cmp_attr_t            => "cmp_attr_sparc_cmp",
+);
+
+
+# addressing modes: imm, reg, reg +/- imm, reg + reg
+# max. imm = 13 bits signed (-4096 ... 4096)
+
+
+my %cmp_operand_constructors = (
+    imm => {
+        attr       => "int immediate_value, bool ins_permuted, bool is_unsigned",
+        custominit => "sparc_set_attr_imm(res, immediate_value);" .
+                                               "\tinit_sparc_cmp_attr(res, ins_permuted, is_unsigned);",
+        reg_req    => { in => [ "gp" ], out => [ "flags" ] },
+               ins        => [ "left" ],
+    },
+    reg => {
+               attr       => "bool ins_permuted, bool is_unsigned",
+        custominit => "init_sparc_cmp_attr(res, ins_permuted, is_unsigned);",
+        reg_req    => { in => [ "gp", "gp" ], out => [ "flags" ] },
+        ins        => [ "left", "right" ],
+    },
+);
+
+my %unop_operand_constructors = (
+    imm => {
+        attr       => "int immediate_value",
+        custominit => "sparc_set_attr_imm(res, immediate_value);",
+        reg_req    => { in => [], out => [ "gp" ] },
+    },
+    reg => {
+               # custominit => "set_sparc_attr_values(res, immediate_value);",
+        reg_req    => { in => [ "gp" ], out => [ "gp" ] },
+    },
+);
+
+my %binop_operand_constructors = (
+    imm => {
+        attr       => "int immediate_value",
+        custominit => "sparc_set_attr_imm(res, immediate_value);",
+        reg_req    => { in => [ "gp" ], out => [ "gp" ] },
+        ins        => [ "left" ],
+    },
+    reg => {
+               # custominit => "set_sparc_attr_values(res, immediate_value);",
+        reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
+        ins        => [ "left", "right" ],
+    },
+);
+
+%nodes = (
+
+#-----------------------------------------------------------------#
+#  _       _                                         _            #
+# (_)     | |                                       | |           #
+#  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
+# | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
+# | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
+# |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
+#                   __/ |                                         #
+#                  |___/                                          #
+#-----------------------------------------------------------------#
+
+# commutative operations
+
+Add => {
+  op_flags  => "C",
+  irn_flags => "R",
+  comment   => "construct Add: Add(a, b) = Add(b, a) = a + b",
+  mode         => $mode_gp,
+  emit      => '. add %S1, %R2I, %D1',
+  constructors => \%binop_operand_constructors,
+},
+
+Sub => {
+  irn_flags => "R",
+  comment   => "construct Sub: Sub(a, b) = a - b",
+  mode         => $mode_gp,
+  reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
+  emit      => '. sub %S1, %R2I, %D1',
+  constructors => \%binop_operand_constructors,
+},
+
+
+# Load / Store
+Load => {
+  op_flags  => "L|F",
+  comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
+  state     => "exc_pinned",
+  ins       => [ "ptr", "mem" ],
+  outs      => [ "res", "M" ],
+  reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
+  attr_type => "sparc_load_store_attr_t",
+  attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
+  emit      => '. ld%LM [%S1%O], %D1'
+},
+
+Store => {
+  op_flags  => "L|F",
+  comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
+  mode                 => "mode_M",
+  state     => "exc_pinned",
+  ins       => [ "ptr", "val", "mem" ],
+  outs      => [ "mem" ],
+  reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
+  attr_type => "sparc_load_store_attr_t",
+  attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
+  emit      => '. st%SM %S1, [%D1%O]'
+},
+
+Mov => {
+  irn_flags => "R",
+  comment   => "construct Mov: Mov(src, dest) = MV src,dest",
+  arity     => "variable",
+  emit      => '. mov %R1I, %D1',
+  mode      => $mode_gp,
+  constructors => \%unop_operand_constructors,
+},
+
+AddSP => {
+       comment => "alloc stack space",
+       reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "gp", "none" ] },
+       ins       => [ "stack", "size", "mem" ],
+       outs      => [ "stack", "addr", "M" ],
+       emit      => ". sub %S1, %S2, %D1\n",
+},
+
+SubSP => {
+       comment => "free stack space",
+       reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
+       ins       => [ "stack", "size", "mem" ],
+       outs      => [ "stack", "M" ],
+       emit      => ". add %S1, %S2, %D1\n",
+},
+
+SymConst => {
+       op_flags  => "c",
+       irn_flags => "R",
+       attr      => "ir_entity *entity",
+       reg_req   => { out => [ "gp" ] },
+       attr_type => "sparc_symconst_attr_t",
+       mode      => $mode_gp,
+},
+
+FrameAddr => {
+       op_flags  => "c",
+       irn_flags => "R",
+       attr      => "ir_entity *entity",
+       reg_req   => { in => [ "gp" ], out => [ "gp" ] },
+       ins       => [ "base" ],
+       attr_type => "sparc_symconst_attr_t",
+       mode      => $mode_gp,
+},
+
+Branch => {
+       op_flags  => "L|X|Y",
+       state     => "pinned",
+       mode      => "mode_T",
+       reg_req   => { in => [ "flags" ], out => [ "none", "none" ] },
+       attr      => "int proj_num",
+       attr_type => "sparc_jmp_cond_attr_t",
+       init_attr => "\tset_sparc_jmp_cond_proj_num(res, proj_num);",
+},
+
+Cmp => {
+       irn_flags    => "R|F",
+       emit         => '. cmp %S1, %R2I',
+       mode         => $mode_flags,
+       attr_type    => "sparc_cmp_attr_t",
+       constructors => \%cmp_operand_constructors,
+},
+
+Tst => {
+       irn_flags    => "R|F",
+       emit         => '. tst %S1',
+       mode         => $mode_flags,
+       attr_type    => "sparc_cmp_attr_t",
+       attr         => "bool ins_permuted, bool is_unsigned",
+       custominit   => "init_sparc_cmp_attr(res, ins_permuted, is_unsigned);",
+       reg_req      => { in => [ "gp" ], out => [ "flags" ] },
+       ins          => [ "left" ],
+},
+
+SwitchJmp => {
+       op_flags  => "L|X|Y",
+       state     => "pinned",
+       mode      => "mode_T",
+       attr      => "int n_projs, long def_proj_num",
+       init_attr => "\tset_sparc_jmp_switch_n_projs(res, n_projs);\n".
+                                       "\tset_sparc_jmp_switch_default_proj_num(res, def_proj_num);",
+       reg_req   => { in => [ "gp" ], out => [ "none" ] },
+       attr_type => "sparc_jmp_switch_attr_t",
+},
+#Mul => {
+#  op_flags  => "C",
+#  irn_flags => "R",
+#  comment   => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
+#  reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
+#  emit      =>'. mul %S1, %S2, %D1'
+#},
+
+#Mul_i => {
+#  irn_flags => "R",
+#  comment   => "construct Mul: Mul(a, const) = Mul(const, a) = a * const",
+#  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
+#  emit      => '. mul %S1, %C, %D1'
+#},
+#
+#And => {
+#  op_flags  => "C",
+#  irn_flags => "R",
+#  comment   => "construct And: And(a, b) = And(b, a) = a AND b",
+#  reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
+#  emit      => '. and %S1, %S2, %D1'
+#},
+#
+#And_i => {
+#  irn_flags => "R",
+#  comment   => "construct And: And(a, const) = And(const, a) = a AND const",
+#  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
+#  emit      => '. and %S1, %C, %D1'
+#},
+#
+#Or => {
+#  op_flags  => "C",
+#  irn_flags => "R",
+#  comment   => "construct Or: Or(a, b) = Or(b, a) = a OR b",
+#  reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
+#  emit      => '. or %S1, %S2, %D1'
+#},
+#
+#Or_i => {
+#  op_flags  => "C",
+#  irn_flags => "R",
+#  comment   => "construct Or: Or(a, const) = Or(const, a) = a OR const",
+#  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
+#  emit      => '. or %S1, %C, %D1'
+#},
+#
+#Eor => {
+#  op_flags  => "C",
+#  irn_flags => "R",
+#  comment   => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
+#  reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
+#  emit      => '. xor %S1, %S2, %D1'
+#},
+#
+#Eor_i => {
+#  irn_flags => "R",
+#  comment   => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
+#  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
+#  emit      => '. xor %S1, %C, %D1'
+#},
+
+# not commutative operations
+#Shl => {
+#  irn_flags => "R",
+#  comment   => "construct Shl: Shl(a, b) = a << b",
+#  reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
+#  emit      => '. shl %S1, %S2, %D1'
+#},
+#
+#Shl_i => {
+#  irn_flags => "R",
+#  comment   => "construct Shl: Shl(a, const) = a << const",
+#  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
+#  emit      => '. shl %S1, %C, %D1'
+#},
+#
+#Shr => {
+#  irn_flags => "R",
+#  comment   => "construct Shr: Shr(a, b) = a >> b",
+#  reg_req   => { in => [ "gp", "gp" ], out => [ "in_r1" ] },
+#  emit      => '. shr %S2, %D1'
+#},
+#
+#Shr_i => {
+#  irn_flags => "R",
+#  comment   => "construct Shr: Shr(a, const) = a >> const",
+#  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
+#  emit      => '. shr %S1, %C, %D1'
+#},
+#
+#RotR => {
+#  irn_flags => "R",
+#  comment   => "construct RotR: RotR(a, b) = a ROTR b",
+#  reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
+#  emit      => '. ror %S1, %S2, %D1'
+#},
+#
+#RotL => {
+#  irn_flags => "R",
+#  comment   => "construct RotL: RotL(a, b) = a ROTL b",
+#  reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
+#  emit      => '. rol %S1, %S2, %D1'
+#},
+#
+#RotL_i => {
+#  irn_flags => "R",
+#  comment   => "construct RotL: RotL(a, const) = a ROTL const",
+#  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
+#  emit      => '. rol %S1, %C, %D1'
+#},
+#
+#Minus => {
+#  irn_flags => "R",
+#  comment   => "construct Minus: Minus(a) = -a",
+#  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
+#  emit      => '. neg %S1, %D1'
+#},
+#
+#Inc => {
+#  irn_flags => "R",
+#  comment   => "construct Increment: Inc(a) = a++",
+#  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
+#  emit      => '. inc %S1, %D1'
+#},
+#
+#Dec => {
+#  irn_flags => "R",
+#  comment   => "construct Decrement: Dec(a) = a--",
+#  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
+#  emit      => '. dec %S1, %D1'
+#},
+#
+#Not => {
+#  arity       => 1,
+#  remat       => 1,
+#  comment     => "construct Not: Not(a) = !a",
+#  reg_req     => { in => [ "gp" ], out => [ "gp" ] },
+#  emit        => '. not %S1, %D1'
+#},
+
+
+#--------------------------------------------------------#
+#    __ _             _                     _            #
+#   / _| |           | |                   | |           #
+#  | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
+#  |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
+#  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
+#  |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
+#--------------------------------------------------------#
+
+# commutative operations
+
+#fAdd => {
+#  op_flags  => "C",
+#  irn_flags => "R",
+#  comment   => "construct FP Add: Add(a, b) = Add(b, a) = a + b",
+#  reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
+#  emit      => '. fadd %S1, %S2, %D1'
+#},
+#
+#fMul => {
+#  op_flags  => "C",
+#  comment   => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b",
+#  reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
+#  emit      =>'. fmul %S1, %S2, %D1'
+#},
+#
+#fMax => {
+#  op_flags  => "C",
+#  irn_flags => "R",
+#  comment   => "construct FP Max: Max(a, b) = Max(b, a) = a > b ? a : b",
+#  reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
+#  emit      =>'. fmax %S1, %S2, %D1'
+#},
+#
+#fMin => {
+#  op_flags  => "C",
+#  irn_flags => "R",
+#  comment   => "construct FP Min: Min(a, b) = Min(b, a) = a < b ? a : b",
+#  reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
+#  emit      =>'. fmin %S1, %S2, %D1'
+#},
+#
+## not commutative operations
+#
+#fSub => {
+#  irn_flags => "R",
+#  comment   => "construct FP Sub: Sub(a, b) = a - b",
+#  reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
+#  emit      => '. fsub %S1, %S2, %D1'
+#},
+#
+#fDiv => {
+#  comment   => "construct FP Div: Div(a, b) = a / b",
+#  reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
+#  emit      => '. fdiv %S1, %S2, %D1'
+#},
+#
+#fMinus => {
+#  irn_flags => "R",
+#  comment   => "construct FP Minus: Minus(a) = -a",
+#  reg_req   => { in => [ "fp" ], out => [ "fp" ] },
+#  emit      => '. fneg %S1, %D1'
+#},
+#
+## other operations
+#
+#fConst => {
+#  op_flags  => "c",
+#  irn_flags => "R",
+#  comment   => "represents a FP constant",
+#  reg_req   => { out => [ "fp" ] },
+#  emit      => '. fmov %C, %D1',
+#  cmp_attr  =>
+#'
+#      /* TODO: compare fConst attributes */
+#      return 1;
+#'
+#},
+#
+## Load / Store
+#
+#fLoad => {
+#  op_flags  => "L|F",
+#  irn_flags => "R",
+#  state     => "exc_pinned",
+#  comment   => "construct FP Load: Load(ptr, mem) = LD ptr",
+#  reg_req   => { in => [ "gp", "none" ], out => [ "fp" ] },
+#  emit      => '. fmov (%S1), %D1'
+#},
+#
+#fStore => {
+#  op_flags  => "L|F",
+#  irn_flags => "R",
+#  state     => "exc_pinned",
+#  comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
+#  reg_req   => { in => [ "gp", "fp", "none" ] },
+#  emit      => '. fmov %S2, (%S1)'
+#},
+
+); # end of %nodes
diff --git a/ir/be/sparc/sparc_transform.c b/ir/be/sparc/sparc_transform.c
new file mode 100644 (file)
index 0000000..bf6b56c
--- /dev/null
@@ -0,0 +1,627 @@
+/*
+ * 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 SPARC FIRM)
+ * @version $Id: TEMPLATE_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 "irprintf.h"
+#include "dbginfo.h"
+#include "iropt_t.h"
+#include "debug.h"
+#include "error.h"
+
+#include "../benode.h"
+#include "../beirg.h"
+#include "../beutil.h"
+#include "../betranshlp.h"
+#include "bearch_sparc_t.h"
+
+#include "sparc_nodes_attr.h"
+#include "sparc_transform.h"
+#include "sparc_new_nodes.h"
+#include "gen_sparc_new_nodes.h"
+
+#include "gen_sparc_regalloc_if.h"
+
+#include <limits.h>
+
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
+
+static sparc_code_gen_t *env_cg;
+
+static inline int mode_needs_gp_reg(ir_mode *mode)
+{
+       return mode_is_int(mode) || mode_is_reference(mode);
+}
+
+/**
+ * Creates a possible DAG for a constant.
+ */
+static ir_node *create_const_graph_value(dbg_info *dbgi, ir_node *block,
+                               long value)
+{
+       ir_node *result;
+
+       // TODO: find a better solution for this
+       if (value < -4096 || value > 4096) {
+               panic("FIXME: immediate value exceeds max. size of simm13 (13 bits signed)");
+       }
+
+       result = new_bd_sparc_Mov_imm(dbgi, block, (int) value);
+       return result;
+}
+
+
+/**
+ * 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);
+       long value;
+
+       if (mode_is_reference(mode)) {
+               /* SPARC V8 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(get_irn_dbg_info(irn), block, value);
+}
+
+
+typedef enum {
+       MATCH_NONE         = 0,
+       MATCH_COMMUTATIVE  = 1 << 0,
+       MATCH_SIZE_NEUTRAL = 1 << 1,
+} match_flags_t;
+
+typedef ir_node* (*new_binop_reg_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2);
+typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, int simm13);
+
+/**
+ * checks wether a node's value can be encoded as a immediate
+ * TODO: pass a result pointer to fetch the encoded immediate
+ *
+ */
+static bool is_imm_encodeable(const ir_node *node)
+{
+       long val;
+
+       if (!is_Const(node))
+               return false;
+
+       val = get_tarval_long(get_Const_tarval(node));
+
+       return !(val < -4096 || val > 4096);
+}
+
+/**
+ * helper function for binop operations
+ *
+ * @param new_binop_reg_func register generation function ptr
+ * @param new_binop_imm_func immediate generation function ptr
+ */
+static ir_node *gen_helper_binop(ir_node *node, match_flags_t flags,
+                               new_binop_reg_func new_reg, new_binop_imm_func new_imm)
+{
+       ir_node  *block   = be_transform_node(get_nodes_block(node));
+       ir_node  *op1     = get_binop_left(node);
+       ir_node  *new_op1;
+       ir_node  *op2     = get_binop_right(node);
+       ir_node  *new_op2;
+       dbg_info *dbgi    = get_irn_dbg_info(node);
+
+/*
+    if (flags & MATCH_SIZE_NEUTRAL) {
+        op1 = arm_skip_downconv(op1);
+        op2 = arm_skip_downconv(op2);
+    } else {
+        assert(get_mode_size_bits(get_irn_mode(node)) == 32);
+    }
+*/
+       if (is_imm_encodeable(op2)) {
+               ir_node *new_op1 = be_transform_node(op1);
+               return new_imm(dbgi, block, new_op1, get_tarval_long(get_Const_tarval(node)));
+       }
+
+       new_op2 = be_transform_node(op2);
+
+       if ((flags & MATCH_COMMUTATIVE) && is_imm_encodeable(op1)) {
+               return new_imm(dbgi, block, new_op2, get_tarval_long(get_Const_tarval(op1)) );
+       }
+
+       new_op1 = be_transform_node(op1);
+
+       return new_reg(dbgi, block, new_op1, new_op2);
+}
+
+/**
+ * Creates an sparc Add.
+ *
+ * @param node   FIRM node
+ * @return the created sparc Add node
+ */
+static ir_node *gen_Add(ir_node *node)
+{
+       ir_mode  *mode    = get_irn_mode(node);
+       ir_node  *block   = be_transform_node(get_nodes_block(node));
+       ir_node  *op1     = get_Add_left(node);
+       ir_node  *op2     = get_Add_right(node);
+       dbg_info *dbgi    = get_irn_dbg_info(node);
+       ir_node  *new_op1 = be_transform_node(op1);
+       ir_node  *new_op2 = be_transform_node(op2);
+
+       (void) new_op1;
+       (void) new_op2;
+       (void) block;
+       (void) dbgi;
+
+       if (mode_is_float(mode))
+               panic("FP not implemented yet");
+
+       return gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, new_bd_sparc_Add_reg, new_bd_sparc_Add_imm);
+}
+
+
+/**
+ * Creates an sparc Sub.
+ *
+ * @param node       FIRM node
+ * @return the created sparc Sub node
+ */
+static ir_node *gen_Sub(ir_node *node)
+{
+       ir_mode  *mode    = get_irn_mode(node);
+       ir_node  *block   = be_transform_node(get_nodes_block(node));
+       ir_node  *op1     = get_Add_left(node);
+       ir_node  *op2     = get_Add_right(node);
+       dbg_info *dbgi    = get_irn_dbg_info(node);
+       ir_node  *new_op1 = be_transform_node(op1);
+       ir_node  *new_op2 = be_transform_node(op2);
+
+       (void) new_op1;
+    (void) new_op2;
+    (void) block;
+    (void) dbgi;
+
+       if (mode_is_float(mode))
+               panic("FP not implemented yet");
+
+       return gen_helper_binop(node, MATCH_SIZE_NEUTRAL, new_bd_sparc_Sub_reg, new_bd_sparc_Sub_imm);
+}
+
+
+/**
+ * Transforms a Load.
+ *
+ * @param node    the ir Load node
+ * @return the created sparc Load node
+ */
+static ir_node *gen_Load(ir_node *node)
+{
+
+       if (mode_is_float(get_irn_mode(node)))
+               panic("SPARC: no fp implementation yet");
+
+       ir_mode  *mode     = get_Load_mode(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);
+       dbg_info *dbgi      = get_irn_dbg_info(node);
+       ir_node  *new_load = NULL;
+
+       new_load = new_bd_sparc_Load(dbgi, block, new_ptr, new_mem, mode, NULL, 0, 0, false);
+       return new_load;
+}
+
+
+
+/**
+ * Transforms a Store.
+ *
+ * @param node    the ir Store node
+ * @return the created sparc Store node
+ */
+static ir_node *gen_Store(ir_node *node)
+{
+       if (mode_is_float(get_irn_mode(node)))
+               panic("SPARC: no fp implmentation yet");
+
+       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);
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+       ir_node *new_store = NULL;
+
+       new_store = new_bd_sparc_Store(dbgi, block, new_ptr, new_val, new_mem, mode, NULL, 0, 0, false);
+
+       return new_store;
+}
+
+
+
+/****** TRANSFORM GENERAL BACKEND NODES ********/
+
+/**
+ * Transforms a Const node.
+ *
+ * @param node    the ir Store node
+ * @return The transformed sparc 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);
+       dbg_info *dbg = get_irn_dbg_info(node);
+
+       (void) dbg;
+
+       if (mode_is_float(mode)) {
+               panic("FP not supported yet");
+       }
+       return create_const_graph(node, block);
+}
+
+/**
+ * AddSP
+ * @param node the ir AddSP node
+ * @return transformed sparc SAVE node
+ */
+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);
+       dbg_info *dbgi   = get_irn_dbg_info(node);
+       ir_node  *nomem  = new_NoMem();
+       ir_node  *new_op;
+
+       /* SPARC stack grows in reverse direction */
+       new_op = new_bd_sparc_AddSP(dbgi, block, new_sp, new_sz, nomem);
+
+       return new_op;
+}
+
+
+/**
+ * SubSP
+ * @param node the ir SubSP node
+ * @return transformed sparc SAVE node
+ */
+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);
+       dbg_info *dbgi   = get_irn_dbg_info(node);
+       ir_node  *nomem  = new_NoMem();
+       ir_node  *new_op;
+
+       /* SPARC stack grows in reverse direction */
+       new_op = new_bd_sparc_SubSP(dbgi, block, new_sp, new_sz, nomem);
+       return new_op;
+}
+
+/**
+ * transform FrameAddr
+ */
+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);
+       ir_node   *fp     = be_get_FrameAddr_frame(node);
+       ir_node   *new_fp = be_transform_node(fp);
+       dbg_info  *dbgi   = get_irn_dbg_info(node);
+       ir_node   *new_node;
+       new_node = new_bd_sparc_FrameAddr(dbgi, block, new_fp, ent);
+       return new_node;
+}
+
+/**
+ * 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 Call
+ */
+static ir_node *gen_be_Call(ir_node *node)
+{
+       ir_node *res = be_duplicate_node(node);
+       arch_irn_add_flags(res, arch_irn_flags_modify_flags);
+       return res;
+}
+
+static ir_node *gen_SwitchJmp(ir_node *node)
+{
+       panic("TODO: not implemented yet");
+}
+
+/**
+ * Transform Cond nodes
+ */
+static ir_node *gen_Cond(ir_node *node)
+{
+       ir_node  *selector = get_Cond_selector(node);
+       ir_mode  *mode     = get_irn_mode(selector);
+       ir_node  *block;
+       ir_node  *flag_node;
+       dbg_info *dbgi;
+
+       // switch/case jumps
+       if (mode != mode_b) {
+               //return gen_SwitchJmp(node);
+               panic("TODO: switchJmp not implemented yet");
+               return node;
+       }
+
+       // regular if/else jumps
+       assert(is_Proj(selector));
+
+       block     = be_transform_node(get_nodes_block(node));
+       dbgi      = get_irn_dbg_info(node);
+       flag_node = be_transform_node(get_Proj_pred(selector));
+       return new_bd_sparc_Branch(dbgi, block, flag_node, get_Proj_proj(selector));
+}
+
+/**
+ * transform Cmp
+ */
+static ir_node *gen_Cmp(ir_node *node)
+{
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *op1      = get_Cmp_left(node);
+       ir_node  *op2      = get_Cmp_right(node);
+       ir_mode  *cmp_mode = get_irn_mode(op1);
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+       ir_node  *new_op1;
+       ir_node  *new_op2;
+       bool      is_unsigned;
+
+       if (mode_is_float(cmp_mode)) {
+               panic("FloatCmp not implemented");
+       }
+
+       if (get_mode_size_bits(cmp_mode) != 32) {
+               panic("CmpMode != 32bit not supported yet");
+       }
+
+       assert(get_irn_mode(op2) == cmp_mode);
+       is_unsigned = !mode_is_signed(cmp_mode);
+
+       /* compare with 0 can be done with Tst */
+       if (is_Const(op2) && tarval_is_null(get_Const_tarval(op2))) {
+               new_op1 = be_transform_node(op1);
+               //new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode);
+               //panic("TODO: implement Tst instruction");
+               return new_bd_sparc_Tst(dbgi, block, new_op1, false,
+                                         is_unsigned);
+       }
+
+       if (is_Const(op1) && tarval_is_null(get_Const_tarval(op1))) {
+               new_op2 = be_transform_node(op2);
+               //new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode);
+               //panic("TODO: implement Tst instruction");
+               return new_bd_sparc_Tst(dbgi, block, new_op2, true,
+                                         is_unsigned);
+       }
+
+       /* integer compare */
+       new_op1 = be_transform_node(op1);
+       //new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode);
+       new_op2 = be_transform_node(op2);
+       //new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode);
+       return new_bd_sparc_Cmp_reg(dbgi, block, new_op1, new_op2, false, is_unsigned);
+}
+
+/**
+ * Transforms a SymConst node.
+ */
+static ir_node *gen_SymConst(ir_node *node)
+{
+       ir_node   *block  = be_transform_node(get_nodes_block(node));
+       ir_entity *entity = get_SymConst_entity(node);
+       dbg_info  *dbgi   = get_irn_dbg_info(node);
+       ir_node   *new_node;
+
+       new_node = new_bd_sparc_SymConst(dbgi, block, entity);
+       be_dep_on_frame(new_node);
+       return new_node;
+}
+
+/**
+ * Transform some Phi nodes
+ */
+static ir_node *gen_Phi(ir_node *node)
+{
+       const arch_register_req_t *req;
+       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;
+               req  = sparc_reg_classes[CLASS_sparc_gp].class_req;
+       } else {
+               req = arch_no_register_req;
+       }
+
+       /* 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);
+       arch_set_out_register_req(phi, 0, req);
+       be_enqueue_preds(node);
+       return phi;
+}
+
+/**
+ * the BAD transformer.
+ */
+static ir_node *bad_transform(ir_node *irn)
+{
+       panic("SPARC backend: Not implemented: %+F", irn);
+}
+
+/**
+ * Set a node emitter. Make it a bit more type safe.
+ */
+static void set_transformer(ir_op *op, be_transform_func sparc_transform_func)
+{
+       op->ops.generic = (op_func)sparc_transform_func;
+}
+
+/**
+ * configure transformation callbacks
+ */
+void sparc_register_transformers(void)
+{
+       clear_irp_opcodes_generic_func();
+       set_transformer(op_Add,                         gen_Add);
+       set_transformer(op_Store,                       gen_Store);
+       set_transformer(op_Const,                       gen_Const);
+       set_transformer(op_Load,                        gen_Load);
+       set_transformer(op_Sub,                         gen_Sub);
+
+       set_transformer(op_be_AddSP,     gen_be_AddSP);
+       set_transformer(op_be_SubSP,     gen_be_SubSP);
+       set_transformer(op_be_Copy,      gen_be_Copy);
+       set_transformer(op_be_Call,      gen_be_Call);
+       set_transformer(op_be_FrameAddr, gen_be_FrameAddr);
+
+       set_transformer(op_Cond,         gen_Cond);
+       set_transformer(op_Cmp,          gen_Cmp);
+
+       set_transformer(op_SymConst,     gen_SymConst);
+
+       set_transformer(op_Phi,          gen_Phi);
+
+       /* node list */
+       /*
+       set_transformer(op_Abs,          gen_Abs);
+       set_transformer(op_Add,          gen_Add);
+       set_transformer(op_And,          gen_And);
+       set_transformer(op_Const,        gen_Const);
+       set_transformer(op_Conv,         gen_Conv);
+       set_transformer(op_CopyB,        gen_CopyB);
+       set_transformer(op_Eor,          gen_Eor);
+       set_transformer(op_Jmp,          gen_Jmp);
+       set_transformer(op_Load,         gen_Load);
+       set_transformer(op_Minus,        gen_Minus);
+       set_transformer(op_Mul,          gen_Mul);
+       set_transformer(op_Not,          gen_Not);
+       set_transformer(op_Or,           gen_Or);
+       set_transformer(op_Proj,         gen_Proj);
+       set_transformer(op_Quot,         gen_Quot);
+       set_transformer(op_Rotl,         gen_Rotl);
+       set_transformer(op_Shl,          gen_Shl);
+       set_transformer(op_Shr,          gen_Shr);
+       set_transformer(op_Shrs,         gen_Shrs);
+       set_transformer(op_Store,        gen_Store);
+       set_transformer(op_Sub,          gen_Sub);
+       set_transformer(op_Unknown,      gen_Unknown);
+       */
+
+       set_transformer(op_ASM,       bad_transform);
+       set_transformer(op_Builtin,   bad_transform);
+       set_transformer(op_CallBegin, bad_transform);
+       set_transformer(op_Cast,      bad_transform);
+       set_transformer(op_Confirm,   bad_transform);
+       set_transformer(op_DivMod,    bad_transform);
+       set_transformer(op_EndExcept, bad_transform);
+       set_transformer(op_EndReg,    bad_transform);
+       set_transformer(op_Filter,    bad_transform);
+       set_transformer(op_Free,      bad_transform);
+       set_transformer(op_Id,        bad_transform);
+       set_transformer(op_InstOf,    bad_transform);
+       set_transformer(op_Mulh,      bad_transform);
+       set_transformer(op_Mux,       bad_transform);
+       set_transformer(op_Raise,     bad_transform);
+       set_transformer(op_Sel,       bad_transform);
+       set_transformer(op_Tuple,     bad_transform);
+}
+
+
+/**
+  * Pre-transform all unknown nodes.
+  */
+static void sparc_pretransform_node(void)
+{
+       sparc_code_gen_t *cg = env_cg;
+       (void) cg;
+       //cg->unknown_gp  = be_pre_transform_node(cg->unknown_gp);
+       //cg->unknown_fpa = be_pre_transform_node(cg->unknown_fpa);
+}
+
+/**
+ * Transform a Firm graph into a SPARC graph.
+ */
+void sparc_transform_graph(sparc_code_gen_t *cg)
+{
+       sparc_register_transformers();
+       env_cg = cg;
+       be_transform_graph(cg->birg, sparc_pretransform_node);
+}
+
+void sparc_init_transform(void)
+{
+       FIRM_DBG_REGISTER(dbg, "firm.be.sparc.transform");
+}
diff --git a/ir/be/sparc/sparc_transform.h b/ir/be/sparc/sparc_transform.h
new file mode 100644 (file)
index 0000000..e1de9f7
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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: TEMPLATE_transform.h 26542 2009-09-18 09:18:32Z matze $
+ */
+#ifndef FIRM_BE_SPARC_SPARC_TRANSFORM_H
+#define FIRM_BE_SPARC_SPARC_TRANSFORM_H
+
+void sparc_init_transform(void);
+
+void sparc_register_transformers(void);
+
+void sparc_transform_graph(sparc_code_gen_t *cg);
+#endif