--- /dev/null
+/*
+ * 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);
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/**
+ * @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
+}
--- /dev/null
+/**
+ * @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
--- /dev/null
+/**
+ * @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;
+}
--- /dev/null
+/**
+ * @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
--- /dev/null
+#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;
+}
--- /dev/null
+/**
+ * @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
--- /dev/null
+/**
+ * @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;
+
+}
--- /dev/null
+/**
+ * @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
--- /dev/null
+/*
+ * 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");
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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"
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+# 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
--- /dev/null
+/*
+ * 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");
+}
--- /dev/null
+/*
+ * 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