/**
* @file
* @brief The main TEMPLATE backend driver file.
- * @version $Id$
*/
#include "config.h"
+#include "bearch_TEMPLATE_t.h"
+
#include "irgwalk.h"
#include "irprog.h"
#include "irprintf.h"
#include "ircons.h"
#include "irgmod.h"
+#include "lower_calls.h"
+#include "lower_builtins.h"
#include "bitset.h"
#include "debug.h"
#include "be.h"
-#include "../bearch.h"
-#include "../benode.h"
-#include "../belower.h"
-#include "../besched.h"
-#include "../beabi.h"
-#include "../bemodule.h"
-#include "../begnuas.h"
-#include "../belistsched.h"
-
-#include "bearch_TEMPLATE_t.h"
+#include "bearch.h"
+#include "benode.h"
+#include "belower.h"
+#include "besched.h"
+#include "beabi.h"
+#include "bemodule.h"
+#include "begnuas.h"
+#include "belistsched.h"
+#include "bestack.h"
+#include "bespillutil.h"
#include "TEMPLATE_new_nodes.h"
#include "gen_TEMPLATE_regalloc_if.h"
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
-static arch_irn_class_t TEMPLATE_classify(const ir_node *irn)
-{
- (void) irn;
- return arch_irn_class_none;
-}
-
static ir_entity *TEMPLATE_get_frame_entity(const ir_node *node)
{
(void) node;
/* fill register allocator interface */
static const arch_irn_ops_t TEMPLATE_irn_ops = {
- TEMPLATE_classify,
TEMPLATE_get_frame_entity,
TEMPLATE_set_frame_offset,
TEMPLATE_get_sp_bias,
*/
static void TEMPLATE_finish_irg(ir_graph *irg)
{
- (void) irg;
+ /* fix stack entity offsets */
+ be_abi_fix_stack_nodes(irg);
+ be_abi_fix_stack_bias(irg);
}
/* Some stuff you need to do after scheduling but before register allocation */
}
-static void TEMPLATE_after_ra(ir_graph *irg)
-{
- (void) irg;
- /* Some stuff you need to do immediatly after register allocation */
-}
-
static void TEMPLATE_init_graph(ir_graph *irg)
{
(void) irg;
},
};
-/**
- * Initializes the backend ISA
- */
-static arch_env_t *TEMPLATE_init(FILE *outfile)
+static void TEMPLATE_init(void)
{
- TEMPLATE_isa_t *isa = XMALLOC(TEMPLATE_isa_t);
- memcpy(isa, &TEMPLATE_isa_template, sizeof(*isa));
-
- be_emit_init(outfile);
-
TEMPLATE_register_init();
TEMPLATE_create_opcodes(&TEMPLATE_irn_ops);
+}
+
+static void TEMPLATE_finish(void)
+{
+ TEMPLATE_free_opcodes();
+}
+
+static arch_env_t *TEMPLATE_begin_codegeneration(const be_main_env_t *env)
+{
+ TEMPLATE_isa_t *isa = XMALLOC(TEMPLATE_isa_t);
+ *isa = TEMPLATE_isa_template;
+
+ be_emit_init(env->file_handle);
+ be_gas_begin_compilation_unit(env);
return &isa->base;
}
/**
* Closes the output file and frees the ISA structure.
*/
-static void TEMPLATE_done(void *self)
+static void TEMPLATE_end_codegeneration(void *self)
{
TEMPLATE_isa_t *isa = (TEMPLATE_isa_t*)self;
/* emit now all global declarations */
- be_gas_emit_decls(isa->base.main_env);
+ be_gas_end_compilation_unit(isa->base.main_env);
be_emit_exit();
free(self);
}
-/**
- * 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 *TEMPLATE_get_reg_class_for_mode(const ir_mode *mode)
-{
- if (mode_is_float(mode))
- return &TEMPLATE_reg_classes[CLASS_TEMPLATE_fp];
- else
- return &TEMPLATE_reg_classes[CLASS_TEMPLATE_gp];
-}
-
/**
* Get the between type for that call.
* @param self The callback object.
* @param method_type The type of the method (procedure) in question.
* @param abi The abi object to be modified
*/
-static void TEMPLATE_get_call_abi(const void *self, ir_type *method_type,
- be_abi_call_t *abi)
+static void TEMPLATE_get_call_abi(ir_type *method_type, be_abi_call_t *abi)
{
ir_type *tp;
ir_mode *mode;
int i, n = get_method_n_params(method_type);
be_abi_call_flags_t call_flags;
- (void) self;
/* set abi flags for calls */
- call_flags.bits.left_to_right = 0;
- call_flags.bits.store_args_sequential = 1;
- call_flags.bits.try_omit_fp = 1;
- call_flags.bits.fp_free = 0;
- call_flags.bits.call_has_imm = 1;
+ call_flags.bits.call_has_imm = true;
/* set stack parameter passing style */
be_abi_call_set_flags(abi, call_flags, &TEMPLATE_abi_callbacks);
}
}
-/**
- * Returns the necessary byte alignment for storing a register of given class.
- */
-static int TEMPLATE_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 void TEMPLATE_lower_for_target(void)
{
- lower_params_t params = {
- 4, /* def_ptr_alignment */
- LF_COMPOUND_RETURN | LF_RETURN_HIDDEN, /* flags */
- ADD_HIDDEN_ALWAYS_IN_FRONT, /* hidden_params */
- NULL, /* find pointer type */
- NULL, /* ret_compound_in_regs */
- };
+ lower_builtins(0, NULL);
/* lower compound param handling */
- lower_calls_with_compounds(¶ms);
+ lower_calls_with_compounds(LF_RETURN_HIDDEN);
}
static int TEMPLATE_is_mux_allowed(ir_node *sel, ir_node *mux_false,
0, /* no inline assembly */
0, /* no support for Rotl nodes */
0, /* 0: little-endian, 1: big-endian */
+ 1, /* modulo shift efficient */
+ 0, /* non-modulo shift efficient */
NULL, /* architecture dependent settings, will be set later */
TEMPLATE_is_mux_allowed, /* parameter for if conversion */
+ 32, /* machine size - a 32bit CPU */
NULL, /* float arithmetic mode */
+ NULL, /* long long type */
+ NULL, /* unsigned long long type */
+ NULL, /* long double type */
0, /* no trampoline support: size 0 */
0, /* no trampoline support: align 0 */
NULL, /* no trampoline support: no trampoline builder */
return &p;
}
-static ir_graph **TEMPLATE_get_backend_irg_list(const void *self,
- ir_graph ***irgs)
-{
- (void) self;
- (void) irgs;
- return NULL;
-}
-
static asm_constraint_flags_t TEMPLATE_parse_asm_constraint(const char **c)
{
(void) c;
return 0;
}
+/**
+ * Check if the given register is callee or caller save.
+ */
+static int TEMPLATE_register_saved_by(const arch_register_t *reg, int callee)
+{
+ if (callee) {
+ /* check for callee saved */
+ if (reg->reg_class == &TEMPLATE_reg_classes[CLASS_TEMPLATE_gp]) {
+ switch (reg->index) {
+ case REG_GP_R7:
+ case REG_GP_R8:
+ case REG_GP_R9:
+ case REG_GP_R10:
+ case REG_GP_R11:
+ case REG_GP_R12:
+ case REG_GP_R13:
+ return 1;
+ default:
+ return 0;
+ }
+ }
+ } else {
+ /* check for caller saved */
+ if (reg->reg_class == &TEMPLATE_reg_classes[CLASS_TEMPLATE_gp]) {
+ switch (reg->index) {
+ case REG_GP_R0:
+ case REG_GP_R1:
+ case REG_GP_R2:
+ case REG_GP_R3:
+ case REG_GP_R4:
+ case REG_GP_R5:
+ case REG_GP_R6:
+ return 1;
+ default:
+ return 0;
+ }
+ } else if (reg->reg_class == &TEMPLATE_reg_classes[CLASS_TEMPLATE_fp]) {
+ /* all FP registers are caller save */
+ return 1;
+ }
+ }
+ return 0;
+}
+
const arch_isa_if_t TEMPLATE_isa_if = {
TEMPLATE_init,
- TEMPLATE_lower_for_target,
- TEMPLATE_done,
- NULL, /* handle intrinsics */
- TEMPLATE_get_reg_class_for_mode,
- TEMPLATE_get_call_abi,
- TEMPLATE_get_reg_class_alignment,
+ TEMPLATE_finish,
TEMPLATE_get_backend_params,
- TEMPLATE_get_backend_irg_list,
- NULL, /* mark remat */
+ TEMPLATE_lower_for_target,
TEMPLATE_parse_asm_constraint,
TEMPLATE_is_valid_clobber,
+ TEMPLATE_begin_codegeneration,
+ TEMPLATE_end_codegeneration,
TEMPLATE_init_graph,
- NULL, /* get_pic_base */
- NULL, /* before_abi */
+ TEMPLATE_get_call_abi,
+ NULL, /* mark remat */
+ NULL, /* get_pic_base */
+ be_new_spill,
+ be_new_reload,
+ TEMPLATE_register_saved_by,
+
+ NULL, /* handle intrinsics */
+ NULL, /* before_abi */
TEMPLATE_prepare_graph,
TEMPLATE_before_ra,
- TEMPLATE_after_ra,
TEMPLATE_finish_irg,
TEMPLATE_emit_routine,
};
-BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_TEMPLATE);
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_TEMPLATE)
void be_init_arch_TEMPLATE(void)
{
be_register_isa_if("TEMPLATE", &TEMPLATE_isa_if);