From aebc3c0c980bcc0536ffdc4cb2a545961b5a8b81 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Wed, 2 May 2007 13:16:54 +0000 Subject: [PATCH] added doxygen comments, transform mips to new emit style, use gnuas gendecls [r13584] --- ir/be/mips/bearch_mips.c | 92 +++--- ir/be/mips/bearch_mips.h | 14 +- ir/be/mips/bearch_mips_t.h | 46 +-- ir/be/mips/mips_emitter.c | 564 ++++++++++++++++------------------ ir/be/mips/mips_emitter.h | 39 ++- ir/be/mips/mips_gen_decls.c | 578 ----------------------------------- ir/be/mips/mips_gen_decls.h | 28 -- ir/be/mips/mips_map_regs.c | 6 +- ir/be/mips/mips_map_regs.h | 12 +- ir/be/mips/mips_new_nodes.c | 9 +- ir/be/mips/mips_new_nodes.h | 13 +- ir/be/mips/mips_nodes_attr.h | 12 +- ir/be/mips/mips_scheduler.c | 8 +- ir/be/mips/mips_spec.pl | 129 ++++---- ir/be/mips/mips_transform.c | 9 +- ir/be/mips/mips_transform.h | 12 +- ir/be/mips/mips_util.h | 12 +- 17 files changed, 496 insertions(+), 1087 deletions(-) delete mode 100644 ir/be/mips/mips_gen_decls.c delete mode 100644 ir/be/mips/mips_gen_decls.h diff --git a/ir/be/mips/bearch_mips.c b/ir/be/mips/bearch_mips.c index d433b46bf..015dbf03a 100644 --- a/ir/be/mips/bearch_mips.c +++ b/ir/be/mips/bearch_mips.c @@ -17,8 +17,12 @@ * PURPOSE. */ -/* The main mips backend driver file. */ -/* $Id$ */ +/** + * @file + * @brief The main mips backend driver file. + * @author Matthias Braun, Mehdi + * @version $Id$ + */ #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -38,7 +42,7 @@ #include "bitset.h" #include "debug.h" -#include "../bearch_t.h" /* the general register allocator interface */ +#include "../bearch_t.h" #include "../benode_t.h" #include "../belower.h" #include "../besched_t.h" @@ -46,12 +50,14 @@ #include "../beabi.h" #include "../bemachine.h" #include "../bemodule.h" +#include "../beemitter.h" +#include "../begnuas.h" +#include "../begnuas.h" #include "bearch_mips_t.h" -#include "mips_new_nodes.h" /* mips nodes interface */ -#include "gen_mips_regalloc_if.h" /* the generated interface (register type and class defenitions) */ -#include "mips_gen_decls.h" /* interface declaration emitter */ +#include "mips_new_nodes.h" +#include "gen_mips_regalloc_if.h" #include "mips_transform.h" #include "mips_emitter.h" #include "mips_map_regs.h" @@ -465,18 +471,10 @@ static void mips_after_ra(void* self) { * the code generator interface. */ static void mips_emit_and_done(void *self) { - mips_code_gen_t *cg = self; - ir_graph *irg = cg->irg; - FILE *out = cg->isa->out; - - mips_register_emitters(); - - if (cg->emit_decls) { - mips_gen_decls(out); - cg->emit_decls = 0; - } + mips_code_gen_t *cg = self; + ir_graph *irg = cg->irg; - mips_gen_routine(out, irg, cg); + mips_gen_routine(cg, irg); cur_reg_set = NULL; @@ -508,8 +506,8 @@ static const arch_code_generator_if_t mips_code_gen_if = { */ static void *mips_cg_init(be_irg_t *birg) { const arch_env_t *arch_env = be_get_birg_arch_env(birg); - mips_isa_t *isa = (mips_isa_t *) arch_env->isa; - mips_code_gen_t *cg = xmalloc(sizeof(*cg)); + mips_isa_t *isa = (mips_isa_t *) arch_env->isa; + mips_code_gen_t *cg = xmalloc(sizeof(*cg)); cg->impl = &mips_code_gen_if; cg->irg = be_get_birg_irg(birg); @@ -520,13 +518,6 @@ static void *mips_cg_init(be_irg_t *birg) { cg->bl_list = NULL; FIRM_DBG_REGISTER(cg->mod, "firm.be.mips.cg"); - isa->num_codegens++; - - if (isa->num_codegens > 1) - cg->emit_decls = 0; - else - cg->emit_decls = 1; - cur_reg_set = cg->reg_set; mips_irn_ops.cg = cg; @@ -546,12 +537,14 @@ static void *mips_cg_init(be_irg_t *birg) { *****************************************************************/ static mips_isa_t mips_isa_template = { - &mips_isa_if, - &mips_gp_regs[REG_SP], - &mips_gp_regs[REG_FP], - -1, // stack direction - 0, // num codegens?!? TODO what is this? - NULL + { + &mips_isa_if, + &mips_gp_regs[REG_SP], + &mips_gp_regs[REG_FP], + -1, /* stack direction */ + NULL, /* main environment */ + }, + { NULL, }, /* emitter environment */ }; /** @@ -563,17 +556,22 @@ static void *mips_init(FILE *file_handle) { if(inited) return NULL; + inited = 1; - isa = xcalloc(1, sizeof(*isa)); - memcpy(isa, &mips_isa_template, sizeof(*isa)); + isa = xcalloc(1, sizeof(isa[0])); + memcpy(isa, &mips_isa_template, sizeof(isa[0])); - isa->out = file_handle; + be_emit_init_env(&isa->emit, file_handle); mips_register_init(isa); mips_create_opcodes(); mips_init_opcode_transforms(); - inited = 1; + /* we mark referenced global entities, so we can only emit those which + * are actually referenced. (Note: you mustn't use the type visited flag + * elsewhere in the backend) + */ + inc_master_type_visited(); return isa; } @@ -582,7 +580,12 @@ static void *mips_init(FILE *file_handle) { * Closes the output file and frees the ISA structure. */ static void mips_done(void *self) { - free(self); + mips_isa_t *isa = self; + + be_gas_emit_decls(&isa->emit, isa->arch_isa.main_env, 1); + + be_emit_destroy_env(&isa->emit); + free(isa); } static int mips_get_n_reg_class(const void *self) { @@ -609,7 +612,7 @@ const arch_register_class_t *mips_get_reg_class_for_mode(const void *self, const typedef struct { be_abi_call_flags_bits_t flags; - const mips_isa_t *isa; + const arch_isa_t *isa; const arch_env_t *arch_env; ir_graph *irg; // do special handling to support debuggers @@ -620,19 +623,20 @@ static void *mips_abi_init(const be_abi_call_t *call, const arch_env_t *arch_env { mips_abi_env_t *env = xmalloc(sizeof(env[0])); 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->isa = (const mips_isa_t*) arch_env->isa; - env->debug = 1; + env->flags = fl.bits; + env->irg = irg; + env->arch_env = arch_env; + env->isa = arch_env->isa; + env->debug = 1; return env; } static void mips_abi_dont_save_regs(void *self, pset *s) { mips_abi_env_t *env = self; + if(env->flags.try_omit_fp) - pset_insert_ptr(s, env->isa->fp); + pset_insert_ptr(s, env->isa->bp); } static const arch_register_t *mips_abi_prologue(void *self, ir_node** mem, pmap *reg_map) diff --git a/ir/be/mips/bearch_mips.h b/ir/be/mips/bearch_mips.h index 78345d6dc..5496dbb45 100644 --- a/ir/be/mips/bearch_mips.h +++ b/ir/be/mips/bearch_mips.h @@ -17,12 +17,18 @@ * PURPOSE. */ -#ifndef _BEARCH_MIPS_H_ -#define _BEARCH_MIPS_H_ +/** + * @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_t.h" -typedef struct _mips_code_gen_t mips_code_gen_t; +typedef struct mips_code_gen_t mips_code_gen_t; extern const arch_isa_if_t mips_isa_if; @@ -38,4 +44,4 @@ void mips_set_block_sched_nr(ir_node *block, int nr); /** get a block schedule number */ int mips_get_block_sched_nr(ir_node *block); -#endif /* _BEARCH_MIPS_H_ */ +#endif diff --git a/ir/be/mips/bearch_mips_t.h b/ir/be/mips/bearch_mips_t.h index 4e0593544..3c45f4c49 100644 --- a/ir/be/mips/bearch_mips_t.h +++ b/ir/be/mips/bearch_mips_t.h @@ -17,19 +17,28 @@ * PURPOSE. */ -#ifndef _BEARCH_mips_T_H_ -#define _BEARCH_mips_T_H_ +/** + * @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_isa_t mips_isa_t; +typedef struct mips_irn_ops_t mips_irn_ops_t; +typedef struct mips_transform_env_t mips_transform_env_t; -struct _mips_code_gen_t { +struct mips_code_gen_t { const arch_code_generator_if_t *impl; /**< implementation */ ir_graph *irg; /**< current irg */ const arch_env_t *arch_env; /**< the arch env */ @@ -42,24 +51,23 @@ struct _mips_code_gen_t { DEBUG_ONLY(firm_dbg_module_t *mod;) /**< debugging module */ }; -struct _mips_isa_t { - const arch_isa_if_t *impl; - const arch_register_t *sp; /**< The stack pointer register. */ - const arch_register_t *fp; /**< The base pointer register. */ - const int stack_dir; /**< -1 for decreasing, 1 for increasing. */ - int num_codegens; - FILE *out; /**< output file */ +struct mips_isa_t { + arch_isa_t arch_isa; /**< must be derived from arch_isa_t */ + + be_emit_env_t emit; }; -typedef struct _mips_irn_ops_t { +struct mips_irn_ops_t { const arch_irn_ops_if_t *impl; - mips_code_gen_t *cg; -} mips_irn_ops_t; + mips_code_gen_t *cg; +}; -/* this is a struct to minimize the number of parameters - for transformation walker */ -typedef struct _mips_transform_env_t { +/** + * 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 */ @@ -67,8 +75,8 @@ typedef struct _mips_transform_env_t { ir_mode *mode; /**< The mode of the irn */ mips_code_gen_t *cg; /**< The code generator */ DEBUG_ONLY(firm_dbg_module_t *mod;) /**< The firm debugger */ -} mips_transform_env_t; +}; ir_node *mips_new_NoReg(mips_code_gen_t *cg); -#endif /* _BEARCH_mips_T_H_ */ +#endif diff --git a/ir/be/mips/mips_emitter.c b/ir/be/mips/mips_emitter.c index 9f6e98c7e..13a5d708b 100644 --- a/ir/be/mips/mips_emitter.c +++ b/ir/be/mips/mips_emitter.c @@ -17,8 +17,12 @@ * PURPOSE. */ -/* mips emitter */ -/* $Id$ */ +/** + * @file + * @brief implementation of mips assembly emitter + * @author Matthias Braun, Mehdi + * @version $Id$ + */ #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -26,7 +30,6 @@ #include #include "xmalloc.h" -#include "tv.h" #include "iredges.h" #include "debug.h" #include "irgwalk.h" @@ -35,11 +38,13 @@ #include "irargs_t.h" #include "irprog_t.h" #include "irouts.h" +#include "tv.h" #include "error.h" #include "../besched.h" #include "../benode_t.h" #include "../beutil.h" +#include "../begnuas.h" #include "mips_emitter.h" #include "gen_mips_emitter.h" @@ -47,10 +52,65 @@ #include "mips_new_nodes.h" #include "mips_map_regs.h" +DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;) + #define SNPRINTF_BUF_LEN 128 -static const arch_env_t *arch_env = NULL; +/** + * Returns the register at in position pos. + */ +static const arch_register_t *get_in_reg(const arch_env_t *arch_env, + 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(arch_env, 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 arch_env_t *arch_env, + 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(arch_env, node); + } else if (is_mips_irn(node)) { + reg = get_mips_out_reg(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(arch_env, proj); + break; + } + } + } + + assert(reg && "no out register found"); + return reg; +} /************************************************************* * _ _ __ _ _ @@ -63,6 +123,21 @@ static const arch_env_t *arch_env = NULL; * |_| |_| *************************************************************/ +void mips_emit_source_register(mips_emit_env_t *env, const ir_node *node, + int pos) +{ + const arch_register_t *reg = get_in_reg(env->arch_env, node, pos); + be_emit_string(env->emit, arch_register_get_name(reg)); +} + +void mips_emit_dest_register(mips_emit_env_t *env, const ir_node *node, + int pos) +{ + const arch_register_t *reg = get_out_reg(env->arch_env, node, pos); + be_emit_string(env->emit, arch_register_get_name(reg)); +} + +#if 0 static const char *get_symconst_str(ir_node *node) { ident *id; @@ -144,207 +219,22 @@ static const char *node_const_to_str(ir_node *n) return buf; } +#endif -/** - * Returns node's offset as string. - */ -static const char *node_offset_to_str(ir_node *n) -{ - return ""; -} - -/* We always pass the ir_node which is a pointer. */ -static int mips_get_arg_type(const lc_arg_occ_t *occ) { - return lc_arg_type_ptr; -} - - -/** - * Returns the register at in position pos. - */ -static const arch_register_t *get_in_reg(ir_node *irn, int pos) -{ - ir_node *op; - const arch_register_t *reg = NULL; - - assert(get_irn_arity(irn) > pos && "Invalid IN position"); - - /* The out register of the operator at position pos is the - in register we need. */ - op = get_irn_n(irn, pos); - - reg = arch_get_irn_register(arch_env, op); - - assert(reg && "no in register found"); - return reg; -} - -/** - * Returns the register at out position pos. - */ -static const arch_register_t *get_out_reg(ir_node *irn, 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(irn) != mode_T) { - reg = arch_get_irn_register(arch_env, irn); - } - else if (is_mips_irn(irn)) { - reg = get_mips_out_reg(irn, pos); - } - else { - const ir_edge_t *edge; - - foreach_out_edge(irn, 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(arch_env, proj); - break; - } - } - } - - assert(reg && "no out register found"); - return reg; -} - -/** - * Returns the number of the in register at position pos. - */ -int get_mips_reg_nr(ir_node *irn, int pos, int in_out) -{ - const arch_register_t *reg; - - if (in_out == 1) { - reg = get_in_reg(irn, pos); - } - else { - reg = get_out_reg(irn, pos); - } - - return arch_register_get_index(reg); -} - -/** - * Returns the name of the in register at position pos. - */ -const char *get_mips_reg_name(ir_node *irn, int pos, int in_out) -{ - const arch_register_t *reg; - - if (in_out == 1) { - reg = get_in_reg(irn, pos); - } - else { - reg = get_out_reg(irn, pos); - } - - return arch_register_get_name(reg); -} - -/** - * Get the register name for a node. - */ -static int mips_get_reg_name(lc_appendable_t *app, - const lc_arg_occ_t *occ, const lc_arg_value_t *arg) -{ - const char *buf; - int res; - ir_node *X = arg->v_ptr; - int nr = occ->width - 1; - - if (!X) - return lc_arg_append(app, occ, "(null)", 6); - - if (occ->conversion == 'S') { - buf = get_mips_reg_name(X, nr, 1); - } - else { /* 'D' */ - buf = get_mips_reg_name(X, nr, 0); - } - - res = lc_appendable_chadd(app, '$'); - res += lc_appendable_snadd(app, buf, strlen(buf)); - return res; -} - -/** - * Returns the tarval or offset of an mips node as a string. - */ -static int mips_const_to_str(lc_appendable_t *app, - const lc_arg_occ_t *occ, const lc_arg_value_t *arg) -{ - const char *buf; - ir_node *X = arg->v_ptr; - - if (!X) - return lc_arg_append(app, occ, "(null)", 6); - - if (occ->conversion == 'C') { - buf = node_const_to_str(X); - } - else { /* 'O' */ - buf = node_offset_to_str(X); - } - - return lc_arg_append(app, occ, buf, strlen(buf)); -} - -/** - * Determines the SSE suffix depending on the mode. - */ -static int mips_get_mode_suffix(lc_appendable_t *app, - const lc_arg_occ_t *occ, const lc_arg_value_t *arg) -{ - ir_node *X = arg->v_ptr; - - if (!X) - return lc_arg_append(app, occ, "(null)", 6); - - if (get_mode_size_bits(get_irn_mode(X)) == 32) - return lc_appendable_chadd(app, 's'); - else - return lc_appendable_chadd(app, 'd'); -} - -/** - * Return the mips printf arg environment. - * We use the firm environment with some additional handlers. - */ -const lc_arg_env_t *mips_get_arg_env(void) +void mips_emit_immediate(mips_emit_env_t *env, const ir_node *node) { - static lc_arg_env_t *env = NULL; - - static const lc_arg_handler_t mips_reg_handler = { mips_get_arg_type, mips_get_reg_name }; - static const lc_arg_handler_t mips_const_handler = { mips_get_arg_type, mips_const_to_str }; - static const lc_arg_handler_t mips_mode_handler = { mips_get_arg_type, mips_get_mode_suffix }; - - if(env == NULL) { - /* extend the firm printer */ - env = firm_get_arg_env(); - //lc_arg_new_env(); - - lc_arg_register(env, "mips:sreg", 'S', &mips_reg_handler); - lc_arg_register(env, "mips:dreg", 'D', &mips_reg_handler); - lc_arg_register(env, "mips:cnst", 'C', &mips_const_handler); - lc_arg_register(env, "mips:offs", 'O', &mips_const_handler); - lc_arg_register(env, "mips:mode", 'M', &mips_mode_handler); - } + const mips_attr_t *attr = get_mips_attr(node); - return env; + be_emit_char(env->emit, '$'); + tarval *tv = attr->tv; + be_emit_tarval(env->emit, tv); } /* * 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 +char *get_unique_label(char *buf, size_t buflen, const char *prefix) { static unsigned long id = 0; snprintf(buf, buflen, "%s%lu", prefix, ++id); @@ -355,13 +245,14 @@ static char *get_unique_label(char *buf, size_t buflen, const char *prefix) /* ABI Handling */ /************************************************************************/ -static void mips_emit_IncSP(const ir_node *node, mips_emit_env_t *env) +static +void mips_emit_IncSP(mips_emit_env_t *env, const ir_node *node) { - FILE *F = env->out; int offset = be_get_IncSP_offset(node); if(offset == 0) { - fprintf(F, "\t\t\t\t # omitted IncSP with 0\n"); + be_emit_cstring(env->emit, "\t/* omitted IncSP with 0 */"); + be_emit_finish_line_gas(env->emit, node); return; } @@ -370,85 +261,113 @@ static void mips_emit_IncSP(const ir_node *node, mips_emit_env_t *env) } if(offset > 0) { - fprintf(F, "\tsubu $sp, $sp, %d\n", offset); + be_emit_irprintf(env->emit, "\tsubu $sp, $sp, %d", offset); } else { - fprintf(F, "\taddu $sp, $sp, %d\n", -offset); + be_emit_irprintf(env->emit, "\taddu $sp, $sp, %d", -offset); } + be_emit_finish_line_gas(env->emit, node); } -static void mips_emit_Copy(const ir_node *node, mips_emit_env_t *env) +static void mips_emit_Copy(mips_emit_env_t *env, const ir_node *node) { - FILE *F = env->out; - - lc_efprintf(mips_get_arg_env(), F, "\tmove %1D, %1S\t\t\t# copy\n", node, node); + be_emit_cstring(env->emit, "\tmove "); + mips_emit_dest_register(env, node, 0); + be_emit_cstring(env->emit, ", "); + mips_emit_source_register(env, node, 0); + be_emit_finish_line_gas(env->emit, node); } -static void mips_emit_Return(const ir_node* node, mips_emit_env_t *env) +static void mips_emit_Return(mips_emit_env_t *env, const ir_node* node) { - FILE *F = env->out; - fprintf(F, "\tj $ra\t\t\t\t# return\n"); + be_emit_cstring(env->emit, "\tj $ra"); + be_emit_finish_line_gas(env->emit, node); } -static void mips_emit_nops(FILE* F, int n) +static __attribute__((unused)) +void mips_emit_nops(mips_emit_env_t *env, int n) { int i; for(i = 0; i < n; ++i) { - fprintf(F, "\tnop\n"); + be_emit_cstring(env->emit, "\tnop\n"); + be_emit_write_line(env->emit); } } static void mips_emit_Perm(const ir_node *node, mips_emit_env_t *env) { - FILE *F = env->out; - assert(get_irn_arity(node) == 2); - lc_efprintf(mips_get_arg_env(), F, "\txor %1S, %1S, %2S\t\t\t# perm\n", node, node, node); - mips_emit_nops(F, 3); - lc_efprintf(mips_get_arg_env(), F, "\txor %2S, %2S, %1S\n", node, node, node); - mips_emit_nops(F, 3); - lc_efprintf(mips_get_arg_env(), F, "\txor %1S, %1S, %2S\n", node, node, node); - mips_emit_nops(F, 3); + be_emit_cstring(env->emit, "\txor "); + mips_emit_source_register(env, node, 0); + be_emit_cstring(env->emit, ", "); + mips_emit_source_register(env, node, 0); + be_emit_cstring(env->emit, ", "); + mips_emit_source_register(env, node, 1); + be_emit_finish_line_gas(env->emit, node); + + /* mips_emit_nops(env, 3); */ + + be_emit_cstring(env->emit, "\txor "); + mips_emit_source_register(env, node, 1); + be_emit_cstring(env->emit, ", "); + mips_emit_source_register(env, node, 1); + be_emit_cstring(env->emit, ", "); + mips_emit_source_register(env, node, 0); + be_emit_finish_line_gas(env->emit, node); + + /* mips_emit_nops(env, 3); */ + + be_emit_cstring(env->emit, "\txor "); + mips_emit_source_register(env, node, 0); + be_emit_cstring(env->emit, ", "); + mips_emit_source_register(env, node, 0); + be_emit_cstring(env->emit, ", "); + mips_emit_source_register(env, node, 1); + be_emit_finish_line_gas(env->emit, node); + + /* mips_emit_nops(env, 3); */ } -static void mips_emit_Spill(const ir_node* node, mips_emit_env_t *env) + +static void mips_emit_Spill(mips_emit_env_t *env, const ir_node *node) { +#if 0 FILE *F = env->out; ir_entity *ent = be_get_frame_entity(node); lc_efprintf(mips_get_arg_env(), F, "\tsw %1S, %d($fp)\n", node, get_entity_offset(ent)); +#endif + /* TODO lower spills and don't emit them... */ } -static void mips_emit_Reload(const ir_node* node, mips_emit_env_t *env) +static void mips_emit_Reload(mips_emit_env_t *env, const ir_node *node) { +#if 0 FILE *F = env->out; ir_entity *ent = be_get_frame_entity(node); lc_efprintf(mips_get_arg_env(), F, "\tlw %1D, %d($fp)\n", node, get_entity_offset(ent)); +#endif + /* TODO lower reloads instead of emitting them... */ } /************************************************************************/ /* Calls */ /************************************************************************/ -static void mips_emit_Call(ir_node *node, mips_emit_env_t *env) +static void mips_emit_Call(mips_emit_env_t *env, const ir_node *node) { - FILE *F = env->out; - const arch_register_t *callee_reg; + be_emit_cstring(env->emit, "\tjal "); // call to imediate value (label) ir_entity *callee = be_Call_get_entity(node); if(callee != NULL) { - fprintf(F, "\tjal %s\n", get_entity_name(callee)); - return; + be_emit_ident(env->emit, get_entity_ident(callee)); + } else { + mips_emit_source_register(env, node, be_pos_Call_ptr); } - - // call to function pointer - callee_reg = get_in_reg(node, be_pos_Call_ptr); - assert(callee_reg != NULL); - - fprintf(F, "\tjal %s\n", arch_register_get_name(callee_reg)); + be_emit_finish_line_gas(env->emit, node); } /************************************************************************ @@ -468,14 +387,20 @@ const char* mips_get_block_label(const ir_node* block) return buf; } -static void mips_emit_Jump(ir_node *node, mips_emit_env_t *env) +static +void mips_emit_block_label(mips_emit_env_t *env, const ir_node *block) { - FILE *F = env->out; - const ir_node *block = get_irn_link(node); + be_emit_irprintf(env->emit, "BLOCK_%ld", get_irn_node_nr(block)); +} +static void mips_emit_Jump(mips_emit_env_t *env, const ir_node *node) +{ + const ir_node *block = get_irn_link(node); assert(is_Block(block)); - fprintf(F, "\tb %s\n", mips_get_block_label(block)); + be_emit_cstring(env->emit, "\tb "); + mips_emit_block_label(env, block); + be_emit_finish_line_gas(env->emit, node); } ir_node *mips_get_jump_block(const ir_node* node, int projn) @@ -495,6 +420,22 @@ ir_node *mips_get_jump_block(const ir_node* node, int projn) return NULL; } +void mips_emit_jump_target_proj(mips_emit_env_t *env, const ir_node *node, int projn) +{ + ir_node *jumpblock = mips_get_jump_block(node, projn); + assert(jumpblock != NULL); + + mips_emit_block_label(env, jumpblock); +} + +void mips_emit_jump_target(mips_emit_env_t *env, const ir_node *node) +{ + ir_node *jumpblock = get_irn_link(node); + assert(jumpblock != NULL); + + mips_emit_block_label(env, jumpblock); +} + /************************************************************************ * ____ _ _ _ _ * * / ___|_ _(_) |_ ___| |__ | |_ _ _ __ ___ _ __ * @@ -546,7 +487,7 @@ const char* mips_get_jumptbl_label(const ir_node* switchjmp) * 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, FILE* F) { +void emit_mips_jump_table(mips_emit_env_t *env, const ir_node *irn) { int lastval, i, i2, pn; jmp_tbl_t tbl; ir_node *proj; @@ -583,17 +524,26 @@ void emit_mips_jump_table(const ir_node *irn, FILE* F) { /* sort the branches by their number */ qsort(tbl.branches, tbl.num_branches, sizeof(tbl.branches[0]), mips_cmp_branch_t); - fprintf(F, "%s:\n", mips_get_jumptbl_label(irn)); + be_emit_string(env->emit, mips_get_jumptbl_label(irn)); + be_emit_cstring(env->emit, ":\n"); + be_emit_write_line(env->emit); 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) { - fprintf(F, "\t.word %s\n", get_id_str(attr->symconst_id)); + be_emit_cstring(env->emit, "\t.word "); + be_emit_ident(env->emit, attr->symconst_id); + be_emit_char(env->emit, '\n'); + be_emit_write_line(env->emit); } - fprintf(F, "\t.word %s\n", mips_get_block_label(branch->target)); + be_emit_cstring(env->emit, "\t.word "); + mips_emit_block_label(env, branch->target); + be_emit_char(env->emit, '\n'); + be_emit_write_line(env->emit); + lastval = branch->value; } @@ -603,15 +553,20 @@ void emit_mips_jump_table(const ir_node *irn, FILE* F) { free(tbl.branches); } -static void dump_jump_tables(ir_node* node, void *env) +static +void dump_jump_tables(ir_node* node, void *data) { - FILE* F = (FILE*) env; + mips_emit_env_t *env = data; // emit jump tables if(is_mips_SwitchJump(node)) { - fprintf(F, ".data\n"); - emit_mips_jump_table(node, F); - fprintf(F, ".text\n"); + be_emit_cstring(env->emit, ".data\n"); + be_emit_write_line(env->emit); + + emit_mips_jump_table(env, node); + + be_emit_cstring(env->emit, ".text\n"); + be_emit_write_line(env->emit); } } @@ -666,30 +621,21 @@ void mips_register_emitters(void) op_Cond->ops.generic = (op_func) mips_emit_this_shouldnt_happen; } -typedef void (*emit_func) (const ir_node *, mips_emit_env_t *); +typedef void (*emit_func) (mips_emit_env_t *, const ir_node *); /** * Emits assembly for a single node */ -static void mips_emit_node(ir_node *irn, mips_emit_env_t* env) +static void mips_emit_node(mips_emit_env_t *env, const ir_node *node) { - mips_emit_env_t *emit_env = env; - FILE *F = emit_env->out; - ir_op *op = get_irn_op(irn); - DEBUG_ONLY(firm_dbg_module_t *mod = emit_env->mod;) - - DBG((mod, LEVEL_1, "emitting code for %+F\n", irn)); + ir_op *op = get_irn_op(node); if (op->ops.generic) { emit_func emit = (emit_func) op->ops.generic; - (*emit) (irn, env); - -#if 0 - if(emit != (emit_func) mips_emit_nothing) - mips_emit_nops(F, 5); -#endif + (*emit) (env, node); } else { - ir_fprintf(F, "\t\t\t\t\t# %+F\n", irn); + be_emit_cstring(env->emit, "\t/* TODO */"); + be_emit_finish_line_gas(env->emit, node); } } @@ -697,54 +643,76 @@ static void mips_emit_node(ir_node *irn, mips_emit_env_t* env) * Walks over the nodes in a block connected by scheduling edges * and emits code for each node. */ -void mips_gen_block(ir_node *block, void *env) +void mips_gen_block(mips_emit_env_t *env, ir_node *block) { - FILE *F = ((mips_emit_env_t *)env)->out; - ir_node *irn; + ir_node *node; if (! is_Block(block)) return; - fprintf(F, "%s:\n", mips_get_block_label(block)); - sched_foreach(block, irn) { - mips_emit_node(irn, env); + mips_emit_block_label(env, block); + be_emit_cstring(env->emit, ":\n"); + be_emit_write_line(env->emit); + + sched_foreach(block, node) { + mips_emit_node(env, node); } - fprintf(F, "\n"); + + be_emit_char(env->emit, '\n'); + be_emit_write_line(env->emit); } /** * Emits code for function start. */ -void mips_emit_start(FILE *F, ir_graph *irg) +void mips_emit_func_prolog(mips_emit_env_t *env, ir_graph *irg) { - const char *irg_name = get_entity_name(get_irg_entity(irg)); + ident *irg_ident = get_entity_ident(get_irg_entity(irg)); + be_emit_env_t *eenv = env->emit; // dump jump tables - irg_walk_graph(irg, NULL, dump_jump_tables, F); + irg_walk_graph(irg, NULL, dump_jump_tables, env); + + be_emit_write_line(eenv); + be_gas_emit_switch_section(eenv, GAS_SECTION_TEXT); + + be_emit_cstring(eenv, "\t.balign\t4\n"); + + be_emit_cstring(eenv, "\t.global\t") + be_emit_ident(eenv, irg_ident); + be_emit_char(eenv, '\n'); - fprintf(F, "\n\n"); - fprintf(F, "\t.balign\t4\n"); - fprintf(F, "\t.global\t%s\n", irg_name); - fprintf(F, "\t.set\tnomips16\n"); - fprintf(F, "\t.ent\t%s\n", irg_name); - fprintf(F, "%s:\n", irg_name); - fprintf(F, "\t.frame\t$fp, 24, $ra\n"); - fprintf(F, "\t.mask\t0xc0000000, -4\n"); - fprintf(F, "\t.fmask\t0x00000000, 0\n"); + be_emit_cstring(eenv, "\t.set\tnomips16\n"); + + be_emit_cstring(eenv, "\t.ent\t"); + be_emit_ident(eenv, irg_ident); + be_emit_char(eenv, '\n'); + + be_emit_ident(eenv, irg_ident); + be_emit_cstring(eenv, ":\n"); + + be_emit_cstring(eenv, "\t.frame\t$fp, 24, $ra\n"); + be_emit_cstring(eenv, "\t.mask\t0xc0000000, -4\n"); + be_emit_cstring(eenv, "\t.fmask\t0x00000000, 0\n"); + + be_emit_write_line(eenv); } /** * Emits code for function end */ -void mips_emit_end(FILE *F, ir_graph *irg) +void mips_emit_func_epilog(mips_emit_env_t *env, ir_graph *irg) { - const char *irg_name = get_entity_name(get_irg_entity(irg)); - fprintf(F, "\t.end\t%s\n", irg_name); + ident *irg_ident = get_entity_ident(get_irg_entity(irg)); + + be_emit_cstring(env->emit, "\t.end\t"); + be_emit_ident(env->emit, irg_ident); + be_emit_char(env->emit, '\n'); + be_emit_write_line(env->emit); } /** * Sets labels for control flow nodes (jump target) - * TODO: Jump optimization */ void mips_gen_labels(ir_node *block, void *env) { @@ -760,29 +728,33 @@ void mips_gen_labels(ir_node *block, void *env) /** * Main driver */ -void mips_gen_routine(FILE *F, ir_graph *irg, const mips_code_gen_t *cg) +void mips_gen_routine(mips_code_gen_t *cg, ir_graph *irg) { - mips_emit_env_t emit_env; + mips_emit_env_t env; int i, n; - emit_env.out = F; - emit_env.arch_env = cg->arch_env; - emit_env.cg = cg; - FIRM_DBG_REGISTER(emit_env.mod, "firm.be.mips.emit"); + env.isa = (mips_isa_t*) cg->arch_env->isa; + env.emit = &env.isa->emit; + env.arch_env = cg->arch_env; + env.cg = cg; - /* set the global arch_env (needed by print hooks) */ - arch_env = cg->arch_env; + mips_register_emitters(); - irg_block_walk_graph(irg, mips_gen_labels, NULL, &emit_env); - mips_emit_start(F, irg); -// irg_walk_blkwise_graph(irg, NULL, mips_gen_block, &emit_env); + irg_block_walk_graph(irg, mips_gen_labels, NULL, &env); + + mips_emit_func_prolog(&env, irg); dump_ir_block_graph_sched(irg, "-kaputtelist"); for (i = 0, n = mips_get_sched_n_blocks(cg); i < n; ++i) { ir_node *block = mips_get_sched_block(cg, i); - mips_gen_block(block, &emit_env); + mips_gen_block(&env, block); } - mips_emit_end(F, irg); + mips_emit_func_epilog(&env, irg); +} + +void mips_init_emitter(void) +{ + FIRM_DBG_REGISTER(dbg, "firm.be.mips.emitter"); } diff --git a/ir/be/mips/mips_emitter.h b/ir/be/mips/mips_emitter.h index 7ff5e387f..a7844a0c0 100644 --- a/ir/be/mips/mips_emitter.h +++ b/ir/be/mips/mips_emitter.h @@ -17,32 +17,43 @@ * PURPOSE. */ -#ifndef _mips_EMITTER_H_ -#define _mips_EMITTER_H_ +/** + * @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 "irargs_t.h" // this also inlucdes #include "irnode.h" -#include "debug.h" -#include "../bearch_t.h" +#include "../bearch.h" +#include "../beemitter.h" #include "bearch_mips_t.h" -typedef struct _mips_emit_env_t { - FILE *out; - const arch_env_t *arch_env; +typedef struct mips_emit_env_t mips_emit_env_t; + +struct mips_emit_env_t { + be_emit_env_t *emit; + const arch_env_t *arch_env; const mips_code_gen_t *cg; - DEBUG_ONLY(firm_dbg_module_t *mod;) -} mips_emit_env_t; + mips_isa_t *isa; +}; -const lc_arg_env_t *mips_get_arg_env(void); +void mips_emit_source_register(mips_emit_env_t *env, const ir_node *node, int pos); +void mips_emit_dest_register(mips_emit_env_t *env, const ir_node *node, int pos); +void mips_emit_immediate(mips_emit_env_t *env, const ir_node *node); +void mips_emit_jump_target(mips_emit_env_t *env, const ir_node *node); +void mips_emit_jump_target_proj(mips_emit_env_t *env, const ir_node *node, + int pn); void equalize_dest_src(FILE *F, ir_node *n); int get_mips_reg_nr(ir_node *irn, int posi, int in_out); const char *get_mips_in_reg_name(ir_node *irn, int pos); -void mips_gen_routine(FILE *F, ir_graph *irg, const mips_code_gen_t *cg); void mips_register_emitters(void); ir_node *mips_get_jump_block(const ir_node* node, int projn); @@ -51,4 +62,6 @@ 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); -#endif /* _mips_EMITTER_H_ */ +void mips_gen_routine(mips_code_gen_t *cg, ir_graph *irg); + +#endif diff --git a/ir/be/mips/mips_gen_decls.c b/ir/be/mips/mips_gen_decls.c deleted file mode 100644 index 0957fb363..000000000 --- a/ir/be/mips/mips_gen_decls.c +++ /dev/null @@ -1,578 +0,0 @@ -/* - * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. - * - * This file is part of libFirm. - * - * This file may be distributed and/or modified under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation and appearing in the file LICENSE.GPL included in the - * packaging of this file. - * - * Licensees holding valid libFirm Professional Edition licenses may use - * this file in accordance with the libFirm Commercial License. - * Agreement provided with the Software. - * - * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE - * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE. - */ - -/** - * Dumps global variables and constants as mips assembler. - * @date 14.02.2006 - * @version $Id$ - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include - -#include "xmalloc.h" -#include "obst.h" - -#include "tv.h" -#include "irnode.h" -#include "entity.h" -#include "irprog.h" - -#include "mips_gen_decls.h" - -/************************************************************************/ - -/* - * returns the highest bit value - */ -static unsigned highest_bit(unsigned v) -{ - int res = -1; - - if (v >= (1U << 16U)) { - res += 16; - v >>= 16; - } - if (v >= (1U << 8U)) { - res += 8; - v >>= 8; - } - if (v >= (1U << 4U)) { - res += 4; - v >>= 4; - } - if (v >= (1U << 2U)) { - res += 2; - v >>= 2; - } - if (v >= (1U << 1U)) { - res += 1; - v >>= 1; - } - if (v >= 1) - res += 1; - - return res; -} - -/* - * output the alignment - */ -static void mips_dump_align(struct obstack *obst, int align) -{ - int h = highest_bit(align); - - if ((1 << h) < align) - ++h; - align = (1 << h); - - if (align > 1) - obstack_printf(obst, "\t.align %d\n", align); -} - -static void dump_arith_tarval(struct obstack *obst, tarval *tv, int bytes) -{ - switch (bytes) { - - case 1: - obstack_printf(obst, "0x%02x", get_tarval_sub_bits(tv, 0)); - break; - - case 2: - obstack_printf(obst, "0x%02x%02x", get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0)); - break; - - case 4: - obstack_printf(obst, "0x%02x%02x%02x%02x", - get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0)); - break; - - case 8: - obstack_printf(obst, "0x%02x%02x%02x%02x%02x%02x%02x%02x", - get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4), - get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0)); - break; - - case 10: - case 12: - break; - - default: - fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes); - assert(0); - } -} - -/* - * dump an atomic value - */ -static void do_dump_atomic_init(struct obstack *obst, ir_node *init) -{ - ir_mode *mode = get_irn_mode(init); - int bytes = get_mode_size_bytes(mode); - tarval *tv; - - switch (get_irn_opcode(init)) { - - case iro_Cast: - do_dump_atomic_init(obst, get_Cast_op(init)); - return; - - case iro_Conv: - do_dump_atomic_init(obst, get_Conv_op(init)); - return; - - case iro_Const: - tv = get_Const_tarval(init); - - /* beware of old stuff */ - assert(! mode_is_reference(mode)); - - /* it's a arithmetic value */ - dump_arith_tarval(obst, tv, bytes); - return; - - case iro_SymConst: - switch (get_SymConst_kind(init)) { - case symconst_addr_name: - obstack_printf(obst, "%s", get_id_str(get_SymConst_name(init))); - break; - - case symconst_addr_ent: - obstack_printf(obst, "%s", get_entity_ld_name(get_SymConst_entity(init))); - break; - - case symconst_ofs_ent: - obstack_printf(obst, "%d", get_entity_offset(get_SymConst_entity(init))); - break; - - case symconst_type_size: - obstack_printf(obst, "%d", get_type_size_bytes(get_SymConst_type(init))); - break; - - case symconst_type_align: - obstack_printf(obst, "%d", get_type_alignment_bytes(get_SymConst_type(init))); - break; - - case symconst_enum_const: - tv = get_enumeration_value(get_SymConst_enum(init)); - dump_arith_tarval(obst, tv, bytes); - break; - - default: - assert(0 && "dump_atomic_init(): don't know how to init from this SymConst"); - } - return; - - case iro_Add: - do_dump_atomic_init(obst, get_Add_left(init)); - obstack_printf(obst, " + "); - do_dump_atomic_init(obst, get_Add_right(init)); - return; - - case iro_Sub: - do_dump_atomic_init(obst, get_Sub_left(init)); - obstack_printf(obst, " - "); - do_dump_atomic_init(obst, get_Sub_right(init)); - return; - - case iro_Mul: - do_dump_atomic_init(obst, get_Mul_left(init)); - obstack_printf(obst, " * "); - do_dump_atomic_init(obst, get_Mul_right(init)); - return; - - default: - assert(0 && "dump_atomic_init(): unknown IR-node"); - } -} - -/* - * dump an atomic value - */ -static void dump_atomic_init(struct obstack *obst, ir_node *init) -{ - ir_mode *mode = get_irn_mode(init); - int bytes = get_mode_size_bytes(mode); - - switch (bytes) { - - case 1: - obstack_printf(obst, "\t.byte\t"); - break; - - case 2: - obstack_printf(obst, "\t.half\t"); - break; - - case 4: - obstack_printf(obst, "\t.word\t"); - break; - - default: - fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes); - assert(0); - } - - do_dump_atomic_init(obst, init); - obstack_printf(obst, "\n"); -} - -/************************************************************************/ -/* Routines to dump global variables */ -/************************************************************************/ - -/** - * Determine if an entity is a string constant - * @param ent The entity - * @return 1 if it is a string constant, 0 otherwise - */ -static int ent_is_string_const(ir_entity *ent) -{ - int res = 0; - ir_type *ty; - - ty = get_entity_type(ent); - - /* if it's an array */ - if (is_Array_type(ty)) { - ir_type *elm_ty = get_array_element_type(ty); - - /* and the array's element type is primitive */ - if (is_Primitive_type(elm_ty)) { - ir_mode *mode = get_type_mode(elm_ty); - - /* - * and the mode of the element type is an int of - * the same size as the byte mode - */ - if (mode_is_int(mode) - && get_mode_size_bits(mode) == get_mode_size_bits(mode_Bs)) - { - int i, c, n; - - n = get_compound_ent_n_values(ent); - for (i = 0; i < n; ++i) { - ir_node *irn = get_compound_ent_value(ent, i); - if(get_irn_opcode(irn) != iro_Const) - return 0; - - c = (int) get_tarval_long(get_Const_tarval(irn)); - - if((i < n - 1 && !(isgraph(c) || isspace(c))) - || (i == n - 1 && c != '\0')) - return 0; - } - - res = 1; - } - } - } - - return res; -} - -/** - * Dump a atring constant. - * No checks are made!! - * @param obst The obst to dump on. - * @param ent The entity to dump. - */ -static void dump_string_cst(struct obstack *obst, ir_entity *ent) -{ - int i, n; - - obstack_printf(obst, "\t.asciiz \""); - n = get_compound_ent_n_values(ent); - - for (i = 0; i < n-1; ++i) { - ir_node *irn; - int c; - - irn = get_compound_ent_value(ent, i); - c = (int) get_tarval_long(get_Const_tarval(irn)); - - switch (c) { - case '"' : obstack_printf(obst, "\\\""); break; - case '\n': obstack_printf(obst, "\\n"); break; - case '\r': obstack_printf(obst, "\\r"); break; - case '\t': obstack_printf(obst, "\\t"); break; - default : - if (isprint(c)) - obstack_printf(obst, "%c", c); - else - obstack_printf(obst, "\\%o", c); - break; - } - } - obstack_printf(obst, "\"\n"); -} - -struct arr_info { - int n_elems; - int visit_cnt; - int size; -}; - -/* - * Dumps the initialization of global variables that are not - * "uninitialized". - */ -static void dump_global(struct obstack *rdata_obstack, struct obstack *data_obstack, struct obstack *comm_obstack, ir_entity *ent) -{ - ir_type *ty = get_entity_type(ent); - const char *ld_name = get_entity_ld_name(ent); - int align, h; - struct obstack *obst = data_obstack; - - /* - * FIXME: did NOT work for partly constant values - */ - if (! is_Method_type(ty)) { - ir_variability variability = get_entity_variability(ent); - ir_visibility visibility = get_entity_visibility(ent); - - if (variability == variability_constant) { - /* a constant entity, put it on the rdata */ - obst = rdata_obstack; - } - - /* check, wether it is initialized, if yes create data */ - if (variability != variability_uninitialized) { - if (visibility == visibility_external_visible) { - obstack_printf(obst, ".globl\t%s\n", ld_name); - } - - align = get_type_alignment_bytes(ty); - mips_dump_align(obst, align); - - obstack_printf(obst, "%s:\n", ld_name); - - if (is_atomic_type(ty)) { - if (get_entity_visibility(ent) != visibility_external_allocated) - dump_atomic_init(obst, get_atomic_ent_value(ent)); - } - else { - int i, size = 0; - - if (ent_is_string_const(ent)) { - dump_string_cst(obst, ent); - } - else if (is_Array_type(ty)) { - int filler; - - /* potential spare values should be already included! */ - for (i = 0; i < get_compound_ent_n_values(ent); ++i) { - ir_entity *step = get_compound_ent_value_member(ent, i); - ir_type *stype = get_entity_type(step); - - if (get_type_mode(stype)) { - int align = (get_type_alignment_bits(stype) + 7) >> 3; - int n = size % align; - - if (n > 0) { - obstack_printf(obst, "\t.space\t%d\n", align - n); - size += align - n; - } - } - dump_atomic_init(obst, get_compound_ent_value(ent, i)); - size += get_type_size_bytes(stype); - } - filler = get_type_size_bytes(ty) - size; - - if (filler > 0) - obstack_printf(obst, "\t.space\t%d\n", filler); - } - else if (is_compound_type(ty)) { - ir_node **vals; - int type_size, j; - - /* Compound entities are NOT sorted. - * The sorting strategy used doesn't work for `value' compound fields nor - * for partially_constant entities. - */ - - /* - * in the worst case, every entity allocates one byte, so the type - * size should be equal or bigger the number of fields - */ - type_size = get_type_size_bytes(ty); - vals = xcalloc(type_size, sizeof(*vals)); - - /* collect the values and store them at the offsets */ - for(i = 0; i < get_compound_ent_n_values(ent); ++i) { - int graph_length, aipos, offset; - struct arr_info *ai; - int all_n = 1; - compound_graph_path *path = get_compound_ent_value_path(ent, i); - - /* get the access path to the costant value */ - graph_length = get_compound_graph_path_length(path); - ai = xcalloc(graph_length, sizeof(struct arr_info)); - - /* We wanna know how many arrays are on the path to the entity. We also have to know how - * many elements each array holds to calculate the offset for the entity. */ - for (j = 0; j < graph_length; j++) { - ir_entity *step = get_compound_graph_path_node(path, j); - ir_type *step_type = get_entity_type(step); - int ty_size = (get_type_size_bits(step_type) + 7) >> 3; - int k, n = 0; - - if (is_Array_type(step_type)) - for (k = 0; k < get_array_n_dimensions(step_type); k++) - n += get_tarval_long(get_Const_tarval(get_array_upper_bound(step_type, k))); - if (n) all_n *= n; - ai[j].n_elems = n ? all_n + 1 : 0; - ai[j].visit_cnt = 0; - ai[j].size = ty_size; - } - - aipos = graph_length - 1; - if (aipos) aipos--; - - for (offset = j = 0; j < graph_length; j++) { - ir_entity *step = get_compound_graph_path_node(path, j); - ir_type *step_type = get_entity_type(step); - int ent_ofs = get_entity_offset(step); - int stepsize = 0; - - /* add all positive offsets (= offsets in structs) */ - if (ent_ofs >= 0) offset += ent_ofs; - - if (j == graph_length - 1) { - stepsize = (get_type_size_bits(step_type) + 7) >> 3; - - /* Search the next free position in vals depending on the information from above (ai). */ - while (vals[offset]) { - if (ai[aipos].visit_cnt < ai[aipos].n_elems) { - offset += stepsize; - ai[aipos].visit_cnt++; - } - else - while (aipos >= 0 && ai[aipos].visit_cnt == ai[aipos].n_elems) { - stepsize = ai[aipos--].size; - offset += stepsize; - } - } - - assert(aipos >= 0 && "couldn't store entity"); - vals[offset] = get_compound_ent_value(ent, i); - } - } - - free(ai); - } - - /* now write them sorted */ - for(i = 0; i < type_size; ) { - if (vals[i]) { - dump_atomic_init(obst, vals[i]); - i += (get_mode_size_bytes(get_irn_mode(vals[i]))); - } - else { - /* a gap */ - obstack_printf(obst, "\t.byte\t0\n"); - ++i; - } - } - free(vals); - } - else { - assert(0 && "unsupported type"); - } - } - obstack_printf(obst, "\n"); - } - else if (visibility != visibility_external_allocated) { - if (visibility == visibility_local) { - obstack_printf(comm_obstack, "\t.local\t%s\n", ld_name); - } - - /* calculate the alignment */ - align = get_type_alignment_bytes(ty); - h = highest_bit(align); - - if ((1 << h) < align) - ++h; - align = (1 << h); - - if (align < 1) - align = 1; - - obstack_printf(comm_obstack, "\t.comm\t%s,%d,%d\n", ld_name, (get_type_size_bits(ty) + 7) >> 3, align); - } - } -} - -/* - * Dumps declarations of global variables and the initialization code. - */ -void mips_dump_globals(struct obstack *rdata_obstack, struct obstack *data_obstack, struct obstack *comm_obstack) -{ - ir_type *gt = get_glob_type(); - int i, n = get_class_n_members(gt); - - for (i = 0; i < n; i++) - dump_global(rdata_obstack, data_obstack, comm_obstack, get_class_member(gt, i)); -} - -/************************************************************************/ - -void mips_gen_decls(FILE *out) { - struct obstack rodata, data, comm; - int size; - char *cp; - - obstack_init(&rodata); - obstack_init(&data); - obstack_init(&comm); - - mips_dump_globals(&rodata, &data, &comm); - - size = obstack_object_size(&data); - cp = obstack_finish(&data); - if (size > 0) { - fprintf(out, "\t.data\n"); - fwrite(cp, 1, size, out); - } - - size = obstack_object_size(&rodata); - cp = obstack_finish(&rodata); - if (size > 0) { - fprintf(out, "\t.data\n"); - fwrite(cp, 1, size, out); - } - - size = obstack_object_size(&comm); - cp = obstack_finish(&comm); - if (size > 0) { - fprintf(out, "\t.data\n"); - fwrite(cp, 1, size, out); - } - - obstack_free(&rodata, NULL); - obstack_free(&data, NULL); - obstack_free(&comm, NULL); -} diff --git a/ir/be/mips/mips_gen_decls.h b/ir/be/mips/mips_gen_decls.h deleted file mode 100644 index eb2787993..000000000 --- a/ir/be/mips/mips_gen_decls.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. - * - * This file is part of libFirm. - * - * This file may be distributed and/or modified under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation and appearing in the file LICENSE.GPL included in the - * packaging of this file. - * - * Licensees holding valid libFirm Professional Edition licenses may use - * this file in accordance with the libFirm Commercial License. - * Agreement provided with the Software. - * - * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE - * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE. - */ - -#ifndef _MIPS_GEN_DECLS_H_ -#define _MIPS_GEN_DECLS_H_ - -/** - * Generate all entities. - */ -void mips_gen_decls(FILE *out); - -#endif /* _MIPS_GEN_DECLS_H_ */ diff --git a/ir/be/mips/mips_map_regs.c b/ir/be/mips/mips_map_regs.c index ddfb67b0c..baecdf0c8 100644 --- a/ir/be/mips/mips_map_regs.c +++ b/ir/be/mips/mips_map_regs.c @@ -18,8 +18,10 @@ */ /** - * Register mapping for firm nodes. Stolen from bearch_firm :) - * $Id$ + * @file + * @brief Register mapping for firm nodes. Stolen from bearch_firm :) + * @author Matthias Braun, Mehdi + * @version $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" diff --git a/ir/be/mips/mips_map_regs.h b/ir/be/mips/mips_map_regs.h index 260050ac3..c0eb97418 100644 --- a/ir/be/mips/mips_map_regs.h +++ b/ir/be/mips/mips_map_regs.h @@ -17,8 +17,14 @@ * PURPOSE. */ -#ifndef _mips_MAP_REGS_H_ -#define _mips_MAP_REGS_H_ +/** + * @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" @@ -32,4 +38,4 @@ 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 /* _mips_MAP_REGS_H_ */ +#endif diff --git a/ir/be/mips/mips_new_nodes.c b/ir/be/mips/mips_new_nodes.c index 73762e1db..2f8f1913d 100644 --- a/ir/be/mips/mips_new_nodes.c +++ b/ir/be/mips/mips_new_nodes.c @@ -18,9 +18,12 @@ */ /** - * This file implements the creation of the achitecture specific firm opcodes - * and the coresponding node constructors for the mips assembler irg. - * $Id$ + * @file + * @brief This file implements the creation of the achitecture specific firm + * opcodes and the coresponding node constructors for the mips + * assembler irg. + * @author Matthias Braun, Mehdi + * @version $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" diff --git a/ir/be/mips/mips_new_nodes.h b/ir/be/mips/mips_new_nodes.h index 10c949d89..1d1a45dca 100644 --- a/ir/be/mips/mips_new_nodes.h +++ b/ir/be/mips/mips_new_nodes.h @@ -17,13 +17,14 @@ * PURPOSE. */ -#ifndef _mips_NEW_NODES_H_ -#define _mips_NEW_NODES_H_ - /** - * Function prototypes for the assembler ir node constructors. - * $Id$ + * @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" @@ -129,4 +130,4 @@ void mips_init_opcode_transforms(void); /* Include the generated headers */ #include "gen_mips_new_nodes.h" -#endif /* _mips_NEW_NODES_H_ */ +#endif diff --git a/ir/be/mips/mips_nodes_attr.h b/ir/be/mips/mips_nodes_attr.h index e496487c2..289473af4 100644 --- a/ir/be/mips/mips_nodes_attr.h +++ b/ir/be/mips/mips_nodes_attr.h @@ -17,8 +17,14 @@ * PURPOSE. */ -#ifndef _MIPS_NODES_ATTR_H_ -#define _MIPS_NODES_ATTR_H_ +/** + * @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_t.h" #include "irmode_t.h" @@ -45,4 +51,4 @@ typedef struct _mips_attr_t { const arch_register_t *slots[1]; /**< register slots for assigned registers */ } mips_attr_t; -#endif /* _mips_NODES_ATTR_H_ */ +#endif diff --git a/ir/be/mips/mips_scheduler.c b/ir/be/mips/mips_scheduler.c index 435b6cf3f..635a959ba 100644 --- a/ir/be/mips/mips_scheduler.c +++ b/ir/be/mips/mips_scheduler.c @@ -17,8 +17,12 @@ * PURPOSE. */ -/* Mips implementation of list scheduler selector */ -/* $Id$ */ +/** + * @file + * @brief Mips implementation of list scheduler selector + * @author Matthias Braun, Mehdi + * @version $Id$ + */ #ifdef HAVE_CONFIG_H #include "config.h" #endif diff --git a/ir/be/mips/mips_spec.pl b/ir/be/mips/mips_spec.pl index 16258eac5..31b633331 100644 --- a/ir/be/mips/mips_spec.pl +++ b/ir/be/mips/mips_spec.pl @@ -5,10 +5,7 @@ # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...) $arch = "mips"; - -# this strings mark the beginning and the end of a comment in emit -$comment_string = "#"; -$comment_string_end = ""; +$new_emit_syntax = 1; # The node description is done as a perl hash initializer with the # following structure: @@ -128,6 +125,19 @@ $comment_string_end = ""; ], ); # %reg_classes +%emit_templates = ( + S1 => "${arch}_emit_source_register(env, node, 0);", + S2 => "${arch}_emit_source_register(env, node, 1);", + S3 => "${arch}_emit_source_register(env, node, 2);", + D1 => "${arch}_emit_dest_register(env, node, 0);", + D2 => "${arch}_emit_dest_register(env, node, 1);", + D3 => "${arch}_emit_dest_register(env, node, 2);", + C => "${arch}_emit_immediate(env, node);", + JumpTarget => "${arch}_emit_jump_target(env, node);", + JumpTarget1 => "${arch}_emit_jump_target_proj(env, node, 1);", +); + + #--------------------------------------------------# # _ # # (_) # @@ -238,10 +248,10 @@ ori => { sl => { reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, emit => ' - if (mode_is_signed(get_irn_mode(n))) { -2. sal %D1, %S1, %S2 + if (mode_is_signed(get_irn_mode(node))) { + . sal %D1, %S1, %S2 } else { -2. sll %D1, %S1, %S2 + . sll %D1, %S1, %S2 } ', mode => "mode_Iu", @@ -250,10 +260,10 @@ sl => { sli => { reg_req => { in => [ "gp" ], out => [ "gp" ] }, emit => ' - if (mode_is_signed(get_irn_mode(n))) { -2. sal %D1, %S1, %C + if (mode_is_signed(get_irn_mode(node))) { + . sal %D1, %S1, %C } else { -2. sll %D1, %S1, %C + . sll %D1, %S1, %C } ', mode => "mode_Iu", @@ -275,10 +285,10 @@ srai => { sr => { reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, emit => ' - if (mode_is_signed(get_irn_mode(n))) { -2. sra %D1, %S1, %S2 + if (mode_is_signed(get_irn_mode(node))) { + . sra %D1, %S1, %S2 } else { -2. srl %D1, %S1, %S2 + . srl %D1, %S1, %S2 } ', mode => "mode_Iu", @@ -287,10 +297,10 @@ sr => { sri => { reg_req => { in => [ "gp" ], out => [ "gp" ] }, emit => ' - if (mode_is_signed(get_irn_mode(n))) { -2. sra %D1, %S1, %C + if (mode_is_signed(get_irn_mode(node))) { + . sra %D1, %S1, %C } else { -2. srl %D1, %S1, %C + . srl %D1, %S1, %C } ', mode => "mode_Iu" @@ -396,11 +406,11 @@ zero => { slt => { reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, emit => ' - if (mode_is_signed(get_irn_mode(n))) { -2. slt %D1, %S1, %S2 + if (mode_is_signed(get_irn_mode(node))) { + . slt %D1, %S1, %S2 } else { -2. sltu %D1, %S1, %S2 + . sltu %D1, %S1, %S2 } ', mode => "mode_Iu", @@ -409,11 +419,11 @@ slt => { slti => { reg_req => { in => [ "gp" ], out => [ "gp" ] }, emit => ' - if (mode_is_signed(get_irn_mode(n))) { -2. slti %D1, %S1, %C + if (mode_is_signed(get_irn_mode(node))) { + . slti %D1, %S1, %C } else { -2. sltiu %D1, %S1, %C + . sltiu %D1, %S1, %C } ', cmp_attr => 'return attr_a->tv != attr_b->tv;', @@ -424,56 +434,28 @@ beq => { op_flags => "X|Y", # TxT -> TxX reg_req => { in => [ "gp", "gp" ], out => [ "in_r0", "none" ] }, - emit => ' - ir_node *jumpblock = mips_get_jump_block(n, 1); - assert(jumpblock != NULL); - - (void) cmd_buf; - (void) cmnt_buf; - lc_efprintf(arg_env, F, "\tbeq %1S, %2S, BLOCK_%d\n", n, n, get_irn_node_nr(jumpblock)); -' + emit => '. beq %S1, %S2, %JumpTarget1' }, bne => { op_flags => "X|Y", # TxT -> TxX reg_req => { in => [ "gp", "gp" ], out => [ "in_r0", "none" ] }, - emit => ' - ir_node *jumpblock = mips_get_jump_block(n, 1); - assert(jumpblock != NULL); - - (void) cmd_buf; - (void) cmnt_buf; - lc_efprintf(arg_env, F, "\tbne %1S, %2S, BLOCK_%d\n", n, n, get_irn_node_nr(jumpblock)); -' + emit => '. bne %S1, %S2, %JumpTarget1' }, bgtz => { op_flags => "X|Y", # TxT -> TxX reg_req => { in => [ "gp" ], out => [ "in_r0", "none" ] }, - emit => ' - ir_node *jumpblock = mips_get_jump_block(n, 1); - assert(jumpblock != NULL); - - (void) cmd_buf; - (void) cmnt_buf; - lc_efprintf(arg_env, F, "\tbgtz %1S, BLOCK_%d\n", n, get_irn_node_nr(jumpblock)); -' + emit => '. bgtz %S1, %JumpTarget1' }, blez => { op_flags => "X|Y", # TxT -> TxX reg_req => { in => [ "gp" ], out => [ "in_r0", "none" ] }, - emit => ' - ir_node *jumpblock = mips_get_jump_block(n, 1); - assert(jumpblock != NULL); - - (void) cmd_buf; - (void) cmnt_buf; - lc_efprintf(arg_env, F, "\tblez %1S, BLOCK_%d\n", n, get_irn_node_nr(jumpblock)); -' + emit => '. blez %S1, %JumpTarget1' }, j => { @@ -486,21 +468,14 @@ b => { op_flags => "X", # -> X reg_req => { in => [ ], out => [ "none" ] }, - emit => ' - ir_node *jumpblock = get_irn_link(n); - assert(jumpblock != NULL); - - (void) cmd_buf; - (void) cmnt_buf; - lc_efprintf(arg_env, F, "\tb BLOCK_%d\t\t\t# mips_b\n", get_irn_node_nr(jumpblock)); -' + emit => '. b %JumpTarget' }, fallthrough => { op_flags => "X", # -> X reg_req => { in => [ ], out => [ "none" ] }, - emit => '. # fallthrough' + emit => '. /* fallthrough to %JumpTarget */' }, SwitchJump => { @@ -520,7 +495,7 @@ SwitchJump => { load_r => { reg_req => { in => [ "none", "gp" ], out => [ "none", "none", "gp" ] }, emit => ' - mips_attr_t* attr = get_mips_attr(n); + mips_attr_t* attr = get_mips_attr(node); ir_mode *mode; mode = attr->modes.load_store_mode; @@ -528,20 +503,20 @@ load_r => { switch (get_mode_size_bits(mode)) { case 8: if (mode_is_signed(mode)) { -3. lb %D3, %C(%S2) + . lb %D3, %C(%S2) } else { -3. lbu %D3, %C(%S2) + . lbu %D3, %C(%S2) } break; case 16: if (mode_is_signed(mode)) { -3. lh %D3, %C(%S2) + . lh %D3, %C(%S2) } else { -3. lhu %D3, %C(%S2) + . lhu %D3, %C(%S2) } break; case 32: -2. lw %D3, %C(%S2) + . lw %D3, %C(%S2) break; default: assert(! "Only 8, 16 and 32 bit loads supported"); @@ -562,7 +537,7 @@ load_r => { store_r => { reg_req => { in => [ "none", "gp", "gp" ], out => [ "none", "none" ] }, emit => ' - mips_attr_t* attr = get_mips_attr(n); + mips_attr_t* attr = get_mips_attr(node); ir_mode* mode; mode = attr->modes.load_store_mode; @@ -570,14 +545,14 @@ store_r => { switch (get_mode_size_bits(mode)) { case 8: if (mode_is_signed(mode)) -2. sb %S3, %C(%S2) + . sb %S3, %C(%S2) break; case 16: if (mode_is_signed(mode)) -2. sh %S3, %C(%S2) + . sh %S3, %C(%S2) break; case 32: -2. sw %S3, %C(%S2) + . sw %S3, %C(%S2) break; default: assert(! "Only 8, 16 and 32 bit stores supported"); @@ -590,20 +565,20 @@ store_r => { store_i => { reg_req => { in => [ "none", "none", "gp" ], out => [ "none", "none" ] }, emit => ' - mips_attr_t* attr = get_mips_attr(n); + mips_attr_t* attr = get_mips_attr(node); ir_mode *mode; mode = attr->modes.load_store_mode; switch (get_mode_size_bits(mode)) { case 8: -2. sb %S3, %C + . sb %S3, %C break; case 16: -2. sh %S3, %C + . sh %S3, %C break; case 32: -2. sw %S3, %C + . sw %S3, %C break; default: assert(! "Only 8, 16 and 32 bit stores supported"); diff --git a/ir/be/mips/mips_transform.c b/ir/be/mips/mips_transform.c index 10c38c3f2..5714e57c9 100644 --- a/ir/be/mips/mips_transform.c +++ b/ir/be/mips/mips_transform.c @@ -17,9 +17,12 @@ * PURPOSE. */ -/* The codegenrator (transform FIRM into mips FIRM */ -/* $Id$ */ - +/** + * @file + * @brief The codegenrator (transform FIRM into mips FIRM + * @author Matthias Braun, Mehdi + * @version $Id$ + */ #ifdef HAVE_CONFIG_H #include "config.h" #endif diff --git a/ir/be/mips/mips_transform.h b/ir/be/mips/mips_transform.h index be218c1d8..fa9b8f3ee 100644 --- a/ir/be/mips/mips_transform.h +++ b/ir/be/mips/mips_transform.h @@ -17,8 +17,14 @@ * PURPOSE. */ -#ifndef _MIPS_TRANSFORM_H_ -#define _MIPS_TRANSFORM_H_ +/** + * @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. @@ -34,4 +40,4 @@ void mips_pre_transform_node(ir_node *node, void *env); void mips_transform_node(ir_node *node, void *env); void mips_after_ra_walker(ir_node *node, void *env); -#endif /* _MIPS_TRANSFORM_H_ */ +#endif diff --git a/ir/be/mips/mips_util.h b/ir/be/mips/mips_util.h index 10bfdfb80..d1f6b2bb4 100644 --- a/ir/be/mips/mips_util.h +++ b/ir/be/mips/mips_util.h @@ -17,9 +17,15 @@ * PURPOSE. */ -#ifndef _MIPS_UTIL_H_ -#define _MIPS_UTIL_H_ +/** + * @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) { assert( (!mode_is_float(mode)) && "floating point not supported (yet)"); } -#endif /* _MIPS_UTIL_H_ */ +#endif -- 2.20.1