BACKENDS=""
if test "$enable_backend" = yes; then
- BACKENDS="arm ia32 mips sparc amd64"
+ BACKENDS="arm ia32 sparc amd64"
fi
AC_SUBST([BACKENDS])
be/arm/arm_spec.pl be/scripts/generate_machine.pl
$(PERL) $(srcdir)/be/scripts/generate_regalloc_if.pl $(srcdir)/be/arm/arm_spec.pl $(srcdir)/be/arm
-# mips backend
-
-mips_sources = \
- be/mips/bearch_mips.c \
- be/mips/mips_emitter.c \
- be/mips/mips_map_regs.c \
- be/mips/mips_new_nodes.c \
- be/mips/mips_scheduler.c \
- be/mips/mips_transform.c
-mips_built_sources = \
- be/mips/gen_mips_emitter.c \
- be/mips/gen_mips_emitter.h \
- be/mips/gen_mips_machine.c \
- be/mips/gen_mips_machine.h \
- be/mips/gen_mips_new_nodes.c.inl \
- be/mips/gen_mips_new_nodes.h \
- be/mips/gen_mips_regalloc_if.c \
- be/mips/gen_mips_regalloc_if.h
-MAINTAINERCLEANFILES += $(mips_built_sources)
-BUILT_SOURCES += $(mips_built_sources)
-libfirm_la_SOURCES += $(mips_sources) $(mips_built_sources)
-
-EXTRA_DIST += \
- be/mips/bearch_mips.h \
- be/mips/bearch_mips_t.h \
- be/mips/mips_emitter.h \
- be/mips/mips_map_regs.h \
- be/mips/mips_new_nodes.h \
- be/mips/mips_nodes_attr.h \
- be/mips/mips_scheduler.h \
- be/mips/mips_spec.pl \
- be/mips/mips_transform.h \
- be/mips/mips_util.h
-
-$(srcdir)/be/mips/gen_mips_new_nodes.c.inl $(srcdir)/be/mips/gen_mips_new_nodes.h: \
- be/mips/mips_spec.pl be/scripts/generate_new_opcodes.pl
- $(PERL) $(srcdir)/be/scripts/generate_new_opcodes.pl $(srcdir)/be/mips/mips_spec.pl $(srcdir)/be/mips
-
-$(srcdir)/be/mips/gen_mips_emitter.c $(srcdir)/be/mips/gen_mips_emitter.h: \
- be/mips/mips_spec.pl be/scripts/generate_emitter.pl
- $(PERL) $(srcdir)/be/scripts/generate_emitter.pl $(srcdir)/be/mips/mips_spec.pl $(srcdir)/be/mips
-
-$(srcdir)/be/mips/gen_mips_machine.c $(srcdir)/be/mips/gen_mips_machine.h: \
- be/mips/mips_spec.pl be/scripts/generate_machine.pl
- $(PERL) $(srcdir)/be/scripts/generate_machine.pl $(srcdir)/be/mips/mips_spec.pl $(srcdir)/be/mips
-
-$(srcdir)/be/mips/gen_mips_regalloc_if.c $(srcdir)/be/mips/gen_mips_regalloc_if.h: \
- be/mips/mips_spec.pl be/scripts/generate_machine.pl
- $(PERL) $(srcdir)/be/scripts/generate_regalloc_if.pl $(srcdir)/be/mips/mips_spec.pl $(srcdir)/be/mips
-
# sparc backend
sparc_sources = \
void be_init_daemelspill(void);
void be_init_dbgout(void);
void be_init_arch_ia32(void);
-void be_init_arch_mips(void);
void be_init_arch_arm(void);
void be_init_arch_sparc(void);
void be_init_arch_amd64(void);
be_init_stabs();
be_init_arch_ia32();
- be_init_arch_mips();
be_init_arch_arm();
be_init_arch_sparc();
be_init_arch_amd64();
+++ /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 mips backend driver file.
- * @author Matthias Braun, Mehdi
- * @version $Id$
- */
-#include "config.h"
-
-#include "pseudo_irg.h"
-#include "irgwalk.h"
-#include "irprog.h"
-#include "irprintf.h"
-#include "ircons.h"
-#include "iroptimize.h"
-#include "irgopt.h"
-#include "irgwalk.h"
-#include "iredges.h"
-#include "irdump.h"
-#include "irextbb.h"
-#include "irtools.h"
-#include "error.h"
-
-#include "bitset.h"
-#include "debug.h"
-
-#include "../bearch.h"
-#include "../benode.h"
-#include "../belower.h"
-#include "../besched.h"
-#include "../beblocksched.h"
-#include "../beirg.h"
-#include "be.h"
-#include "../beabi.h"
-#include "../bemachine.h"
-#include "../bemodule.h"
-#include "../bespillslots.h"
-#include "../beemitter.h"
-#include "../begnuas.h"
-
-#include "bearch_mips_t.h"
-
-#include "mips_new_nodes.h"
-#include "gen_mips_regalloc_if.h"
-#include "mips_transform.h"
-#include "mips_emitter.h"
-#include "mips_map_regs.h"
-#include "mips_util.h"
-#include "mips_scheduler.h"
-
-#define DEBUG_MODULE "firm.be.mips.isa"
-
-/**************************************************
- * _ _ _ __
- * | | | (_)/ _|
- * _ __ ___ __ _ __ _| | | ___ ___ _| |_
- * | '__/ _ \/ _` | / _` | | |/ _ \ / __| | | _|
- * | | | __/ (_| | | (_| | | | (_) | (__ | | |
- * |_| \___|\__, | \__,_|_|_|\___/ \___| |_|_|
- * __/ |
- * |___/
- **************************************************/
-
-static arch_irn_class_t mips_classify(const ir_node *irn)
-{
- (void) irn;
- return 0;
-}
-
-int mips_is_Load(const ir_node *node)
-{
- return is_mips_lw(node) || is_mips_lh(node) || is_mips_lhu(node) ||
- is_mips_lb(node) || is_mips_lbu(node);
-}
-
-int mips_is_Store(const ir_node *node)
-{
- return is_mips_sw(node) || is_mips_sh(node) || is_mips_sb(node);
-}
-
-static ir_entity *mips_get_frame_entity(const ir_node *node)
-{
- const mips_load_store_attr_t *attr;
-
- if (!is_mips_irn(node))
- return NULL;
- if (!mips_is_Load(node) && !mips_is_Store(node))
- return NULL;
-
- attr = get_mips_load_store_attr_const(node);
- return attr->stack_entity;
-}
-
-static void mips_set_frame_entity(ir_node *node, ir_entity *entity)
-{
- mips_load_store_attr_t *attr;
-
- if (!is_mips_irn(node)) {
- panic("trying to set frame entity on non load/store node %+F", node);
- }
- if (!mips_is_Load(node) && !mips_is_Store(node)) {
- panic("trying to set frame entity on non load/store node %+F", node);
- }
-
- attr = get_irn_generic_attr(node);
- attr->stack_entity = entity;
-}
-
-/**
- * This function is called by the generic backend to correct offsets for
- * nodes accessing the stack.
- */
-static void mips_set_frame_offset(ir_node *node, int offset)
-{
- mips_load_store_attr_t *attr;
-
- if (!is_mips_irn(node)) {
- panic("trying to set frame offset on non load/store node %+F", node);
- }
- if (!mips_is_Load(node) && !mips_is_Store(node)) {
- panic("trying to set frame offset on non load/store node %+F", node);
- }
-
- attr = get_irn_generic_attr(node);
- attr->offset += offset;
-
- if (attr->offset < -32768 || attr->offset > 32767) {
- panic("Out of stack space! (mips supports only 16bit offsets)");
- }
-}
-
-static int mips_get_sp_bias(const ir_node *irn)
-{
- (void) irn;
- return 0;
-}
-
-/* fill register allocator interface */
-
-static const arch_irn_ops_t mips_irn_ops = {
- get_mips_in_req,
- mips_classify,
- mips_get_frame_entity,
- mips_set_frame_entity,
- mips_set_frame_offset,
- mips_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 mips firm graph
- */
-static void mips_prepare_graph(void *self)
-{
- mips_code_gen_t *cg = self;
-
- /* do local optimizations */
- optimize_graph_df(cg->irg);
-
- /* TODO: we often have dead code reachable through out-edges here. So for
- * now we rebuild edges (as we need correct user count for code selection)
- */
-#if 1
- edges_deactivate(cg->irg);
- edges_activate(cg->irg);
-#endif
-
- // walk the graph and transform firm nodes into mips nodes where possible
- mips_transform_graph(cg);
- dump_ir_graph(cg->irg, "transformed");
-
- /* do local optimizations (mainly CSE) */
- optimize_graph_df(cg->irg);
-
- /* do code placement, to optimize the position of constants */
- place_code(cg->irg);
-
- dump_ir_graph(cg->irg, "place");
-}
-
-/**
- * Called immediately before emit phase.
- */
-static void mips_finish_irg(void *self)
-{
- mips_code_gen_t *cg = self;
- ir_graph *irg = cg->irg;
-
- /* create block schedule, this also removes empty blocks which might
- * produce critical edges */
- cg->block_schedule = be_create_block_schedule(irg);
-
- dump_ir_graph(irg, "mips-finished");
-}
-
-
-static void mips_before_ra(void *self)
-{
- (void) self;
-}
-
-static void mips_after_ra(void* self)
-{
- mips_code_gen_t *cg = self;
- be_coalesce_spillslots(cg->irg);
- irg_walk_blkwise_graph(cg->irg, NULL, mips_after_ra_walker, self);
-}
-
-/**
- * Emits the code, closes the output file and frees
- * the code generator interface.
- */
-static void mips_emit_and_done(void *self)
-{
- mips_code_gen_t *cg = self;
- ir_graph *irg = cg->irg;
- (void) self;
-
- mips_gen_routine(cg, irg);
-
- /* de-allocate code generator */
- del_set(cg->reg_set);
- free(cg);
-}
-
-static void *mips_cg_init(ir_graph *irg);
-
-static const arch_code_generator_if_t mips_code_gen_if = {
- mips_cg_init,
- NULL, /* get_pic_base */
- NULL, /* before abi introduce */
- mips_prepare_graph,
- NULL, /* spill */
- mips_before_ra, /* before register allocation hook */
- mips_after_ra,
- mips_finish_irg,
- mips_emit_and_done
-};
-
-/**
- * Initializes the code generator.
- */
-static void *mips_cg_init(ir_graph *irg)
-{
- const arch_env_t *arch_env = be_get_irg_arch_env(irg);
- mips_isa_t *isa = (mips_isa_t *) arch_env;
- mips_code_gen_t *cg = XMALLOCZ(mips_code_gen_t);
-
- cg->impl = &mips_code_gen_if;
- cg->irg = irg;
- cg->reg_set = new_set(mips_cmp_irn_reg_assoc, 1024);
- cg->isa = isa;
-
- isa->cg = cg;
-
- return (arch_code_generator_t *)cg;
-}
-
-
-/*****************************************************************
- * ____ _ _ _____ _____
- * | _ \ | | | | |_ _|/ ____| /\
- * | |_) | __ _ ___| | _____ _ __ __| | | | | (___ / \
- * | _ < / _` |/ __| |/ / _ \ '_ \ / _` | | | \___ \ / /\ \
- * | |_) | (_| | (__| < __/ | | | (_| | _| |_ ____) / ____ \
- * |____/ \__,_|\___|_|\_\___|_| |_|\__,_| |_____|_____/_/ \_\
- *
- *****************************************************************/
-
-static mips_isa_t mips_isa_template = {
- {
- &mips_isa_if,
- &mips_gp_regs[REG_SP],
- &mips_gp_regs[REG_FP],
- &mips_reg_classes[CLASS_mips_gp],
- -1, /* stack direction */
- 2, /* power of two stack alignment for calls, 2^2 == 4 */
- NULL, /* main environment */
- 7, /* spill costs */
- 5, /* reload costs */
- },
- NULL, /* cg */
-};
-
-/**
- * Initializes the backend ISA and opens the output file.
- */
-static arch_env_t *mips_init(FILE *file_handle)
-{
- static int inited = 0;
- mips_isa_t *isa;
-
- if (inited)
- return NULL;
- inited = 1;
-
- isa = XMALLOC(mips_isa_t);
- memcpy(isa, &mips_isa_template, sizeof(isa[0]));
-
- be_emit_init(file_handle);
-
- mips_register_init();
- mips_create_opcodes(&mips_irn_ops);
- // mips_init_opcode_transforms();
-
- return &isa->arch_env;
-}
-
-/**
- * Closes the output file and frees the ISA structure.
- */
-static void mips_done(void *self)
-{
- mips_isa_t *isa = self;
-
- be_gas_emit_decls(isa->arch_env.main_env);
-
- be_emit_exit();
- free(isa);
-}
-
-static unsigned mips_get_n_reg_class(void)
-{
- return N_CLASSES;
-}
-
-static const arch_register_class_t *mips_get_reg_class(unsigned i)
-{
- assert(i < N_CLASSES);
- return &mips_reg_classes[i];
-}
-
-
-
-/**
- * Get the register class which shall be used to store a value of a given mode.
- * @param self The this pointer.
- * @param mode The mode in question.
- * @return A register class which can hold values of the given mode.
- */
-static const arch_register_class_t *mips_get_reg_class_for_mode(const ir_mode *mode)
-{
- (void) mode;
- ASSERT_NO_FLOAT(mode);
- return &mips_reg_classes[CLASS_mips_gp];
-}
-
-typedef struct {
- be_abi_call_flags_bits_t flags;
- const arch_env_t *arch_env;
- ir_graph *irg;
- // do special handling to support debuggers
- int debug;
-} mips_abi_env_t;
-
-static void *mips_abi_init(const be_abi_call_t *call, const arch_env_t *arch_env, ir_graph *irg)
-{
- mips_abi_env_t *env = XMALLOC(mips_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;
- env->debug = 1;
- return env;
-}
-
-static const arch_register_t *mips_abi_prologue(void *self, ir_node** mem, pmap *reg_map, int *stack_bias)
-{
- mips_abi_env_t *env = self;
- ir_graph *irg = env->irg;
- ir_node *block = get_irg_start_block(irg);
- ir_node *sp = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_SP]);
- ir_node *fp = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_FP]);
- int initialstackframesize;
-
- (void) stack_bias;
-
- if (env->debug) {
- /*
- * The calling conventions wants a stack frame of at least 24bytes size with
- * a0-a3 saved in offset 0-12
- * fp saved in offset 16
- * ra saved in offset 20
- */
- ir_node *mm[6];
- ir_node *sync, *reg, *store;
- initialstackframesize = 24;
-
- // - setup first part of stackframe
- sp = new_bd_mips_addu(NULL, block, sp,
- mips_create_Immediate(initialstackframesize));
- arch_set_irn_register(sp, &mips_gp_regs[REG_SP]);
-
- /* TODO: where to get an edge with a0-a3
- int i;
- for (i = 0; i < 4; ++i) {
- ir_node *reg = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_A0 + i]);
- ir_node *store = new_bd_mips_store_r(dbg, block, *mem, sp, reg, mode_T);
- attr = get_mips_attr(store);
- attr->load_store_mode = mode_Iu;
- attr->tv = new_tarval_from_long(i * 4, mode_Is);
-
- mm[i] = new_r_Proj(irg, store, mode_M, pn_Store_M);
- }
- */
-
- reg = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_FP]);
- store = new_bd_mips_sw(NULL, block, sp, reg, *mem, NULL, 16);
-
- mm[4] = store;
-
- reg = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_RA]);
- store = new_bd_mips_sw(NULL, block, sp, reg, *mem, NULL, 20);
-
- mm[5] = store;
-
- /* Note: ideally we would route these mem edges directly towards the
- * epilogue, but this is currently not supported so we sync all mems
- * together */
- sync = new_r_Sync(block, 2, mm+4);
- *mem = sync;
- } else {
- ir_node *reg, *store;
- initialstackframesize = 4;
-
- // save old framepointer
- sp = new_bd_mips_addu(NULL, block, sp,
- mips_create_Immediate(-initialstackframesize));
- arch_set_irn_register(sp, &mips_gp_regs[REG_SP]);
-
- reg = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_FP]);
- store = new_bd_mips_sw(NULL, block, sp, reg, *mem, NULL, 0);
-
- *mem = store;
- }
-
- // setup framepointer
- fp = new_bd_mips_addu(NULL, block, sp,
- mips_create_Immediate(-initialstackframesize));
- arch_set_irn_register(fp, &mips_gp_regs[REG_FP]);
-
- be_abi_reg_map_set(reg_map, &mips_gp_regs[REG_FP], fp);
- be_abi_reg_map_set(reg_map, &mips_gp_regs[REG_SP], sp);
-
- return &mips_gp_regs[REG_SP];
-}
-
-static void mips_abi_epilogue(void *self, ir_node *block, ir_node **mem, pmap *reg_map)
-{
- mips_abi_env_t *env = self;
-
- ir_node *sp = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_SP]);
- ir_node *fp = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_FP]);
- ir_node *load;
- int initial_frame_size = env->debug ? 24 : 4;
- int fp_save_offset = env->debug ? 16 : 0;
-
- // copy fp to sp
- sp = new_bd_mips_or(NULL, block, fp, mips_create_zero());
- arch_set_irn_register(sp, &mips_gp_regs[REG_SP]);
-
- // 1. restore fp
- load = new_bd_mips_lw(NULL, block, sp, *mem, NULL,
- fp_save_offset - initial_frame_size);
-
- fp = new_r_Proj(load, mode_Iu, pn_mips_lw_res);
- *mem = new_r_Proj(load, mode_Iu, pn_mips_lw_M);
- arch_set_irn_register(fp, &mips_gp_regs[REG_FP]);
-
- be_abi_reg_map_set(reg_map, &mips_gp_regs[REG_FP], fp);
- be_abi_reg_map_set(reg_map, &mips_gp_regs[REG_SP], sp);
-}
-
-/**
- * Produces the type which sits between the stack args and the locals on the stack.
- * it will contain the return address and space to store the old frame pointer.
- * @return The Firm type modelling the ABI between type.
- */
-static ir_type *mips_abi_get_between_type(void *self)
-{
- mips_abi_env_t *env = self;
-
- static ir_type *debug_between_type = NULL;
- static ir_type *opt_between_type = NULL;
- static ir_entity *old_fp_ent = NULL;
-
- if (env->debug && debug_between_type == NULL) {
- ir_entity *a0_ent, *a1_ent, *a2_ent, *a3_ent;
- ir_entity *ret_addr_ent;
- ir_type *ret_addr_type = new_type_primitive(mode_P);
- ir_type *old_fp_type = new_type_primitive(mode_P);
- ir_type *old_param_type = new_type_primitive(mode_Iu);
-
- debug_between_type = new_type_class(new_id_from_str("mips_between_type"));
- a0_ent = new_entity(debug_between_type, new_id_from_str("a0_ent"), old_param_type);
- a1_ent = new_entity(debug_between_type, new_id_from_str("a1_ent"), old_param_type);
- a2_ent = new_entity(debug_between_type, new_id_from_str("a2_ent"), old_param_type);
- a3_ent = new_entity(debug_between_type, new_id_from_str("a3_ent"), old_param_type);
- old_fp_ent = new_entity(debug_between_type, new_id_from_str("old_fp"), old_fp_type);
- ret_addr_ent = new_entity(debug_between_type, new_id_from_str("ret_addr"), ret_addr_type);
-
- set_entity_offset(a0_ent, 0);
- set_entity_offset(a1_ent, 4);
- set_entity_offset(a2_ent, 8);
- set_entity_offset(a3_ent, 12);
- set_entity_offset(old_fp_ent, 16);
- set_entity_offset(ret_addr_ent, 20);
-
- set_type_size_bytes(debug_between_type, 24);
- } else if (!env->debug && opt_between_type == NULL) {
- ir_type *old_fp_type = new_type_primitive(mode_P);
- ir_entity *old_fp_ent;
-
- opt_between_type = new_type_class(new_id_from_str("mips_between_type"));
- old_fp_ent = new_entity(opt_between_type, new_id_from_str("old_fp"), old_fp_type);
- set_entity_offset(old_fp_ent, 0);
- set_type_size_bytes(opt_between_type, 4);
- }
-
- return env->debug ? debug_between_type : opt_between_type;
-}
-
-static const be_abi_callbacks_t mips_abi_callbacks = {
- mips_abi_init,
- free,
- mips_abi_get_between_type,
- mips_abi_prologue,
- mips_abi_epilogue,
-};
-
-/**
- * Get the ABI restrictions for procedure calls.
- * @param self The this pointer.
- * @param method_type The type of the method (procedure) in question.
- * @param abi The abi object to be modified
- */
-static void mips_get_call_abi(const void *self, ir_type *method_type,
- be_abi_call_t *abi)
-{
- ir_type *tp;
- ir_mode *mode;
- int n = get_method_n_params(method_type);
- int result_count;
- int i;
- ir_mode **modes;
- const arch_register_t *reg;
- be_abi_call_flags_t call_flags;
- (void) self;
-
- memset(&call_flags, 0, sizeof(call_flags));
- call_flags.bits.left_to_right = 0;
- call_flags.bits.store_args_sequential = 0;
- 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, &mips_abi_callbacks);
-
- /* collect the mode for each type */
- modes = ALLOCAN(ir_mode*, n);
- for (i = 0; i < n; i++) {
- tp = get_method_param_type(method_type, i);
- modes[i] = get_type_mode(tp);
- }
-
- // assigns parameters to registers or stack
- for (i = 0; i < n; i++) {
- // first 4 params in $a0-$a3, the others on the stack
- if (i < 4) {
- reg = &mips_gp_regs[REG_A0 + i];
- be_abi_call_param_reg(abi, i, reg, ABI_CONTEXT_BOTH);
- } else {
- /* default: all parameters on stack */
- be_abi_call_param_stack(abi, i, modes[i], 4, 0, 0, ABI_CONTEXT_BOTH);
- }
- }
-
- /* set return register */
- /* default: return value is in R0 (and maybe R1) */
- result_count = get_method_n_ress(method_type);
- assert(result_count <= 2 && "More than 2 result values not supported");
- for (i = 0; i < result_count; ++i) {
- const arch_register_t* reg;
- tp = get_method_res_type(method_type, i);
- mode = get_type_mode(tp);
- ASSERT_NO_FLOAT(mode);
-
- reg = &mips_gp_regs[REG_V0 + i];
- be_abi_call_res_reg(abi, i, reg, ABI_CONTEXT_BOTH);
- }
-}
-
-/**
- * Initializes the code generator interface.
- */
-static const arch_code_generator_if_t *mips_get_code_generator_if(void *self)
-{
- (void) self;
- return &mips_code_gen_if;
-}
-
-/**
- * Returns the necessary byte alignment for storing a register of given class.
- */
-static int mips_get_reg_class_alignment(const arch_register_class_t *cls)
-{
- ir_mode *mode = arch_register_class_mode(cls);
- return get_mode_size_bytes(mode);
-}
-
-static const be_execution_unit_t ***mips_get_allowed_execution_units(
- const ir_node *irn)
-{
- (void) irn;
- /* TODO */
- panic("Unimplemented mips_get_allowed_execution_units()");
-}
-
-static const be_machine_t *mips_get_machine(const void *self)
-{
- (void) self;
- /* TODO */
- panic("Unimplemented mips_get_machine()");
-}
-
-/**
- * Return irp irgs in the desired order.
- */
-static ir_graph **mips_get_irg_list(const void *self, ir_graph ***irg_list)
-{
- (void) self;
- (void) irg_list;
- return NULL;
-}
-
-/**
- * Returns the libFirm configuration parameter for this backend.
- */
-static const backend_params *mips_get_libfirm_params(void)
-{
- static backend_params p = {
- 1, /* need dword lowering */
- 0, /* don't support inline assembler yet */
- NULL, /* will be set later */
- NULL, /* but yet no creator function */
- NULL, /* context for create_intrinsic_fkt */
- NULL, /* no if conversion settings */
- NULL, /* float arithmetic mode (TODO) */
- 0, /* no trampoline support: size 0 */
- 0, /* no trampoline support: align 0 */
- NULL, /* no trampoline support: no trampoline builder */
- 4 /* alignment of stack parameter */
- };
-
- return &p;
-}
-
-static asm_constraint_flags_t mips_parse_asm_constraint(const char **c)
-{
- (void) c;
- return ASM_CONSTRAINT_FLAG_INVALID;
-}
-
-static int mips_is_valid_clobber(const char *clobber)
-{
- (void) clobber;
- return 0;
-}
-
-const arch_isa_if_t mips_isa_if = {
- mips_init,
- mips_done,
- NULL, /* handle intrinsics */
- mips_get_n_reg_class,
- mips_get_reg_class,
- mips_get_reg_class_for_mode,
- mips_get_call_abi,
- mips_get_code_generator_if,
- mips_get_list_sched_selector,
- mips_get_ilp_sched_selector,
- mips_get_reg_class_alignment,
- mips_get_libfirm_params,
- mips_get_allowed_execution_units,
- mips_get_machine,
- mips_get_irg_list,
- NULL, /* mark remat */
- mips_parse_asm_constraint,
- mips_is_valid_clobber
-};
-
-BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_mips);
-void be_init_arch_mips(void)
-{
- be_register_isa_if("mips", &mips_isa_if);
-}
+++ /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 the mips backend
- * @author Matthias Braun, Mehdi
- * @version $Id$
- */
-#ifndef FIRM_BE_MIPS_BEARCH_MIPS_H
-#define FIRM_BE_MIPS_BEARCH_MIPS_H
-
-#include "../bearch.h"
-
-typedef struct mips_code_gen_t mips_code_gen_t;
-
-extern const arch_isa_if_t mips_isa_if;
-
-int mips_is_Load(const ir_node *node);
-int mips_is_Store(const ir_node *node);
-
-#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 datastructures and declarations for the mips backend
- * @author Matthias Braun, Mehdi
- * @version $Id$
- */
-#ifndef FIRM_BE_MIPS_BEARCH_MIPS_T_H
-#define FIRM_BE_MIPS_BEARCH_MIPS_T_H
-
-#include "debug.h"
-#include "irgopt.h"
-#include "bearch_mips.h"
-#include "mips_nodes_attr.h"
-#include "be.h"
-#include "../beemitter.h"
-#include "set.h"
-
-typedef struct mips_isa_t mips_isa_t;
-typedef struct mips_transform_env_t mips_transform_env_t;
-
-struct mips_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) */
- mips_isa_t *isa; /**< the isa instance */
- ir_node **block_schedule;
-};
-
-struct mips_isa_t {
- arch_env_t arch_env; /**< must be derived from arch_env_t */
- mips_code_gen_t *cg;
-};
-
-
-/**
- * this is a struct to minimize the number of parameters
- * for transformation walker
- */
-struct mips_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 */
- mips_code_gen_t *cg; /**< The code generator */
-};
-
-#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 implementation of mips assembly emitter
- * @author Matthias Braun, Mehdi
- * @version $Id$
- */
-#include "config.h"
-
-#include <limits.h>
-
-#include "xmalloc.h"
-#include "iredges.h"
-#include "debug.h"
-#include "irgwalk.h"
-#include "irprintf.h"
-#include "irop_t.h"
-#include "irargs_t.h"
-#include "irprog_t.h"
-#include "irouts.h"
-#include "tv.h"
-#include "error.h"
-
-#include "../besched.h"
-#include "../benode.h"
-#include "../beutil.h"
-#include "../begnuas.h"
-
-#include "mips_emitter.h"
-#include "gen_mips_emitter.h"
-#include "mips_nodes_attr.h"
-#include "mips_new_nodes.h"
-#include "mips_map_regs.h"
-
-#define SNPRINTF_BUF_LEN 128
-
-/**
- * Returns the register at in position pos.
- */
-static const arch_register_t *get_in_reg(const ir_node *node, int pos)
-{
- ir_node *op;
- const arch_register_t *reg = NULL;
-
- assert(get_irn_arity(node) > pos && "Invalid IN position");
-
- /* The out register of the operator at position pos is the
- in register we need. */
- op = get_irn_n(node, pos);
-
- reg = arch_get_irn_register(op);
-
- assert(reg && "no in register found");
- return reg;
-}
-
-/**
- * Returns the register at out position pos.
- */
-static const arch_register_t *get_out_reg(const ir_node *node, int pos)
-{
- ir_node *proj;
- const arch_register_t *reg = NULL;
-
- /* 1st case: irn is not of mode_T, so it has only */
- /* one OUT register -> good */
- /* 2nd case: irn is of mode_T -> collect all Projs and ask the */
- /* Proj with the corresponding projnum for the register */
-
- if (get_irn_mode(node) != mode_T) {
- reg = arch_get_irn_register(node);
- } else if (is_mips_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;
-}
-
-/*************************************************************
- * _ _ __ _ _
- * (_) | | / _| | | | |
- * _ __ _ __ _ _ __ | |_| |_ | |__ ___| |_ __ ___ _ __
- * | '_ \| '__| | '_ \| __| _| | '_ \ / _ \ | '_ \ / _ \ '__|
- * | |_) | | | | | | | |_| | | | | | __/ | |_) | __/ |
- * | .__/|_| |_|_| |_|\__|_| |_| |_|\___|_| .__/ \___|_|
- * | | | |
- * |_| |_|
- *************************************************************/
-
-/**
- * Emit the name of the source register at given input position.
- */
-void mips_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));
-}
-
-/**
- * Emit the name of the destination register at given output position.
- */
-void mips_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));
-}
-
-#if 0
-static const char *get_symconst_str(ir_node *node)
-{
- ident *id;
-
- switch (get_SymConst_kind(node)) {
- case symconst_addr_ent:
- id = get_entity_ident(get_SymConst_entity(node));
- return get_id_str(id);
- default:
- panic("Unsupported SymConst kind");
- }
-
- return NULL;
-}
-
-/**
- * Return a const or symconst as string.
- */
-static const char *node_const_to_str(ir_node *n)
-{
- static char buf[64];
- const mips_attr_t *attr = get_mips_attr(n);
- long val;
-
- if (is_mips_load_r(n) || is_mips_store_r(n)) {
- mips_attr_t *attr = get_mips_attr(n);
- ir_node *symconst;
-
- if (attr->tv != NULL) {
- val = get_tarval_long(attr->tv);
- snprintf(buf, sizeof(buf), "%ld", val);
-
- return buf;
- }
- if (attr->stack_entity != NULL) {
- snprintf(buf, sizeof(buf), "%d", attr->stack_entity_offset);
- return buf;
- }
-
- symconst = get_irn_n(n, 1);
- assert(get_irn_opcode(symconst) == iro_SymConst);
-
- return get_symconst_str(symconst);
- } else if (is_mips_la(n)) {
- snprintf(buf, sizeof(buf), "%s", get_id_str(attr->symconst_id));
- return buf;
- } else if (is_mips_lli(n)) {
- assert(attr->tv != NULL);
- if (get_mode_sign(get_tarval_mode(attr->tv))) {
- long val = get_tarval_long(attr->tv);
- snprintf(buf, sizeof(buf), "0x%04lX", val & 0xffff);
- } else {
- unsigned long val = get_tarval_long(attr->tv);
- snprintf(buf, sizeof(buf), "0x%04lX", val & 0xffff);
- }
-
- return buf;
- } else if (is_mips_lui(n)) {
- assert(attr->tv != NULL);
- if (get_mode_sign(get_tarval_mode(attr->tv))) {
- long val = get_tarval_long(attr->tv);
- val = (val & 0xffff0000) >> 16;
- snprintf(buf, sizeof(buf), "0x%04lX", val & 0xffff);
- } else {
- unsigned long val = get_tarval_long(attr->tv);
- val = (val & 0xffff0000) >> 16;
- snprintf(buf, sizeof(buf), "0x%04lX", val & 0xffff);
- }
-
- return buf;
- }
-
- assert(attr->tv != NULL);
- val = get_tarval_long(attr->tv);
- snprintf(buf, sizeof(buf), "%ld", val);
-
- return buf;
-}
-#endif
-
-void mips_emit_load_store_address(const ir_node *node, int pos)
-{
- const mips_load_store_attr_t *attr = get_mips_load_store_attr_const(node);
-
- be_emit_irprintf("%d(", attr->offset);
- mips_emit_source_register(node, pos);
- be_emit_char(')');
-}
-
-void mips_emit_immediate_suffix(const ir_node *node, int pos)
-{
- ir_node *op = get_irn_n(node, pos);
- if (is_mips_Immediate(op))
- be_emit_char('i');
-}
-
-void mips_emit_immediate(const ir_node *node)
-{
- const mips_immediate_attr_t *attr = get_mips_immediate_attr_const(node);
-
- switch (attr->imm_type) {
- case MIPS_IMM_CONST:
- be_emit_irprintf("%d", attr->val);
- break;
- case MIPS_IMM_SYMCONST_LO:
- be_emit_cstring("%lo($");
- be_emit_ident(get_entity_ld_ident(attr->entity));
- if (attr->val != 0) {
- be_emit_irprintf("%+d", attr->val);
- }
- be_emit_char(')');
- break;
- case MIPS_IMM_SYMCONST_HI:
- be_emit_cstring("%hi($");
- be_emit_ident(get_entity_ld_ident(attr->entity));
- if (attr->val != 0) {
- be_emit_irprintf("%+d", attr->val);
- }
- be_emit_char(')');
- break;
- default:
- panic("invalid immediate type found");
- }
-}
-
-/**
- * Emit the name of the destination register at given output position.
- */
-void mips_emit_source_register_or_immediate(const ir_node *node, int pos)
-{
- const ir_node *op = get_irn_n(node, pos);
- if (is_mips_Immediate(op)) {
- mips_emit_immediate(op);
- } else {
- mips_emit_source_register(node, pos);
- }
-}
-
-#if 0
-/*
- * Add a number to a prefix. This number will not be used a second time.
- */
-static char *get_unique_label(char *buf, size_t buflen, const char *prefix)
-{
- static unsigned long id = 0;
- snprintf(buf, buflen, "%s%lu", prefix, ++id);
- return buf;
-}
-#endif
-
-/************************************************************************/
-/* ABI Handling */
-/************************************************************************/
-
-static void mips_emit_IncSP(const ir_node *node)
-{
- int offset = be_get_IncSP_offset(node);
-
- if (offset == 0) {
- return;
- }
-
- if (offset > 0xffff || offset < -0xffff) {
- panic("stackframe > 2^16 bytes not supported yet");
- }
-
- if (offset > 0) {
- be_emit_irprintf("\tsubu $sp, $sp, %d", offset);
- } else {
- be_emit_irprintf("\taddu $sp, $sp, %d", -offset);
- }
- be_emit_finish_line_gas(node);
-}
-
-static void mips_emit_Copy(const ir_node *node)
-{
- be_emit_cstring("\tmove ");
- mips_emit_dest_register(node, 0);
- be_emit_cstring(", ");
- mips_emit_source_register(node, 0);
- be_emit_finish_line_gas(node);
-}
-
-static void mips_emit_Return(const ir_node* node)
-{
- be_emit_cstring("\tj $ra");
- be_emit_finish_line_gas(node);
-}
-
-static __attribute__((unused))
-void mips_emit_nops(int n)
-{
- int i;
-
- for (i = 0; i < n; ++i) {
- be_emit_cstring("\tnop\n");
- be_emit_write_line();
- }
-}
-
-static void mips_emit_Perm(const ir_node *node)
-{
- assert(get_irn_arity(node) == 2);
-
- be_emit_cstring("\txor ");
- mips_emit_source_register(node, 0);
- be_emit_cstring(", ");
- mips_emit_source_register(node, 0);
- be_emit_cstring(", ");
- mips_emit_source_register(node, 1);
- be_emit_finish_line_gas(node);
-
- /* mips_emit_nops(3); */
-
- be_emit_cstring("\txor ");
- mips_emit_source_register(node, 1);
- be_emit_cstring(", ");
- mips_emit_source_register(node, 1);
- be_emit_cstring(", ");
- mips_emit_source_register(node, 0);
- be_emit_finish_line_gas(node);
-
- /* mips_emit_nops(3); */
-
- be_emit_cstring("\txor ");
- mips_emit_source_register(node, 0);
- be_emit_cstring(", ");
- mips_emit_source_register(node, 0);
- be_emit_cstring(", ");
- mips_emit_source_register(node, 1);
- be_emit_finish_line_gas(node);
-
- /* mips_emit_nops(3); */
-}
-
-/************************************************************************/
-/* Calls */
-/************************************************************************/
-
-static void mips_emit_Call(const ir_node *node)
-{
- ir_entity *callee;
-
- be_emit_cstring("\tjal ");
-
- /* call of immediate value (label) */
- callee = be_Call_get_entity(node);
- if (callee != NULL) {
- be_emit_ident(get_entity_ld_ident(callee));
- } else {
- mips_emit_source_register(node, be_pos_Call_ptr);
- }
- be_emit_finish_line_gas(node);
-}
-
-/************************************************************************
- * _
- * | |_ _ _ __ ___ _ __ ___
- * _ | | | | | '_ ` _ \| '_ \/ __|
- * | |_| | |_| | | | | | | |_) \__ \
- * \___/ \__,_|_| |_| |_| .__/|___/
- * |_|
- ************************************************************************/
-
-static void mips_emit_Jump(const ir_node *node)
-{
- const ir_node *block = get_irn_link(node);
- assert(is_Block(block));
-
- be_emit_cstring("\tb ");
- be_gas_emit_block_name(block);
- be_emit_finish_line_gas(node);
-}
-
-ir_node *mips_get_jump_block(const ir_node* node, long projn)
-{
- const ir_edge_t *oute;
- for (oute = get_irn_out_edge_first(node); oute != NULL;
- oute = get_irn_out_edge_next(node, oute)) {
- ir_node *proj = get_edge_src_irn(oute);
- long n;
- assert(is_Proj(proj));
-
- n = get_Proj_proj(proj);
- if (n == projn)
- return get_irn_link(proj);
- }
-
- return NULL;
-}
-
-void mips_emit_jump_target_proj(const ir_node *node, long projn)
-{
- ir_node *jumpblock = mips_get_jump_block(node, projn);
- assert(jumpblock != NULL);
-
- be_gas_emit_block_name(jumpblock);
-}
-
-void mips_emit_jump_target(const ir_node *node)
-{
- ir_node *jumpblock = get_irn_link(node);
- assert(jumpblock != NULL);
-
- be_gas_emit_block_name(jumpblock);
-}
-
-void mips_emit_jump_or_fallthrough(const ir_node *node, long pn)
-{
- ir_node *jumpblock = mips_get_jump_block(node, pn);
- assert(jumpblock != NULL);
-
- /* TODO: use fallthrough when possible */
- be_emit_cstring("b ");
- be_gas_emit_block_name(jumpblock);
-}
-
-/************************************************************************
- * ____ _ _ _ _ *
- * / ___|_ _(_) |_ ___| |__ | |_ _ _ __ ___ _ __ *
- * \___ \ \ /\ / / | __/ __| '_ \ _ | | | | | '_ ` _ \| '_ \ *
- * ___) \ V V /| | || (__| | | | |_| | |_| | | | | | | |_) | *
- * |____/ \_/\_/ |_|\__\___|_| |_|\___/ \__,_|_| |_| |_| .__/ *
- * |_| *
- * *
- ************************************************************************/
-
-#if 0
-/* jump table entry (target and corresponding number) */
-typedef struct _branch_t {
- ir_node *target;
- int value;
-} branch_t;
-
-/* jump table for switch generation */
-typedef struct _jmp_tbl_t {
- ir_node *defBlock; /**< default target */
- int min_value; /**< smallest switch case */
- int max_value; /**< largest switch case */
- int num_branches; /**< number of jumps */
- char *label; /**< label of the jump table */
- branch_t *branches; /**< jump array */
-} jmp_tbl_t;
-
-/**
- * Compare two variables of type branch_t. Used to sort all switch cases
- */
-static int mips_cmp_branch_t(const void *a, const void *b)
-{
- branch_t *b1 = (branch_t *)a;
- branch_t *b2 = (branch_t *)b;
-
- if (b1->value <= b2->value)
- return -1;
- else
- return 1;
-}
-
-const char* mips_get_jumptbl_label(const ir_node* switchjmp)
-{
- static char buf[64];
- snprintf(buf, sizeof(buf), "__JUMPTBL%ld", get_irn_node_nr(switchjmp));
-
- return buf;
-}
-
-/**
- * Emits code for a SwitchJmp (creates a jump table if
- * possible otherwise a cmp-jmp cascade). Stolen from ia32
- */
-void emit_mips_jump_table(const ir_node *irn)
-{
- int lastval, i, i2, pn;
- jmp_tbl_t tbl;
- ir_node *proj;
- const ir_edge_t *edge;
- const mips_attr_t *attr = get_mips_attr_const(irn);
-
- /* fill the table structure */
- tbl.label = XMALLOCN(char, SNPRINTF_BUF_LEN);
- tbl.label = get_unique_label(tbl.label, SNPRINTF_BUF_LEN, "JMPTBL_");
- tbl.defBlock = NULL;
- tbl.num_branches = get_irn_n_edges(irn);
- tbl.branches = XMALLOCNZ(branch_t, tbl.num_branches);
- tbl.min_value = INT_MAX;
- tbl.max_value = INT_MIN;
-
- i = 0;
- /* go over all proj's and collect them */
- foreach_out_edge(irn, edge) {
- proj = get_edge_src_irn(edge);
- assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
-
- pn = get_Proj_proj(proj);
-
- /* create branch entry */
- tbl.branches[i].target = get_irn_link(proj);
- tbl.branches[i].value = pn;
-
- tbl.min_value = pn < tbl.min_value ? pn : tbl.min_value;
- tbl.max_value = pn > tbl.max_value ? pn : tbl.max_value;
-
- i++;
- }
-
- /* sort the branches by their number */
- qsort(tbl.branches, tbl.num_branches, sizeof(tbl.branches[0]), mips_cmp_branch_t);
-
- be_emit_string(mips_get_jumptbl_label(irn));
- be_emit_cstring(":\n");
- be_emit_write_line();
- lastval = tbl.min_value;
- for (i = 0; i < tbl.num_branches; ++i) {
- const branch_t *branch = &tbl.branches[i];
- int value = branch->value;
-
- for (i2 = lastval + 1; i2 < value; ++i2) {
- be_emit_cstring("\t.word ");
- be_emit_ident(get_entity_ld_ident(attr->symconst));
- be_emit_char('\n');
- be_emit_write_line();
- }
-
- be_emit_cstring("\t.word ");
- be_gas_emit_block_name(branch->target);
- be_emit_char('\n');
- be_emit_write_line();
-
- lastval = branch->value;
- }
-
- if (tbl.label)
- free(tbl.label);
- if (tbl.branches)
- free(tbl.branches);
-}
-
-static void dump_jump_tables(ir_node* node, void *data)
-{
- (void) data;
-
- // emit jump tables
- if (is_mips_SwitchJump(node)) {
- be_emit_cstring(".data\n");
- be_emit_write_line();
-
- emit_mips_jump_table(node);
-
- be_emit_cstring(".text\n");
- be_emit_write_line();
- }
-}
-#endif
-
-/***********************************************************************************
- * _ __ _
- * (_) / _| | |
- * _ __ ___ __ _ _ _ __ | |_ _ __ __ _ _ __ ___ _____ _____ _ __| | __
- * | '_ ` _ \ / _` | | '_ \ | _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
- * | | | | | | (_| | | | | | | | | | | (_| | | | | | | __/\ V V / (_) | | | <
- * |_| |_| |_|\__,_|_|_| |_| |_| |_| \__,_|_| |_| |_|\___| \_/\_/ \___/|_| |_|\_\
- *
- ***********************************************************************************/
-
-static void mips_emit_nothing(const ir_node *node)
-{
- (void) node;
-}
-
-static void mips_emit_this_shouldnt_happen(const ir_node *node)
-{
- panic("Found non-lowered node %+F while emitting", node);
-}
-
-/**
- * The type of a emitter function.
- */
-typedef void (*emit_func) (const ir_node *);
-
-/**
- * Set a node emitter. Make it a bit more type safe.
- */
-static void register_emitter(ir_op *op, emit_func func)
-{
- op->ops.generic = (op_func) func;
-}
-
-/**
- * Register emitter functions for mips backend
- */
-void mips_register_emitters(void)
-{
- /* first clear the generic function pointer for all ops */
- clear_irp_opcodes_generic_func();
-
- /* register all emitter functions defined in spec */
- mips_register_spec_emitters();
-
- /* benode emitter */
- register_emitter(op_be_IncSP, mips_emit_IncSP);
- register_emitter(op_be_AddSP, mips_emit_this_shouldnt_happen);
- register_emitter(op_be_Call, mips_emit_Call);
- register_emitter(op_be_Copy, mips_emit_Copy);
- register_emitter(op_be_Keep, mips_emit_nothing);
- register_emitter(op_be_Barrier, mips_emit_nothing);
- register_emitter(op_be_Return, mips_emit_Return);
- register_emitter(op_be_Start, mips_emit_nothing);
- register_emitter(op_be_Spill, mips_emit_this_shouldnt_happen);
- register_emitter(op_be_Reload, mips_emit_this_shouldnt_happen);
- register_emitter(op_be_Perm, mips_emit_Perm);
-
- register_emitter(op_Proj, mips_emit_nothing);
- register_emitter(op_SymConst, mips_emit_this_shouldnt_happen);
- register_emitter(op_Const, mips_emit_this_shouldnt_happen);
- register_emitter(op_Jmp, mips_emit_Jump);
- register_emitter(op_Cmp, mips_emit_this_shouldnt_happen);
- register_emitter(op_Cond, mips_emit_this_shouldnt_happen);
- register_emitter(op_Phi, mips_emit_nothing);
-}
-
-/**
- * Emits assembly for a single node
- */
-static void mips_emit_node(const ir_node *node)
-{
- ir_op *op = get_irn_op(node);
-
- if (op->ops.generic) {
- emit_func emit = (emit_func) op->ops.generic;
- (*emit) (node);
- } else {
- panic("No emitter defined for node %+F", node);
- }
-}
-
-/**
- * Walks over the nodes in a block connected by scheduling edges
- * and emits code for each node.
- */
-static void mips_gen_block(const ir_node *block)
-{
- ir_node *node;
-
- if (! is_Block(block))
- return;
-
- be_gas_emit_block_name(block);
- be_emit_cstring(":\n");
- be_emit_write_line();
-
- sched_foreach(block, node) {
- mips_emit_node(node);
- }
-
- be_emit_char('\n');
- be_emit_write_line();
-}
-
-/**
- * Emits code for function start.
- */
-static void mips_emit_func_prolog(ir_graph *irg)
-{
- ident *irg_ident = get_entity_ld_ident(get_irg_entity(irg));
-
- // dump jump tables
- //irg_walk_graph(irg, NULL, dump_jump_tables, env);
-
- be_emit_write_line();
- be_gas_emit_switch_section(GAS_SECTION_TEXT);
-
- be_emit_cstring("\t.balign\t4\n");
-
- be_emit_cstring("\t.global\t");
- be_emit_ident(irg_ident);
- be_emit_char('\n');
-
- be_emit_cstring("\t.set\tnomips16\n");
-
- be_emit_cstring("\t.ent\t");
- be_emit_ident(irg_ident);
- be_emit_char('\n');
-
- be_emit_ident(irg_ident);
- be_emit_cstring(":\n");
-
- be_emit_cstring("\t.frame\t$fp, 24, $ra\n");
- be_emit_cstring("\t.mask\t0xc0000000, -4\n");
- be_emit_cstring("\t.fmask\t0x00000000, 0\n");
-
- be_emit_write_line();
-}
-
-/**
- * Emits code for function end
- */
-static void mips_emit_func_epilog(ir_graph *irg)
-{
- ident *irg_ident = get_entity_ident(get_irg_entity(irg));
-
- be_emit_cstring("\t.end\t");
- be_emit_ident(irg_ident);
- be_emit_char('\n');
- be_emit_write_line();
-}
-
-/**
- * Sets labels for control flow nodes (jump target)
- */
-static void mips_gen_labels(ir_node *block, void *env)
-{
- ir_node *pred;
- int n = get_Block_n_cfgpreds(block);
- (void) env;
-
- for (n--; n >= 0; n--) {
- pred = get_Block_cfgpred(block, n);
- set_irn_link(pred, block);
- }
-}
-
-/**
- * Main driver
- */
-void mips_gen_routine(mips_code_gen_t *mips_cg, ir_graph *irg)
-{
- int i, n;
-
- mips_register_emitters();
-
- irg_block_walk_graph(irg, mips_gen_labels, NULL, NULL);
-
- mips_emit_func_prolog(irg);
-
- n = ARR_LEN(mips_cg->block_schedule);
- for (i = 0; i < n; ++i) {
- ir_node *block = mips_cg->block_schedule[i];
- mips_gen_block(block);
- }
-
- mips_emit_func_epilog(irg);
-}
+++ /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 the mips assembler emitter
- * @author Matthias Braun, Mehdi
- * @version $Id$
- */
-#ifndef FIRM_BE_MIPS_MIPS_EMITTER_H
-#define FIRM_BE_MIPS_MIPS_EMITTER_H
-
-#include "irnode.h"
-
-#include "../bearch.h"
-#include "../beemitter.h"
-
-#include "bearch_mips_t.h"
-
-void mips_emit_source_register(const ir_node *node, int pos);
-void mips_emit_dest_register(const ir_node *node, int pos);
-void mips_emit_source_register_or_immediate(const ir_node *node, int pos);
-void mips_emit_immediate(const ir_node *node);
-void mips_emit_immediate_suffix(const ir_node *node, int pos);
-void mips_emit_load_store_address(const ir_node *node, int pos);
-void mips_emit_jump_target(const ir_node *node);
-void mips_emit_jump_target_proj(const ir_node *node, long pn);
-void mips_emit_jump_or_fallthrough(const ir_node *node, long pn);
-
-void mips_register_emitters(void);
-ir_node *mips_get_jump_block(const ir_node* node, long projn);
-
-/** returns the label used for a block */
-const char* mips_get_block_label(const ir_node* block);
-/** returns the label for the jumptable */
-const char* mips_get_jumptbl_label(const ir_node* switchjmp);
-
-void mips_gen_routine(mips_code_gen_t *cg, ir_graph *irg);
-
-#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 Register mapping for firm nodes. Stolen from bearch_firm :)
- * @author Matthias Braun, Mehdi
- * @version $Id$
- */
-#include "config.h"
-
-#include <stdlib.h>
-
-#include "mips_map_regs.h"
-#include "mips_new_nodes.h"
-
-/* Mapping to store registers in firm nodes */
-
-struct mips_irn_reg_assoc {
- const ir_node *irn;
- const arch_register_t *reg;
-};
-
-int mips_cmp_irn_reg_assoc(const void *a, const void *b, size_t size)
-{
- const struct mips_irn_reg_assoc *x = a;
- const struct mips_irn_reg_assoc *y = b;
- (void) size;
-
- return x->irn != y->irn;
-}
-
-static struct mips_irn_reg_assoc *get_irn_reg_assoc(const ir_node *irn, set *reg_set)
-{
- struct mips_irn_reg_assoc templ;
- unsigned int hash;
-
- templ.irn = irn;
- templ.reg = NULL;
- hash = HASH_PTR(irn);
-
- return set_insert(reg_set, &templ, sizeof(templ), hash);
-}
-
-void mips_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set)
-{
- struct mips_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
- assoc->reg = reg;
-}
-
-const arch_register_t *mips_get_firm_reg(const ir_node *irn, set *reg_set)
-{
- struct mips_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
- return assoc->reg;
-}
-
-/**
- * Translates the projnum into a "real" argument position for register
- * requirements dependend on the predecessor.
- */
-long mips_translate_proj_pos(const ir_node *proj)
-{
- return get_Proj_proj(proj);
-}
+++ /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 mips register allocation interface
- * @author Matthias Braun, Mehdi
- * @version $Id$
- */
-#ifndef FIRM_BE_MIPS_MIPS_MAP_REGS_H
-#define FIRM_BE_MIPS_MIPS_MAP_REGS_H
-
-#include "irnode.h"
-#include "set.h"
-
-#include "../bearch.h"
-#include "mips_nodes_attr.h"
-
-int mips_cmp_irn_reg_assoc(const void *a, const void *b, size_t len);
-void mips_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set);
-const arch_register_t *mips_get_firm_reg(const ir_node *irn, set *reg_set);
-
-long mips_translate_proj_pos(const ir_node *proj);
-
-#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 architecture specific firm
- * opcodes and the corresponding node constructors for the MIPS
- * assembler irg.
- * @author Matthias Braun, Mehdi
- * @version $Id$
- */
-#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 "mips_nodes_attr.h"
-#include "mips_new_nodes.h"
-#include "gen_mips_regalloc_if.h"
-
-
-
-/***********************************************************************************
- * _ _ _ __
- * | | (_) | | / _|
- * __| |_ _ _ __ ___ _ __ ___ _ __ _ _ __ | |_ ___ _ __| |_ __ _ ___ ___
- * / _` | | | | '_ ` _ \| '_ \ / _ \ '__| | | '_ \| __/ _ \ '__| _/ _` |/ __/ _ \
- * | (_| | |_| | | | | | | |_) | __/ | | | | | | || __/ | | || (_| | (_| __/
- * \__,_|\__,_|_| |_| |_| .__/ \___|_| |_|_| |_|\__\___|_| |_| \__,_|\___\___|
- * | |
- * |_|
- ***********************************************************************************/
-
-/**
- * Dumper interface for dumping mips nodes in vcg.
- * @param F the output file
- * @param n the node to dump
- * @param reason indicates which kind of information should be dumped
- */
-static void mips_dump_node(FILE *F, ir_node *n, dump_reason_t reason)
-{
- switch (reason) {
- case dump_node_opcode_txt:
- fprintf(F, "%s", get_irn_opname(n));
- break;
-
- case dump_node_mode_txt:
- break;
-
- case dump_node_nodeattr_txt:
-
- if (is_mips_Immediate(n)) {
- const mips_immediate_attr_t *attr
- = get_mips_immediate_attr_const(n);
- switch (attr->imm_type) {
- case MIPS_IMM_CONST:
- fprintf(F, " %ld ", attr->val);
- break;
- case MIPS_IMM_SYMCONST_LO:
- fprintf(F, " lo(%s", get_entity_ld_name(attr->entity));
- if (attr->val != 0) {
- fprintf(F, "%+ld", attr->val);
- }
- fprintf(F, ") ");
- break;
- case MIPS_IMM_SYMCONST_HI:
- fprintf(F, " hi(%s", get_entity_ld_name(attr->entity));
- if (attr->val != 0) {
- fprintf(F, "%+ld", attr->val);
- }
- fprintf(F, ") ");
- break;
- default:
- fprintf(F, " INVALID ");
- break;
- }
- }
- break;
-
- case dump_node_info_txt:
- arch_dump_reqs_and_registers(F, n);
- break;
- }
-}
-
-
-
-/***************************************************************************************************
- * _ _ _ __ _ _ _ _
- * | | | | | | / / | | | | | | | |
- * __ _| |_| |_ _ __ ___ ___| |_ / /_ _ ___| |_ _ __ ___ ___| |_| |__ ___ __| |___
- * / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
- * | (_| | |_| |_| | \__ \ __/ |_ / / (_| | __/ |_ | | | | | | __/ |_| | | | (_) | (_| \__ \
- * \__,_|\__|\__|_| |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
- * __/ |
- * |___/
- ***************************************************************************************************/
-
-mips_attr_t *get_mips_attr(ir_node *node)
-{
- assert(is_mips_irn(node) && "need mips node to get attributes");
- return (mips_attr_t *) get_irn_generic_attr(node);
-}
-
-const mips_attr_t *get_mips_attr_const(const ir_node *node)
-{
- assert(is_mips_irn(node) && "need mips node to get attributes");
- return get_irn_generic_attr_const(node);
-}
-
-const mips_immediate_attr_t *get_mips_immediate_attr_const(const ir_node *node)
-{
- assert(is_mips_irn(node) && "need mips node to get attributes");
- return get_irn_generic_attr_const(node);
-}
-
-const mips_load_store_attr_t *get_mips_load_store_attr_const(
- const ir_node *node)
-{
- assert(is_mips_irn(node) && "need mips node to get attributes");
- return get_irn_generic_attr_const(node);
-}
-
-/**
- * Returns the argument register requirements of a mips node.
- */
-const arch_register_req_t **get_mips_in_req_all(const ir_node *node)
-{
- const mips_attr_t *attr = get_mips_attr_const(node);
- return attr->in_req;
-}
-
-/**
- * Returns the argument register requirement at position pos of an mips node.
- */
-const arch_register_req_t *get_mips_in_req(const ir_node *node, int pos)
-{
- const mips_attr_t *attr = get_mips_attr_const(node);
- return attr->in_req[pos];
-}
-
-/**
- * Sets the IN register requirements at position pos.
- */
-void set_mips_req_in(ir_node *node, const arch_register_req_t *req, int pos)
-{
- mips_attr_t *attr = get_mips_attr(node);
- attr->in_req[pos] = req;
-}
-
-/**
- * Initializes the nodes attributes.
- */
-static void init_mips_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);
- mips_attr_t *attr = get_mips_attr(node);
- backend_info_t *info;
- (void) execution_units;
-
- arch_irn_set_flags(node, flags);
- attr->in_req = in_reqs;
-
- info = be_get_info(node);
- info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
- memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
-}
-
-static void init_mips_immediate_attributes(ir_node *node,
- mips_immediate_type_t type,
- ir_entity *entity, long val)
-{
- mips_immediate_attr_t *attr = get_irn_generic_attr(node);
-
- attr->imm_type = type;
- attr->entity = entity;
- attr->val = val;
-}
-
-static void init_mips_load_store_attributes(ir_node *node, ir_entity *entity,
- long offset)
-{
- mips_load_store_attr_t *attr = get_irn_generic_attr(node);
- attr->stack_entity = entity;
- attr->offset = offset;
-}
-
-static int mips_compare_nodes_attr(ir_node *node_a, ir_node *node_b)
-{
- const mips_attr_t *a = get_mips_attr_const(node_a);
- const mips_attr_t *b = get_mips_attr_const(node_b);
-
- if (a->switch_default_pn != b->switch_default_pn)
- return 1;
-
- return 0;
-}
-
-static int mips_compare_immediate_attr(ir_node *node_a, ir_node *node_b)
-{
- const mips_immediate_attr_t *a = get_mips_immediate_attr_const(node_a);
- const mips_immediate_attr_t *b = get_mips_immediate_attr_const(node_b);
-
- if (a->val != b->val)
- return 1;
-
- return 0;
-}
-
-static int mips_compare_load_store_attr(ir_node *node_a, ir_node *node_b)
-{
- const mips_load_store_attr_t *a = get_mips_load_store_attr_const(node_a);
- const mips_load_store_attr_t *b = get_mips_load_store_attr_const(node_b);
-
- if (mips_compare_nodes_attr(node_a, node_b))
- return 1;
- if (a->stack_entity != b->stack_entity)
- return 1;
- if (a->offset != b->offset)
- return 1;
-
- return 0;
-}
-
-static void mips_copy_attr(ir_graph *irg, const ir_node *old_node,
- ir_node *new_node)
-{
- struct obstack *obst = get_irg_obstack(irg);
- const mips_attr_t *attr_old = get_mips_attr_const(old_node);
- mips_attr_t *attr_new = get_mips_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);
-}
-
-/***************************************************************************************
- * _ _ _
- * | | | | | |
- * _ __ ___ __| | ___ ___ ___ _ __ ___| |_ _ __ _ _ ___| |_ ___ _ __ ___
- * | '_ \ / _ \ / _` |/ _ \ / __/ _ \| '_ \/ __| __| '__| | | |/ __| __/ _ \| '__/ __|
- * | | | | (_) | (_| | __/ | (_| (_) | | | \__ \ |_| | | |_| | (__| || (_) | | \__ \
- * |_| |_|\___/ \__,_|\___| \___\___/|_| |_|___/\__|_| \__,_|\___|\__\___/|_| |___/
- *
- ***************************************************************************************/
-
-/* Include the generated constructor functions */
-#include "gen_mips_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.
- * @author Matthias Braun, Mehdi
- * @version $Id$
- */
-#ifndef FIRM_BE_MIPS_MIPS_NEW_NODES_H
-#define FIRM_BE_MIPS_MIPS_NEW_NODES_H
-
-#include "mips_nodes_attr.h"
-
-/***************************************************************************************************
- * _ _ _ __ _ _ _ _
- * | | | | | | / / | | | | | | | |
- * __ _| |_| |_ _ __ ___ ___| |_ / /_ _ ___| |_ _ __ ___ ___| |_| |__ ___ __| |___
- * / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
- * | (_| | |_| |_| | \__ \ __/ |_ / / (_| | __/ |_ | | | | | | __/ |_| | | | (_) | (_| \__ \
- * \__,_|\__|\__|_| |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
- * __/ |
- * |___/
- ***************************************************************************************************/
-
-/**
- * Returns the attributes of an mips node.
- */
-mips_attr_t *get_mips_attr(ir_node *node);
-const mips_attr_t *get_mips_attr_const(const ir_node *node);
-const mips_immediate_attr_t *get_mips_immediate_attr_const(const ir_node *node);
-const mips_load_store_attr_t *get_mips_load_store_attr_const(
- const ir_node *node);
-
-/**
- * Returns the argument register requirements of an mips node.
- */
-const arch_register_req_t **get_mips_in_req_all(const ir_node *node);
-
-/**
- * Returns the argument register requirements of an mips node.
- */
-const arch_register_req_t *get_mips_in_req(const ir_node *node, int pos);
-
-/**
- * Sets the OUT register requirements at position pos.
- */
-void set_mips_req_out(ir_node *node, const arch_register_req_t *req, int pos);
-
-/**
- * Sets the IN register requirements at position pos.
- */
-void set_mips_req_in(ir_node *node, const arch_register_req_t *req, int pos);
-
-/* Include the generated headers */
-#include "gen_mips_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 declaration of attributes for mips nodes
- * @author Matthias Braun
- * @version $Id$
- */
-#ifndef FIRM_BE_MIPS_MIPS_NODES_ATTR_H
-#define FIRM_BE_MIPS_MIPS_NODES_ATTR_H
-
-#include "../bearch.h"
-#include "irmode_t.h"
-#include "irnode_t.h"
-
-typedef struct mips_attr_t {
- except_attr exc; /**< the exception attribute. MUST be the first one. */
-
- int switch_default_pn; /**< proj number of default case in switch */
-
- const arch_register_req_t **in_req; /**< register requirements for arguments */
-} mips_attr_t;
-
-typedef enum mips_immediate_type_t {
- MIPS_IMM_CONST,
- MIPS_IMM_SYMCONST_LO,
- MIPS_IMM_SYMCONST_HI
-} mips_immediate_type_t;
-
-typedef struct mips_immediate_attr_t {
- mips_attr_t attr;
- mips_immediate_type_t imm_type;
- ir_entity *entity;
- long val;
-} mips_immediate_attr_t;
-
-typedef struct mips_load_store_attr_t {
- mips_attr_t attr;
- ir_entity *stack_entity;
- long offset;
-} mips_load_store_attr_t;
-
-#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 Mips implementation of list scheduler selector
- * @author Matthias Braun, Mehdi
- * @version $Id$
- */
-#include "config.h"
-
-#include "mips_scheduler.h"
-
-#include "../besched.h"
-#include "be.h"
-#include "../beabi.h"
-#include "../belistsched.h"
-#include "iredges.h"
-#include "ircons.h"
-#include "gen_mips_regalloc_if.h"
-
-#include "mips_new_nodes.h"
-
-list_sched_selector_t mips_sched_selector;
-
-typedef struct {
- pset *div_set;
- /**
- * This array holds an entry for each register that specifies how much cycles
- * have to pass before we can access that register again
- * (because mips will write the register value back in the WB phase of the pipeline)
- */
- int busy_registers[N_mips_gp_REGS];
- /// current block
- ir_node* block;
- ir_node* last_nop;
-} mips_sched_env_t;
-
-/* Matze: deprecated and totally broken */
-#if 0
-
-static void *mips_scheduler_init_graph(const list_sched_selector_t *vtab, ir_graph *irg)
-{
- mips_sched_env_t *sched_env = XMALLOCZ(mips_sched_env_t);
-
- sched_env->div_set = new_pset(pset_default_ptr_cmp, 4);
-
- return sched_env;
-}
-
-static void mips_scheduler_finish_graph(void* graph_env)
-{
- mips_sched_env_t *sched_env = (mips_sched_env_t*) graph_env;
- del_pset(sched_env->div_set);
-}
-
-static void *mips_scheduler_init_block(void *graph_env, ir_node *block)
-{
- mips_sched_env_t *sched_env = (mips_sched_env_t*) graph_env;
- assert(pset_count(sched_env->div_set) == 0);
- srand(12234);
- // TODO later we might have blocks that don't end in a jump
- memset(&sched_env->busy_registers, 0, sizeof(sched_env->busy_registers));
- sched_env->block = block;
- sched_env->last_nop = NULL;
- return sched_env;
-}
-
-static void mips_scheduler_finish_block(void* graph_env)
-{
- mips_sched_env_t *sched_env = (mips_sched_env_t*) graph_env;
- // attach last nop to end node (so that firm doesn't discard it)
- if (sched_env->last_nop != NULL) {
- ir_node* end = get_irg_end(get_irn_irg(sched_env->block));
- (void) end;
- // TODO
- }
- sched_env->block = NULL;
-}
-
-static int mips_scheduler_to_appear_in_schedule(void *block_env, const ir_node *irn)
-{
- return is_mips_irn(irn) && !is_mips_zero(irn) && !is_mips_reinterpret_conv(irn) && !is_mips_fallthrough(irn);
-}
-
-static void mips_collect_mflohis(pset* set, ir_node* node)
-{
- // construct a list of nodes that need to be scheduled before
- // we are allowed to schedule another div or mul instruction
- const ir_edge_t *edge, *edge2;
-
- if (is_mips_div(node)) {
- foreach_out_edge(node, edge) {
- const ir_node* node2 = get_edge_src_irn(edge);
-
- assert(is_Proj(node2));
- foreach_out_edge(node2, edge2) {
- const ir_node* node3 = get_edge_src_irn(edge2);
- if (is_mips_mfhi(node3) || is_mips_mflo(node3))
- pset_insert_ptr(set, node3);
- }
- }
- } else if (is_mips_mult(node)) {
- foreach_out_edge(node, edge) {
- const ir_node* node2 = get_edge_src_irn(edge);
-
- if (is_mips_mfhi(node2) || is_mips_mflo(node2))
- pset_insert_ptr(set, node2);
- }
- }
-}
-
-static int mips_scheduler_node_allowed(mips_sched_env_t *sched_env, ir_node* node)
-{
- if (pset_count(sched_env->div_set) != 0 && (is_mips_div(node) || is_mips_mult(node))) {
- return 0;
- }
-
- return 1;
-}
-
-static ir_node *mips_scheduler_select(void *block_env, nodeset *ready_set, nodeset *live_set)
-{
- mips_sched_env_t *sched_env = (mips_sched_env_t*) block_env;
- ir_node *node = NULL;
- ir_node *block = sched_env->block;
- ir_node *condjmp = NULL;
- ir_graph *irg = get_irn_irg(block);
- int have_non_branch_nodes = 0;
-
- // test all nodes in the ready set and take the first non-branch that
- // is allowed
- for (node = nodeset_first(ready_set); node != NULL; node = nodeset_next(ready_set)) {
- if (arch_irn_class_is(node, branch)) {
- if (is_irn_forking(node))
- condjmp = node;
- continue;
- }
-
- have_non_branch_nodes = 1;
-
- if (mips_scheduler_node_allowed(sched_env, node))
- {
- nodeset_break(ready_set);
-
- // TODO update busy_registers
-
- if (is_mips_div(node) || is_mips_mult(node)) {
- mips_collect_mflohis(sched_env->div_set, node);
- } else if (is_mips_mflo(node) || is_mips_mfhi(node)) {
- pset_remove_ptr(sched_env->div_set, node);
- }
-
- return node;
- }
- }
-
- // if we arrive here no non-branch node was found that we can emit
-
- // return a branch if there are just branches left
- if (!have_non_branch_nodes) {
- // schedule conditional branches before non-conditional ones
- if (condjmp != NULL) {
- return condjmp;
- }
- node = nodeset_first(ready_set);
- assert(arch_irn_class_is(node, branch));
- nodeset_break(ready_set);
- return node;
- }
-
- // emit a nop
- node = new_rd_mips_nop(NULL, irg, block, mode_M);
- keep_alive(node);
- return node;
-}
-
-#endif
-
-static int mips_to_appear_in_schedule(void *block_env, const ir_node *node)
-{
- (void) block_env;
-
- if (!is_mips_irn(node))
- return -1;
- if (is_mips_zero(node) || is_mips_Immediate(node))
- return 0;
-
- return 1;
-}
-
-list_sched_selector_t mips_selector;
-
-/**
- * Returns the reg_pressure scheduler with to_appear_in_schedule() overloaded
- */
-const list_sched_selector_t *mips_get_list_sched_selector(const void *self,
- list_sched_selector_t *selector)
-{
- (void) self;
-#if 0
- memset(&mips_sched_selector, 0, sizeof(mips_sched_selector));
- mips_sched_selector.init_graph = mips_scheduler_init_graph;
- mips_sched_selector.init_block = mips_scheduler_init_block;
- mips_sched_selector.select = mips_scheduler_select;
- mips_sched_selector.to_appear_in_schedule = mips_scheduler_to_appear_in_schedule;
- mips_sched_selector.finish_block = mips_scheduler_finish_block;
- mips_sched_selector.finish_graph = mips_scheduler_finish_graph;
- //return &mips_sched_selector;
-#endif
- memcpy(&mips_selector, selector, sizeof(mips_selector));
- mips_selector.to_appear_in_schedule = mips_to_appear_in_schedule;
-
- return &mips_selector;
-}
-
-const ilp_sched_selector_t *mips_get_ilp_sched_selector(const void *self)
-{
- (void) self;
- return NULL;
-}
+++ /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 mips scheduler
- * @author Matthias Braun, Mehdi
- * @version $Id$
- */
-#ifndef FIRM_BE_MIPS_MIPS_SCHEDULER_H
-#define FIRM_BE_MIPS_MIPS_SCHEDULER_H
-
-#include "../besched.h"
-
-const list_sched_selector_t *mips_get_list_sched_selector(const void *self, list_sched_selector_t *selector);
-const ilp_sched_selector_t *mips_get_ilp_sched_selector(const void *self);
-
-#endif
+++ /dev/null
-# Creation: 2006/02/13
-# $Id$
-
-# the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
-
-$arch = "mips";
-
-# register types:
-# 0 - no special type
-# 1 - caller save (register must be saved by the caller of a function)
-# 2 - callee save (register must be saved by the called function)
-# 4 - ignore (do not assign this register)
-# NOTE: Last entry of each class is the largest Firm-Mode a register can hold\
-%reg_classes = (
- "gp" => [
- { name => "zero", type => 4 }, # always zero
- { name => "at", type => 4 }, # reserved for assembler
- { name => "v0", realname => "2", type => 1 }, # first return value
- { name => "v1", realname => "3", type => 1 }, # second return value
- { name => "a0", realname => "4", type => 1 }, # first argument
- { name => "a1", realname => "5", type => 1 }, # second argument
- { name => "a2", realname => "6", type => 1 }, # third argument
- { name => "a3", realname => "7", type => 1 }, # fourth argument
- { name => "t0", realname => "8", type => 1 },
- { name => "t1", realname => "9", type => 1 },
- { name => "t2", realname => "10", type => 1 },
- { name => "t3", realname => "11", type => 1 },
- { name => "t4", realname => "12", type => 1 },
- { name => "t5", realname => "13", type => 1 },
- { name => "t6", realname => "14", type => 1 },
- { name => "t7", realname => "15", type => 1 },
- { name => "s0", realname => "16", type => 2 },
- { name => "s1", realname => "17", type => 2 },
- { name => "s2", realname => "18", type => 2 },
- { name => "s3", realname => "19", type => 2 },
- { name => "s4", realname => "20", type => 2 },
- { name => "s5", realname => "21", type => 2 },
- { name => "s6", realname => "22", type => 2 },
- { name => "s7", realname => "23", type => 2 },
- { name => "t8", realname => "24", type => 1 },
- { name => "t9", realname => "25", type => 1 },
- { name => "kt0", type => 4 }, # reserved for OS
- { name => "kt1", type => 4 }, # reserved for OS
- { name => "gp", type => 4 }, # general purpose
- { name => "sp", type => 4 }, # stack pointer
- { name => "fp", type => 4 }, # frame pointer
- { name => "ra", type => 2+1 }, # return address
- { name => "gp_NOREG", realname => "!NOREG_INVALID!", type => 4 | 8 | 16 }, #dummy register for immediate nodes
- { mode => "mode_Iu" }
- ],
-); # %reg_classes
-
-%emit_templates = (
- S0 => "${arch}_emit_source_register(node, 0);",
- S1 => "${arch}_emit_source_register(node, 1);",
- SI1 => "${arch}_emit_source_register_or_immediate(node, 1);",
- D0 => "${arch}_emit_dest_register(node, 0);",
- A0 => "${arch}_emit_load_store_address(node, 0);",
- I => "${arch}_emit_immediate_suffix(node, 1);",
- C => "${arch}_emit_immediate(node);",
- JumpTarget => "${arch}_emit_jump_target(node);",
- JumpTarget1 => "${arch}_emit_jump_target_proj(node, 1);",
- JumpOrFallthrough => "${arch}_emit_jump_or_fallthrough(node, 0);",
-);
-
-$default_attr_type = "mips_attr_t";
-$default_copy_attr = "mips_copy_attr";
-
-$mode_gp = "mode_Iu";
-
-%init_attr = (
- mips_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, exec_units, n_res);",
-
- mips_immediate_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, exec_units, n_res);\n".
- "\tinit_mips_immediate_attributes(res, imm_type, entity, val);",
-
- mips_load_store_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, exec_units, n_res);\n".
- "\tinit_mips_load_store_attributes(res, entity, offset);",
-);
-
-%compare_attr = (
- mips_attr_t => "mips_compare_nodes_attr",
- mips_immediate_attr_t => "mips_compare_immediate_attr",
- mips_load_store_attr_t => "mips_compare_load_store_attr",
-);
-
-#--------------------------------------------------#
-# _ #
-# (_) #
-# _ __ _____ __ _ _ __ ___ _ __ ___ #
-# | '_ \ / _ \ \ /\ / / | | '__| / _ \| '_ \/ __| #
-# | | | | __/\ V V / | | | | (_) | |_) \__ \ #
-# |_| |_|\___| \_/\_/ |_|_| \___/| .__/|___/ #
-# | | #
-# |_| #
-#--------------------------------------------------#
-
-%nodes = (
-
-Immediate => {
- state => "pinned",
- op_flags => "c",
- reg_req => { out => [ "gp_NOREG:I" ] },
- attr => "mips_immediate_type_t imm_type, ir_entity *entity, long val",
- attr_type => "mips_immediate_attr_t",
- mode => $mode_gp,
-},
-
-#-----------------------------------------------------------------#
-# _ _ _ #
-# (_) | | | | #
-# _ _ __ | |_ ___ __ _ ___ _ __ _ __ ___ __| | ___ ___ #
-# | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
-# | | | | | || __/ (_| | __/ | | | | | (_) | (_| | __/\__ \ #
-# |_|_| |_|\__\___|\__, |\___|_| |_| |_|\___/ \__,_|\___||___/ #
-# __/ | #
-# |___/ #
-#-----------------------------------------------------------------#
-
-# commutative operations
-
-addu => {
- op_flags => "R",
- reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
- ins => [ "left", "right" ],
- emit => '. add%I%.u %D0, %S0, %SI1',
- mode => $mode_gp,
-},
-
-and => {
- op_flags => "R",
- reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
- ins => [ "left", "right" ],
- emit => '. and%I %D0, %S0, %SI1',
- mode => $mode_gp,
-},
-
-div => {
- reg_req => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
- ins => [ "left", "right" ],
- outs => [ "lohi", "M" ],
- emit => '. div %S0, %S1',
- mode => "mode_M",
-},
-
-divu => {
- reg_req => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
- ins => [ "left", "right" ],
- outs => [ "lohi", "M" ],
- emit => '. divu %S0, %S1',
- mode => "mode_M",
-},
-
-mult => {
- reg_req => { in => [ "gp", "gp" ], out => [ "none" ] },
- ins => [ "left", "right" ],
- emit => '. mult %S0, %S1',
- mode => "mode_M"
-},
-
-multu => {
- reg_req => { in => [ "gp", "gp" ], out => [ "none" ] },
- ins => [ "left", "right" ],
- emit => '. multu %S0, %S1',
- mode => "mode_M",
-},
-
-nor => {
- op_flags => "R",
- reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
- emit => '. nor%I %D0, %S0, %SI1',
- mode => $mode_gp
-},
-
-or => {
- op_flags => "R",
- reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
- ins => [ "left", "right" ],
- emit => '. or%I %D0, %S0, %SI1',
- mode => $mode_gp
-},
-
-sll => {
- op_flags => "R",
- reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
- ins => [ "left", "right" ],
- emit => '. sll %D0, %S0, %SI1',
- mode => $mode_gp,
-},
-
-sra => {
- op_flags => "R",
- reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
- ins => [ "left", "right" ],
- emit => '. sra %D0, %S0, %SI1',
- mode => $mode_gp
-},
-
-srl => {
- op_flags => "R",
- reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
- ins => [ "left", "right" ],
- emit => '. srl %D0, %S0, %SI1',
- mode => $mode_gp,
-},
-
-subu => {
- op_flags => "R",
- reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
- ins => [ "left", "right" ],
- emit => '. subu %D0, %S0, %S1',
- mode => $mode_gp
-},
-
-xor => {
- op_flags => "R",
- reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
- ins => [ "left", "right" ],
- emit => '. xor%I %D0, %S0, %SI1',
- mode => $mode_gp,
-},
-
-seb => {
- op_flags => "R",
- reg_req => { in => [ "gp" ], out => [ "gp" ] },
- ins => [ "val" ],
- emit => '.seb %D0, %S0',
- mode => $mode_gp,
-},
-
-seh => {
- op_flags => "R",
- reg_req => { in => [ "gp" ], out => [ "gp" ] },
- ins => [ "val" ],
- emit => '.seh %D0, %S0',
- mode => $mode_gp,
-},
-
-lui => {
- op_flags => "c",
- irn_flags => "R",
- reg_req => { out => [ "gp" ] },
- emit => '.lui %D0, %C',
- attr_type => "mips_immediate_attr_t",
- attr => "mips_immediate_type_t imm_type, ir_entity *entity, long val",
- mode => $mode_gp,
-},
-
-mflo => {
- irn_flags => "R",
- reg_req => { in => [ "none" ], out => [ "gp" ] },
- ins => [ "lohi" ],
- emit => '. mflo %D0',
- mode => $mode_gp
-},
-
-mfhi => {
- irn_flags => "R",
- reg_req => { in => [ "none" ], out => [ "gp" ] },
- ins => [ "lohi" ],
- emit => '. mfhi %D0',
- mode => $mode_gp
-},
-
-zero => {
- state => "pinned",
- op_flags => "c",
- reg_req => { out => [ "zero:I" ] },
- emit => '',
- mode => $mode_gp
-},
-
-#
-# ____ _ __ _
-# | __ ) _ __ __ _ _ __ ___| |__ / / | |_ _ _ __ ___ _ __
-# | _ \| '__/ _` | '_ \ / __| '_ \ / / | | | | | '_ ` _ \| '_ \
-# | |_) | | | (_| | | | | (__| | | |/ / |_| | |_| | | | | | | |_) |
-# |____/|_| \__,_|_| |_|\___|_| |_/_/ \___/ \__,_|_| |_| |_| .__/
-# |_|
-#
-
-slt => {
- op_flags => "R",
- reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
- emit => '. slt%I %D0, %S0, %SI1',
- mode => $mode_gp,
-},
-
-sltu => {
- op_flags => "R",
- reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
- emit => '. slt%I%.u %D0, %S0, %SI1',
- mode => $mode_gp,
-},
-
-beq => {
- op_flags => "X|Y",
- reg_req => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
- outs => [ "false", "true" ],
- emit => '. beq %S0, %S1, %JumpTarget1
- . %JumpOrFallthrough'
-},
-
-bne => {
- op_flags => "X|Y",
- reg_req => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
- outs => [ "false", "true" ],
- emit => '. bne %S0, %S1, %JumpTarget1
- . %JumpOrFallthrough'
-},
-
-bgtz => {
- op_flags => "X|Y",
- reg_req => { in => [ "gp" ], out => [ "none", "none" ] },
- outs => [ "false", "true" ],
- emit => '. bgtz %S0, %JumpTarget1
- . %JumpOrFallthrough'
-},
-
-blez => {
- op_flags => "X|Y",
- reg_req => { in => [ "gp" ], out => [ "none", "none" ] },
- outs => [ "false", "true" ],
- emit => '. blez %S0, %JumpTarget1
- . %JumpOrFallthrough'
-},
-
-b => {
- op_flags => "X",
- reg_req => { in => [ ], out => [ "none" ] },
- emit => '. b %JumpTarget',
- mode => 'mode_X'
-},
-
-jr => {
- op_flags => "X",
- reg_req => { in => [ "gp" ], out => [ "none" ] },
- emit => '. jr %S0',
- mode => 'mode_X'
-},
-
-SwitchJump => {
- op_flags => "X",
- reg_req => { in => [ "gp" ], out => [ "none" ] },
- emit => '. jr %S0'
-},
-
-# _ _ ______ _
-# | | ___ __ _ __| | / / ___|| |_ ___ _ __ ___
-# | | / _ \ / _` |/ _` | / /\___ \| __/ _ \| '__/ _ \
-# | |__| (_) | (_| | (_| |/ / ___) | || (_) | | | __/
-# |_____\___/ \__,_|\__,_/_/ |____/ \__\___/|_| \___|
-#
-
-lw => {
- op_flags => "L|F",
- state => "exc_pinned",
- reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
- ins => [ "ptr", "mem" ],
- outs => [ "res", "M" ],
- emit => '. lw %D0, %A0',
- attr_type => "mips_load_store_attr_t",
- attr => "ir_entity *entity, long offset",
-},
-
-lh => {
- op_flags => "L|F",
- state => "exc_pinned",
- reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
- ins => [ "ptr", "mem" ],
- outs => [ "res", "M" ],
- emit => '. lh %D0, %A0',
- attr_type => "mips_load_store_attr_t",
- attr => "ir_entity *entity, long offset",
-},
-
-lhu => {
- op_flags => "L|F",
- state => "exc_pinned",
- reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
- ins => [ "ptr", "mem" ],
- outs => [ "res", "M" ],
- emit => '. lhu %D0, %A0',
- attr_type => "mips_load_store_attr_t",
- attr => "ir_entity *entity, long offset",
-},
-
-lb => {
- op_flags => "L|F",
- state => "exc_pinned",
- reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
- ins => [ "ptr", "mem" ],
- outs => [ "res", "M" ],
- emit => '. lb %D0, %A0',
- attr_type => "mips_load_store_attr_t",
- attr => "ir_entity *entity, long offset",
-},
-
-lbu => {
- op_flags => "L|F",
- state => "exc_pinned",
- reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
- ins => [ "ptr", "mem" ],
- outs => [ "res", "M" ],
- emit => '. lbu %D0, %A0',
- attr_type => "mips_load_store_attr_t",
- attr => "ir_entity *entity, long offset",
-},
-
-sw => {
- op_flags => "L|F",
- state => "exc_pinned",
- reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
- ins => [ "ptr", "val", "mem" ],
- emit => '. sw %S1, %A0',
- mode => 'mode_M',
- attr_type => "mips_load_store_attr_t",
- attr => "ir_entity *entity, long offset",
-},
-
-sh => {
- op_flags => "L|F",
- state => "exc_pinned",
- reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
- ins => [ "ptr", "val", "mem" ],
- emit => '. sh %S1, %A0',
- mode => 'mode_M',
- attr_type => "mips_load_store_attr_t",
- attr => "ir_entity *entity, long offset",
-},
-
-sb => {
- op_flags => "L|F",
- state => "exc_pinned",
- reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
- ins => [ "ptr", "val", "mem" ],
- emit => '. sb %S1, %A0',
- mode => 'mode_M',
- attr_type => "mips_load_store_attr_t",
- attr => "ir_entity *entity, long offset",
-},
-
-#
-# Miscelaneous
-#
-
-nop => {
- op_flags => "K",
- reg_req => { in => [], out => [ "none" ] },
- emit => '. nop',
-},
-
-); # 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 The codegenrator (transform FIRM into mips FIRM
- * @author Matthias Braun, Mehdi
- * @version $Id$
- */
-#include "config.h"
-
-#include <limits.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 "irop.h"
-#include "iropt_t.h"
-#include "debug.h"
-#include "error.h"
-
-#include "../benode.h"
-#include "../beabi.h"
-#include "../besched.h"
-#include "../besched.h"
-#include "../beirg.h"
-#include "../betranshlp.h"
-#include "bearch_mips_t.h"
-
-#include "mips_nodes_attr.h"
-#include "mips_transform.h"
-#include "mips_new_nodes.h"
-#include "mips_map_regs.h"
-#include "mips_util.h"
-#include "mips_emitter.h"
-
-#include "gen_mips_regalloc_if.h"
-
-/****************************************************************************************************
- * _ _ __ _ _
- * | | | | / _| | | (_)
- * _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __
- * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
- * | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | |
- * |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
- *
- ****************************************************************************************************/
-
-typedef ir_node *construct_binop_func(dbg_info *db, ir_node *block,
- ir_node *left, ir_node *right);
-
-static inline int mode_needs_gp_reg(ir_mode *mode)
-{
- return mode_is_int(mode) || mode_is_reference(mode);
-}
-
-ir_node *mips_create_Immediate(long val)
-{
- ir_graph *irg = current_ir_graph;
- ir_node *block = get_irg_start_block(irg);
- ir_node *res;
-
- assert(val >= -32768 && val <= 32767);
- res = new_bd_mips_Immediate(NULL, block, MIPS_IMM_CONST, NULL, val);
- arch_set_irn_register(res, &mips_gp_regs[REG_GP_NOREG]);
-
- return res;
-}
-
-ir_node* mips_create_zero(void)
-{
- ir_graph *irg = current_ir_graph;
- ir_node *block = get_irg_start_block(irg);
- ir_node *zero = new_bd_mips_zero(NULL, block);
-
- arch_set_irn_register(zero, &mips_gp_regs[REG_GP_NOREG]);
-
- return zero;
-}
-
-static ir_node *try_create_Immediate(ir_node *node)
-{
- tarval *tv;
- long val;
- ir_mode *mode;
-
- if (!is_Const(node))
- return NULL;
-
- mode = get_irn_mode(node);
- if (!mode_needs_gp_reg(mode))
- return NULL;
-
- tv = get_Const_tarval(node);
- if (tarval_is_long(tv)) {
- val = get_tarval_long(tv);
- } else {
- ir_fprintf(stderr, "Optimisation Warning: tarval %+F is not a long?\n",
- node);
- return NULL;
- }
-
- if (val < -32768 || val > 32767)
- return NULL;
-
- return mips_create_Immediate(val);
-}
-
-static void create_binop_operands(ir_node **new_left, ir_node **new_right,
- ir_node *left, ir_node *right,
- int is_commutative)
-{
- *new_right = try_create_Immediate(right);
- if (*new_right != NULL) {
- *new_left = be_transform_node(left);
- return;
- }
- if (is_commutative) {
- *new_right = try_create_Immediate(left);
- if (*new_right != NULL) {
- *new_left = be_transform_node(right);
- return;
- }
- }
-
- *new_left = be_transform_node(left);
- *new_right = be_transform_node(right);
-}
-
-static ir_node *gen_binop(ir_node *node, ir_node *left, ir_node *right,
- construct_binop_func func, int supports_immediate)
-{
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *res;
- ir_node *new_left, *new_right;
-
- assert(mode_needs_gp_reg(get_irn_mode(node)));
-
- if (supports_immediate) {
- int is_commutative = is_op_commutative(get_irn_op(node));
- create_binop_operands(&new_left, &new_right, left, right,
- is_commutative);
- } else {
- new_left = be_transform_node(left);
- new_right = be_transform_node(right);
- }
-
- res = func(dbgi, block, new_left, new_right);
-
- return res;
-}
-
-static ir_node *gen_Add(ir_node *node)
-{
- /* TODO: match add(symconst, const) */
- return gen_binop(node, get_Add_left(node), get_Add_right(node),
- new_bd_mips_addu, 1);
-}
-
-static ir_node *gen_Sub(ir_node *node)
-{
- return gen_binop(node, get_Sub_left(node), get_Sub_right(node),
- new_bd_mips_addu, 0);
-}
-
-static ir_node *gen_And(ir_node *node)
-{
- return gen_binop(node, get_Add_left(node), get_Add_right(node),
- new_bd_mips_and, 1);
-}
-
-static ir_node *gen_Or(ir_node *node)
-{
- return gen_binop(node, get_Add_left(node), get_Add_right(node),
- new_bd_mips_or, 1);
-}
-
-static ir_node *gen_Eor(ir_node *node)
-{
- return gen_binop(node, get_Add_left(node), get_Add_right(node),
- new_bd_mips_xor, 1);
-}
-
-static ir_node *gen_Shl(ir_node *node)
-{
- return gen_binop(node, get_Add_left(node), get_Add_right(node),
- new_bd_mips_sll, 1);
-}
-
-static ir_node *gen_Shr(ir_node *node)
-{
- return gen_binop(node, get_Add_left(node), get_Add_right(node),
- new_bd_mips_srl, 1);
-}
-
-static ir_node *gen_Shrs(ir_node *node)
-{
- return gen_binop(node, get_Add_left(node), get_Add_right(node),
- new_bd_mips_sra, 1);
-}
-
-static ir_node *gen_Not(ir_node *node)
-{
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *op = get_Not_op(node);
- ir_node *new_op;
- ir_node *res;
- ir_node *one;
-
- /* we can transform not->or to nor */
- if (is_Or(op)) {
- return gen_binop(op, get_Or_left(op), get_Or_right(op),
- new_bd_mips_nor, 1);
- }
-
- /* construct (op < 1) */
- one = mips_create_Immediate(1);
- new_op = be_transform_node(op);
- res = new_bd_mips_sltu(dbgi, block, new_op, one);
-
- return res;
-}
-
-static ir_node *gen_Minus(ir_node *node)
-{
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *op = get_Minus_op(node);
- ir_node *new_op = be_transform_node(op);
- ir_node *res;
- ir_node *zero;
-
- /* construct (0 - op) */
- zero = mips_create_zero();
- res = new_bd_mips_subu(dbgi, block, zero, new_op);
-
- return res;
-}
-
-static ir_node *gen_Abs(ir_node *node)
-{
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *op = get_Abs_op(node);
- ir_node *new_op = be_transform_node(op);
- ir_node *sra_const, *sra, *add, *xor;
-
- /* TODO: support other bit sizes... */
- assert(get_mode_size_bits(get_irn_mode(node)) == 32);
- sra_const = mips_create_Immediate(31);
- sra = new_bd_mips_sra( dbgi, block, new_op, sra_const);
- add = new_bd_mips_addu(dbgi, block, new_op, sra);
- xor = new_bd_mips_xor( dbgi, block, sra, add);
-
- return xor;
-}
-
-static ir_node* gen_Const(ir_node *node)
-{
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = be_transform_node(get_nodes_block(node));
- tarval *tv = get_Const_tarval(node);
- ir_node *upper_node;
- ir_node *lower_node;
- ir_node *or_const;
- unsigned long val, lower, upper;
-
- if (tarval_is_long(tv)) {
- val = get_tarval_long(tv);
- } else {
- panic("Can't get value of tarval %+F", node);
- }
-
- val = get_tarval_long(tv);
-
- lower = val & 0xffff;
- upper = (val >> 16) & 0xffff;
- if (upper == 0) {
- upper_node = mips_create_zero();
- } else {
- upper_node = new_bd_mips_lui(dbgi, block, MIPS_IMM_CONST, NULL, upper);
- }
-
- if (lower == 0)
- return upper_node;
-
- or_const = mips_create_Immediate(lower);
- lower_node = new_bd_mips_or(dbgi, block, upper_node, or_const);
-
- return lower_node;
-}
-
-static ir_node* gen_SymConst(ir_node *node)
-{
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_entity *entity;
- ir_node *lui, *or_const, *or;
-
- if (get_SymConst_kind(node) != symconst_addr_ent) {
- panic("Only address entity symconsts supported in mips backend");
- }
-
- entity = get_SymConst_entity(node);
-
- lui = new_bd_mips_lui(dbgi, block, MIPS_IMM_SYMCONST_HI, entity, 0);
- or_const = new_bd_mips_Immediate(dbgi, block, MIPS_IMM_SYMCONST_LO, entity, 0);
- or = new_bd_mips_or(dbgi, block, lui, or_const);
-
- arch_set_irn_register(or_const, &mips_gp_regs[REG_GP_NOREG]);
-
- return or;
-}
-
-typedef ir_node* (*gen_load_func)(dbg_info *dbg, ir_node *block, ir_node *ptr,
- ir_node *mem, ir_entity *entity, long offset);
-
-/**
- * Generates a mips node for a firm Load node
- */
-static ir_node *gen_Load(ir_node *node)
-{
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *mem = get_Load_mem(node);
- ir_node *new_mem = be_transform_node(mem);
- ir_node *ptr = get_Load_ptr(node);
- ir_node *new_ptr = be_transform_node(ptr);
- ir_mode *mode = get_Load_mode(node);
- int sign = get_mode_sign(mode);
- ir_node *res;
- gen_load_func func;
-
- ASSERT_NO_FLOAT(mode);
- assert(mode_needs_gp_reg(mode));
-
- /* TODO: make use of offset in ptrs */
-
- switch (get_mode_size_bits(mode)) {
- case 32:
- func = new_bd_mips_lw;
- break;
- case 16:
- func = sign ? new_bd_mips_lh : new_bd_mips_lhu;
- break;
- case 8:
- func = sign ? new_bd_mips_lb : new_bd_mips_lbu;
- break;
- default:
- panic("mips backend only support 32, 16, 8 bit loads");
- }
-
- res = func(dbgi, block, new_ptr, new_mem, NULL, 0);
- set_irn_pinned(res, get_irn_pinned(node));
-
- return res;
-}
-
-typedef ir_node* (*gen_store_func)(dbg_info *dbg, ir_node *block, ir_node *ptr,
- ir_node *val, ir_node *mem, ir_entity *ent, long offset);
-
-/**
- * Generates a mips node for a firm Store node
- */
-static ir_node *gen_Store(ir_node *node)
-{
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *mem = get_Store_mem(node);
- ir_node *new_mem = be_transform_node(mem);
- ir_node *ptr = get_Store_ptr(node);
- ir_node *new_ptr = be_transform_node(ptr);
- ir_node *val = get_Store_value(node);
- ir_node *new_val = be_transform_node(val);
- ir_mode *mode = get_irn_mode(val);
- gen_store_func func;
- ir_node *res;
-
- assert(mode_needs_gp_reg(mode));
-
- switch (get_mode_size_bits(mode)) {
- case 32:
- func = new_bd_mips_sw;
- break;
- case 16:
- func = new_bd_mips_sh;
- break;
- case 8:
- func = new_bd_mips_sb;
- break;
- default:
- panic("store only supported for 32, 16, 8 bit values in mips backend");
- }
-
- res = func(dbgi, block, new_ptr, new_val, new_mem, NULL, 0);
- set_irn_pinned(res, get_irn_pinned(node));
-
- return res;
-}
-
-static ir_node *gen_Proj_DivMod(ir_node *node)
-{
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *divmod = get_Proj_pred(node);
- ir_node *new_div = be_transform_node(divmod);
- long pn = get_Proj_proj(node);
- ir_node *proj;
-
- assert(is_mips_div(new_div) || is_mips_divu(new_div));
-
- switch (get_irn_opcode(divmod)) {
- case iro_Div:
- switch (pn) {
- case pn_Div_M:
- return new_rd_Proj(dbgi, new_div, mode_M, pn_mips_div_M);
- case pn_Div_res:
- proj = new_rd_Proj(dbgi, new_div, mode_M, pn_mips_div_lohi);
- return new_bd_mips_mflo(dbgi, block, proj);
- default:
- break;
- }
- case iro_Mod:
- switch (pn) {
- case pn_Mod_M:
- return new_rd_Proj(dbgi, new_div, mode_M, pn_mips_div_M);
- case pn_Mod_res:
- proj = new_rd_Proj(dbgi, new_div, mode_M, pn_mips_div_lohi);
- return new_bd_mips_mfhi(dbgi, block, proj);
- default:
- break;
- }
-
- case iro_DivMod:
- switch (pn) {
- case pn_Div_M:
- return new_rd_Proj(dbgi, new_div, mode_M, pn_mips_div_M);
- case pn_DivMod_res_div:
- proj = new_rd_Proj(dbgi, new_div, mode_M, pn_mips_div_lohi);
- return new_bd_mips_mflo(dbgi, block, proj);
- case pn_DivMod_res_mod:
- proj = new_rd_Proj(dbgi, new_div, mode_M, pn_mips_div_lohi);
- return new_bd_mips_mfhi(dbgi, block, proj);
- default:
- break;
- }
- default:
- break;
- }
-
- panic("invalid proj attached to %+F", divmod);
-}
-
-static ir_node *gen_Proj_Start(ir_node *node)
-{
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = be_transform_node(get_nodes_block(node));
- long pn = get_Proj_proj(node);
- ir_graph *irg;
-
- if (pn == pn_Start_X_initial_exec) {
- /* we exchange the projx with a jump */
- ir_node *jump = new_rd_Jmp(dbgi, block);
- return jump;
- }
- irg = get_irn_irg(node);
- if (node == get_irg_anchor(irg, anchor_tls)) {
- /* TODO... */
- return be_duplicate_node(node);
- }
- return be_duplicate_node(node);
-}
-
-static ir_node *gen_Proj(ir_node *node)
-{
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *pred = get_Proj_pred(node);
-
- switch (get_irn_opcode(pred)) {
- case iro_Load:
- break;
- case iro_Store:
- break;
- case iro_Div:
- case iro_Mod:
- case iro_DivMod:
- return gen_Proj_DivMod(node);
-
- case iro_Start:
- return gen_Proj_Start(node);
-
- default:
- assert(get_irn_mode(node) != mode_T);
- if (mode_needs_gp_reg(get_irn_mode(node))) {
- ir_node *new_pred = be_transform_node(pred);
- long pn = get_Proj_proj(node);
-
- return new_rd_Proj(dbgi, new_pred, mode_Iu, pn);
- }
- break;
- }
-
- return be_duplicate_node(node);
-}
-
-static ir_node *gen_Phi(ir_node *node)
-{
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_graph *irg = get_Block_irg(block);
- ir_mode *mode = get_irn_mode(node);
- ir_node *phi;
-
- if (mode_needs_gp_reg(mode)) {
- assert(get_mode_size_bits(mode) <= 32);
- mode = mode_Iu;
- }
-
- /* 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(irg, node, phi);
- be_duplicate_deps(node, phi);
-
- be_enqueue_preds(node);
-
- return phi;
-}
-
-#if 0
-static ir_node *gen_node_for_SwitchCond(mips_transform_env_t *env)
-{
- ir_node *selector = get_Cond_selector(env->irn);
- ir_mode *selector_mode = get_irn_mode(selector);
- ir_node *node = env->irn;
- dbg_info *dbg = env->dbg;
- ir_graph *irg = env->irg;
- ir_node *block = env->block;
- ir_node *sub, *sltu, *minval_const, *max_const, *switchjmp;
- ir_node *defaultproj, *defaultproj_succ;
- ir_node *beq, *sl;
- long pn, minval, maxval, defaultprojn;
- const ir_edge_t *edge;
- ir_node *zero, *two_const, *add, *la, *load, *proj;
- ir_mode *unsigned_mode;
- mips_attr_t *attr;
-
- // mode_b conds are handled by gen_node_for_Proj
- if (get_mode_sort(selector_mode) != irms_int_number)
- return env->irn;
-
- assert(get_mode_size_bits(selector_mode) == 32);
-
- defaultproj = NULL;
- defaultprojn = get_Cond_default_proj(node);
-
- // go over all projs to find min-&maxval of the switch
- minval = INT_MAX;
- maxval = INT_MIN;
- foreach_out_edge(node, edge) {
- ir_node* proj = get_edge_src_irn(edge);
- assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
-
- pn = get_Proj_proj(proj);
- if (pn == defaultprojn) {
- defaultproj = proj;
- continue;
- }
-
- if (pn < minval)
- minval = pn;
- if (pn > maxval)
- maxval = pn;
- }
- assert(defaultproj != NULL);
-
- // subtract minval from the switch value
-
- if (minval != 0) {
- minval_const = new_rd_Const(dbg, irg, selector_mode, new_tarval_from_long(minval, selector_mode));
- minval_const = gen_node_for_Const(env, dbg, irg, block, minval_const);
- sub = new_bd_mips_sub(dbg, block, selector, minval_const);
- } else {
- sub = selector;
- }
-
- // compare if we're above maxval-minval or below zero.
- // we can do this with 1 compare because we use unsigned mode
- unsigned_mode = new_ir_mode(get_mode_name(selector_mode),
- get_mode_sort(selector_mode), get_mode_size_bits(selector_mode),
- 0, get_mode_arithmetic(selector_mode), get_mode_modulo_shift(selector_mode));
-
- max_const = new_rd_Const(dbg, irg, unsigned_mode, new_tarval_from_long(maxval - minval + 1, unsigned_mode));
- max_const = gen_node_for_Const(env, dbg, irg, block, max_const);
- sltu = new_bd_mips_slt(dbg, block, sub, max_const);
-
- zero = gen_zero_node(env, dbg, irg, block);
- beq = new_bd_mips_beq(dbg, block, sltu, zero, mode_T);
-
- // attach defaultproj to beq now
- set_irn_n(defaultproj, 0, beq);
- set_Proj_proj(defaultproj, 1);
-
- two_const = new_rd_Const(dbg, irg, block, unsigned_mode, new_tarval_from_long(2, unsigned_mode));
- two_const = gen_node_for_Const(env, dbg, irg, block, two_const);
- sl = new_bd_mips_sl(dbg, block, sub, two_const);
-
- la = new_bd_mips_la( dbg, block);
- add = new_bd_mips_addu( dbg, block, sl, la);
- load = new_bd_mips_load_r(dbg, block, new_NoMem(), add, mode_T);
- attr = get_mips_attr(load);
- attr->modes.load_store_mode = mode_Iu;
- attr->tv = new_tarval_from_long(0, mode_Iu);
-
- proj = new_rd_Proj(dbg, load, mode_Iu, pn_Load_res);
-
- switchjmp = new_bd_mips_SwitchJump(dbg, block, proj, mode_T);
- attr = get_mips_attr(switchjmp);
- attr->switch_default_pn = defaultprojn;
-
- edge = get_irn_out_edge_first(defaultproj);
- defaultproj_succ = get_edge_src_irn(edge);
- attr->symconst_id = new_id_from_str(mips_get_block_label(defaultproj_succ));
-
- attr = get_mips_attr(la);
- attr->symconst_id = new_id_from_str(mips_get_jumptbl_label(switchjmp));
-
- return switchjmp;
-}
-#endif
-
-static ir_node *gen_Cond(ir_node *node)
-{
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = get_nodes_block(node);
- ir_node *sel_proj = get_Cond_selector(node);
- ir_node *cmp = get_Proj_pred(sel_proj);
- ir_node *left = get_Cmp_left(cmp);
- ir_node *new_left = be_transform_node(left);
- ir_node *right = get_Cmp_right(cmp);
- ir_node *new_right = be_transform_node(right);
- long pnc = get_Proj_proj(sel_proj);
- ir_node *res;
- ir_node *slt;
- ir_node *zero;
-
- /* TODO: use blez & co. when possible */
-
- switch (pnc) {
- case pn_Cmp_False:
- case pn_Cmp_True:
- case pn_Cmp_Leg:
- panic("mips backend can't handle unoptimized constant Cond");
-
- case pn_Cmp_Eq:
- res = new_bd_mips_beq(dbgi, block, new_left, new_right);
- break;
-
- case pn_Cmp_Lt:
- zero = mips_create_zero();
- slt = new_bd_mips_slt(dbgi, block, new_left, new_right);
- res = new_bd_mips_bne(dbgi, block, slt, zero);
- break;
-
- case pn_Cmp_Le:
- zero = mips_create_zero();
- slt = new_bd_mips_slt(dbgi, block, new_right, new_left);
- res = new_bd_mips_beq(dbgi, block, slt, zero);
- break;
-
- case pn_Cmp_Gt:
- zero = mips_create_zero();
- slt = new_bd_mips_slt(dbgi, block, new_right, new_left);
- res = new_bd_mips_bne(dbgi, block, slt, zero);
- break;
-
- case pn_Cmp_Ge:
- zero = mips_create_zero();
- slt = new_bd_mips_slt(dbgi, block, new_right, new_left);
- res = new_bd_mips_bne(dbgi, block, slt, zero);
- break;
-
- case pn_Cmp_Lg:
- res = new_bd_mips_bne(dbgi, block, new_left, new_right);
- break;
-
- default:
- panic("mips backend doesn't handle unordered compares yet");
- }
-
- return res;
-}
-
-static ir_node *gen_Conv(ir_node *node)
-{
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *op = get_Conv_op(node);
- ir_node *new_op = be_transform_node(op);
- ir_mode *src_mode = get_irn_mode(op);
- ir_mode *dst_mode = get_irn_mode(node);
- int src_size = get_mode_size_bits(src_mode);
- int dst_size = get_mode_size_bits(dst_mode);
- ir_node *res;
-
- assert(mode_needs_gp_reg(src_mode));
- assert(mode_needs_gp_reg(dst_mode));
-
- /* we only need to do something on upconvs */
- if (src_size >= dst_size) {
- /* unnecessary conv */
- return new_op;
- }
-
- if (mode_is_signed(src_mode)) {
- if (src_size == 8) {
- res = new_bd_mips_seb(dbgi, block, new_op);
- } else if (src_size == 16) {
- res = new_bd_mips_seh(dbgi, block, new_op);
- } else {
- panic("invalid conv %+F", node);
- }
- } else {
- ir_node *and_const;
-
- if (src_size == 8) {
- and_const = mips_create_Immediate(0xff);
- } else if (src_size == 16) {
- and_const = mips_create_Immediate(0xffff);
- } else {
- panic("invalid conv %+F", node);
- }
- res = new_bd_mips_and(dbgi, block, new_op, and_const);
- }
-
- return res;
-}
-
-static ir_node *create_div(ir_node *node, ir_node *left, ir_node *right,
- ir_mode *mode)
-{
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *new_left = be_transform_node(left);
- ir_node *new_right = be_transform_node(right);
- ir_node *res;
-
- if (mode_is_signed(mode)) {
- res = new_bd_mips_div(dbgi, block, new_left, new_right);
- } else {
- res = new_bd_mips_divu(dbgi, block, new_left, new_right);
- }
-
- set_irn_pinned(res, get_irn_pinned(node));
-
- return res;
-}
-
-static ir_node *gen_DivMod(ir_node *node)
-{
- return create_div(node, get_DivMod_left(node), get_DivMod_right(node),
- get_DivMod_resmode(node));
-}
-
-static ir_node *gen_Div(ir_node *node)
-{
- return create_div(node, get_Div_left(node), get_Div_right(node),
- get_Div_resmode(node));
-}
-
-static ir_node *gen_Mod(ir_node *node)
-{
- return create_div(node, get_Mod_left(node), get_Mod_right(node),
- get_Mod_resmode(node));
-}
-
-#if 0
-static ir_node *gen_node_for_Mul(mips_transform_env_t *env)
-{
- ir_node *node = env->irn;
- ir_node *mul;
- ir_node *mflo;
- ir_node *op1, *op2;
- ir_mode *mode = get_irn_mode(node);
-
- op1 = get_Mul_left(node);
- op2 = get_Mul_right(node);
-
- assert(get_mode_size_bits(env->mode) == 32);
- assert(get_mode_size_bits(get_irn_mode(op1)) == get_mode_size_bits(env->mode));
- assert(get_mode_size_bits(get_irn_mode(op2)) == get_mode_size_bits(env->mode));
-
- if (mode_is_signed(mode)) {
- mul = new_bd_mips_mult(env->dbg, env->block, get_Mul_left(node), get_Mul_right(node));
- } else {
- mul = new_bd_mips_multu(env->dbg, env->block, get_Mul_left(node), get_Mul_right(node));
- }
- mflo = new_bd_mips_mflo(env->dbg, env->block, mul);
-
- return mflo;
-}
-
-static ir_node *gen_node_for_IJmp(mips_transform_env_t *env)
-{
- ir_node *node = env->irn;
- dbg_info *dbg = get_irn_dbg_info(node);
- ir_node *block = get_nodes_block(node);
- ir_node *target = get_IJmp_target(node);
-
- return new_bd_mips_jr(dbg, block, target);
-}
-
-static ir_node *gen_node_for_Rot(mips_transform_env_t *env)
-{
- ir_node *node = env->irn;
- ir_node *subu, *srlv, *sllv, *or;
-
- subu = new_bd_mips_subuzero(env->dbg, env->block, get_Rot_right(node));
- srlv = new_bd_mips_srlv(env->dbg, env->block, get_Rot_left(node), subu);
- sllv = new_bd_mips_sllv(env->dbg, env->block, get_Rot_left(node), get_Rot_right(node));
- or = new_bd_mips_or(env->dbg, env->block, sllv, srlv);
-
- return or;
-}
-#endif
-
-static ir_node *gen_Unknown(ir_node *node)
-{
- (void) node;
- assert(mode_needs_gp_reg(get_irn_mode(node)));
- return mips_create_zero();
-}
-
-#if 0
-/*
- * lower a copyB into standard Firm assembler :-)
- */
-ir_node *gen_code_for_CopyB(ir_node *block, ir_node *node)
-{
- ir_node *cnt, *sub;
- ir_node *dst = get_CopyB_dst(node);
- ir_node *src = get_CopyB_src(node);
- ir_type *type = get_CopyB_type(node);
- ir_node *mem = get_CopyB_mem(node);
- ir_node *mm[4];
- ir_node *result = NULL;
- int size = get_type_size_bytes(type);
- dbg_info *dbg = get_irn_dbg_info(node);
- ir_graph *irg = get_irn_irg(block);
- mips_attr_t *attr;
- int i, n;
-
- if (size > 16) {
- ir_node *phi, *projT, *projF, *cmp, *proj, *cond, *jmp, *in[2];
- ir_node *new_bl, *src_phi, *dst_phi, *mem_phi, *add;
- ir_mode *p_mode = get_irn_mode(src);
- ir_node *ld[4];
-
- /* build the control loop */
- in[0] = in[1] = new_r_Unknown(irg, mode_X);
-
- new_bl = new_r_Block(irg, 2, in);
-
- in[0] = cnt = new_Const_long(mode_Is, (size >> 4));
- in[1] = new_r_Unknown(irg, mode_Is);
- phi = new_r_Phi(irg, new_bl, 2, in, mode_Is);
-
- sub = new_rd_Sub(dbg, irg, new_bl, phi, new_Const_long(mode_Is, -1), mode_Is);
- set_Phi_pred(phi, 1, sub);
-
- cmp = new_rd_Cmp(dbg, irg, new_bl, sub, new_Const_long(mode_Is, 0));
- proj = new_r_Proj(irg, new_bl, cmp, mode_b, pn_Cmp_Lg);
- cond = new_rd_Cond(dbg, irg, new_bl, proj);
-
- projT = new_r_Proj(irg, new_bl, cond, mode_X, pn_Cond_true);
- projF = new_r_Proj(irg, new_bl, cond, mode_X, pn_Cond_false);
-
- jmp = get_Block_cfgpred(block, 0);
- set_Block_cfgpred(block, 0, projF);
-
- set_Block_cfgpred(new_bl, 0, jmp);
- set_Block_cfgpred(new_bl, 1, projT);
-
- size &= 0xF;
-
- /* build the copy */
- in[0] = src;
- in[1] = new_r_Unknown(irg, p_mode);
- src_phi = new_r_Phi(irg, new_bl, 2, in, p_mode);
-
- in[0] = dst;
- dst_phi = new_r_Phi(irg, new_bl, 2, in, p_mode);
-
- add = new_rd_Add(dbg, irg, new_bl, src_phi, new_Const_long(mode_Is, 16), p_mode);
- set_Phi_pred(src_phi, 1, add);
- add = new_rd_Add(dbg, irg, new_bl, dst_phi, new_Const_long(mode_Is, 16), p_mode);
- set_Phi_pred(dst_phi, 1, add);
-
- in[0] = mem;
- in[1] = new_r_Unknown(irg, mode_M);
- mem_phi = new_r_Phi(irg, new_bl, 2, in, mode_M);
-
- src = src_phi;
- dst = dst_phi;
-
- /* create 4 parallel loads */
- for (i = 0; i < 4; ++i) {
- ir_node *load;
-
- load = new_bd_mips_load_r(dbg, new_bl, mem_phi, src, mode_T);
- attr = get_mips_attr(load);
- attr->modes.load_store_mode = mode_Iu;
- attr->tv = new_tarval_from_long(i * 4, mode_Iu);
-
- ld[i] = new_rd_Proj(dbg, irg, load, mode_Iu, pn_Load_res);
- }
-
- /* create 4 parallel stores */
- for (i = 0; i < 4; ++i) {
- ir_node *store;
-
- store = new_bd_mips_store_r(dbg, new_bl, mem_phi, dst, ld[i], mode_T);
- attr = get_mips_attr(store);
- attr->modes.load_store_mode = mode_Iu;
- attr->tv = new_tarval_from_long(i * 4, mode_Iu);
-
- mm[i] = new_rd_Proj(dbg, irg, store, mode_M, pn_Store_M);
- }
- mem = new_r_Sync(irg, new_bl, 4, mm);
- result = mem;
- set_Phi_pred(mem_phi, 1, mem);
- }
-
- // output store/loads manually
- n = 0;
- for (i = size; i > 0; ) {
- ir_mode *mode;
- ir_node *load, *store, *projv;
- int offset = size - i;
- if (i >= 4) {
- mode = mode_Iu;
- i -= 4;
- } else if (i >= 2) {
- mode = mode_Hu;
- i -= 2;
- } else {
- mode = mode_Bu;
- i -= 1;
- }
-
- load = new_bd_mips_load_r(dbg, block, mem, src, mode_T);
- attr = get_mips_attr(load);
- attr->modes.load_store_mode = mode;
- attr->tv = new_tarval_from_long(offset, mode_Iu);
-
- projv = new_rd_Proj(dbg, irg, load, mode, pn_Load_res);
-
- store = new_bd_mips_store_r(dbg, block, mem, dst, projv, mode_T);
- attr = get_mips_attr(store);
- attr->modes.load_store_mode = mode;
- attr->tv = new_tarval_from_long(offset, mode_Iu);
-
- mm[n] = new_rd_Proj(dbg, irg, store, mode_M, pn_Store_M);
- n++;
- }
-
- if (n > 0) {
- result = new_r_Sync(irg, block, n, mm);
- } else if (n == 1) {
- result = mm[0];
- }
-
- return result;
-}
-
-static void mips_fix_CopyB_Proj(mips_transform_env_t* env)
-{
- ir_node *node = env->irn;
- long n = get_Proj_proj(node);
-
- if (n == pn_CopyB_M_except) {
- panic("Unsupported Proj from CopyB");
- } else if (n == pn_CopyB_M_regular) {
- set_Proj_proj(node, pn_Store_M);
- } else if (n == pn_CopyB_M_except) {
- set_Proj_proj(node, pn_Store_X_except);
- }
-}
-#endif
-
-static void mips_transform_Spill(mips_transform_env_t* env)
-{
- ir_node *node = env->irn;
- ir_node *sched_point = NULL;
- ir_node *store;
- ir_node *nomem = new_NoMem();
- ir_node *ptr = get_irn_n(node, 0);
- ir_node *val = get_irn_n(node, 1);
- ir_entity *ent = be_get_frame_entity(node);
-
- if (sched_is_scheduled(node)) {
- sched_point = sched_prev(node);
- }
-
- store = new_bd_mips_sw(env->dbg, env->block, ptr, val, nomem, ent, 0);
-
- if (sched_point) {
- sched_add_after(sched_point, store);
- sched_remove(node);
- }
-
- exchange(node, store);
-}
-
-static void mips_transform_Reload(mips_transform_env_t* env)
-{
- ir_node *node = env->irn;
- ir_node *sched_point = NULL;
- ir_node *load, *proj;
- ir_node *ptr = get_irn_n(node, 0);
- ir_node *mem = get_irn_n(node, 1);
- ir_entity *ent = be_get_frame_entity(node);
- const arch_register_t* reg;
-
- if (sched_is_scheduled(node)) {
- sched_point = sched_prev(node);
- }
-
- load = new_bd_mips_lw(env->dbg, env->block, ptr, mem, ent, 0);
-
- proj = new_rd_Proj(env->dbg, load, mode_Iu, pn_mips_lw_res);
-
- if (sched_point) {
- sched_add_after(sched_point, load);
-
- sched_remove(node);
- }
-
- /* copy the register from the old node to the new Load */
- reg = arch_get_irn_register(node);
- arch_set_irn_register(proj, reg);
-
- exchange(node, proj);
-}
-
-#if 0
-static ir_node *gen_AddSP(ir_node *node)
-{
- ir_node *node = env->irn;
- ir_node *op1, *op2;
- ir_node *add;
- const arch_register_t *reg;
-
- op1 = get_irn_n(node, 0);
- op2 = get_irn_n(node, 1);
-
- add = new_bd_mips_addu(env->dbg, env->block, op1, op2);
-
- /* copy the register requirements from the old node to the new node */
- reg = arch_get_irn_register(node);
- arch_set_irn_register(add, reg);
-
- return add;
-}
-#endif
-
-/*********************************************************
- * _ _ _
- * (_) | | (_)
- * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
- * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
- * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
- * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
- *
- *********************************************************/
-
-typedef ir_node *(*mips_transform_func) (ir_node *node);
-
-static void register_transformer(ir_op *op, mips_transform_func func)
-{
- assert(op->ops.generic == NULL);
- op->ops.generic = (op_func) func;
-}
-
-static void register_transformers(void)
-{
- clear_irp_opcodes_generic_func();
-
- register_transformer(op_Add, gen_Add);
- register_transformer(op_Sub, gen_Sub);
- register_transformer(op_And, gen_And);
- register_transformer(op_Or, gen_Or);
- register_transformer(op_Eor, gen_Eor);
- register_transformer(op_Shl, gen_Shl);
- register_transformer(op_Shr, gen_Shr);
- register_transformer(op_Shrs, gen_Shrs);
- register_transformer(op_Not, gen_Not);
- register_transformer(op_Minus, gen_Minus);
- register_transformer(op_Div, gen_Div);
- register_transformer(op_Mod, gen_Mod);
- register_transformer(op_DivMod, gen_DivMod);
- register_transformer(op_Abs, gen_Abs);
- register_transformer(op_Load, gen_Load);
- register_transformer(op_Store, gen_Store);
- register_transformer(op_Cond, gen_Cond);
- register_transformer(op_Conv, gen_Conv);
- register_transformer(op_Const, gen_Const);
- register_transformer(op_SymConst, gen_SymConst);
- register_transformer(op_Unknown, gen_Unknown);
- register_transformer(op_Proj, gen_Proj);
- register_transformer(op_Phi, gen_Phi);
-}
-
-void mips_transform_graph(mips_code_gen_t *cg)
-{
- register_transformers();
- be_transform_graph(cg->irg, NULL);
-}
-
-/**
- * Calls the transform functions for Spill and Reload.
- */
-void mips_after_ra_walker(ir_node *node, void *env)
-{
- mips_code_gen_t *cg = env;
- mips_transform_env_t tenv;
-
- if (is_Block(node))
- return;
-
- tenv.block = get_nodes_block(node);
- tenv.dbg = get_irn_dbg_info(node);
- tenv.irg = current_ir_graph;
- tenv.irn = node;
- tenv.mode = get_irn_mode(node);
- tenv.cg = cg;
-
- if (be_is_Reload(node)) {
- mips_transform_Reload(&tenv);
- } else if (be_is_Spill(node)) {
- mips_transform_Spill(&tenv);
- }
-}
+++ /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 code transform (code selection)
- * @author Matthias Braun, Mehdi
- * @version $Id$
- */
-#ifndef FIRM_BE_MIPS_MIPS_TRANSFORM_H
-#define FIRM_BE_MIPS_MIPS_TRANSFORM_H
-
-/**
- * Create Firm assembler for a copyB node.
- *
- * @param blk the block where to place the code
- * @param node the copyB node to lower
- *
- * @return the memory from the lowered CopyB
- */
-ir_node *gen_code_for_CopyB(ir_node *blk, ir_node *node);
-
-ir_node *mips_create_Immediate(long offset);
-ir_node *mips_create_zero(void);
-
-void mips_transform_graph(mips_code_gen_t *cg);
-void mips_after_ra_walker(ir_node *node, void *env);
-
-#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 utility macros for mips backend
- * @author Matthias Braun, Mehdi
- * @version $Id$
- */
-#ifndef FIRM_BE_MIPS_MIPS_UTIL_H
-#define FIRM_BE_MIPS_MIPS_UTIL_H
-
-#define ASSERT_NO_FLOAT(mode) do { assert( (!mode_is_float(mode)) && "floating point not supported (yet)"); } while(0)
-
-#endif