Commit 3403745d authored by Hannes Rapp's avatar Hannes Rapp
Browse files

- various updates to sparc backend

- extende beabi so you can specify different registers at the call site
  and the beginning of a called function
- adapt all backends for API changes

[r27390]
parent ece28efe
......@@ -384,12 +384,12 @@ static void TEMPLATE_get_call_abi(const void *self, ir_type *method_type,
for (i = 0; i < n; i++) {
/* TODO: implement register parameter: */
/* reg = get reg for param i; */
/* be_abi_call_param_reg(abi, i, reg); */
/* be_abi_call_param_reg(abi, i, reg, ABI_CONTEXT_BOTH); */
/* default: all parameters on stack */
tp = get_method_param_type(method_type, i);
mode = get_type_mode(tp);
be_abi_call_param_stack(abi, i, mode, 4, 0, 0);
be_abi_call_param_stack(abi, i, mode, 4, 0, 0, ABI_CONTEXT_BOTH);
}
/* TODO: set correct return register */
......@@ -399,7 +399,7 @@ static void TEMPLATE_get_call_abi(const void *self, ir_type *method_type,
mode = get_type_mode(tp);
be_abi_call_res_reg(abi, 0,
mode_is_float(mode) ? &TEMPLATE_fp_regs[REG_F0] : &TEMPLATE_gp_regs[REG_R0]);
mode_is_float(mode) ? &TEMPLATE_fp_regs[REG_F0] : &TEMPLATE_gp_regs[REG_R0], ABI_CONTEXT_BOTH);
}
}
......
......@@ -949,11 +949,11 @@ static void arm_get_call_abi(const void *self, ir_type *method_type, be_abi_call
/* reg = get reg for param i; */
/* be_abi_call_param_reg(abi, i, reg); */
if (i < 4) {
be_abi_call_param_reg(abi, i, arm_get_RegParam_reg(i));
be_abi_call_param_reg(abi, i, arm_get_RegParam_reg(i), ABI_CONTEXT_BOTH);
} else {
tp = get_method_param_type(method_type, i);
mode = get_type_mode(tp);
be_abi_call_param_stack(abi, i, mode, 4, 0, 0);
be_abi_call_param_stack(abi, i, mode, 4, 0, 0, ABI_CONTEXT_BOTH);
}
}
......@@ -974,8 +974,8 @@ static void arm_get_call_abi(const void *self, ir_type *method_type, be_abi_call
assert(!mode_is_float(mode) && "mixed INT, FP results not supported");
be_abi_call_res_reg(abi, 0, &arm_gp_regs[REG_R0]);
be_abi_call_res_reg(abi, 1, &arm_gp_regs[REG_R1]);
be_abi_call_res_reg(abi, 0, &arm_gp_regs[REG_R0], ABI_CONTEXT_BOTH);
be_abi_call_res_reg(abi, 1, &arm_gp_regs[REG_R1], ABI_CONTEXT_BOTH);
} else if (n == 1) {
const arch_register_t *reg;
......@@ -984,7 +984,7 @@ static void arm_get_call_abi(const void *self, ir_type *method_type, be_abi_call
mode = get_type_mode(tp);
reg = mode_is_float(mode) ? &arm_fpa_regs[REG_F0] : &arm_gp_regs[REG_R0];
be_abi_call_res_reg(abi, 0, reg);
be_abi_call_res_reg(abi, 0, reg, ABI_CONTEXT_BOTH);
}
}
......
......@@ -63,6 +63,7 @@ typedef struct _be_abi_call_arg_t {
unsigned is_res : 1; /**< 1: the call argument is a return value. 0: it's a call parameter. */
unsigned in_reg : 1; /**< 1: this argument is transmitted in registers. */
unsigned on_stack : 1; /**< 1: this argument is transmitted on the stack. */
unsigned callee : 1; /**< 1: someone called us. 0: We call another function */
int pos;
const arch_register_t *reg;
......@@ -141,7 +142,7 @@ static int cmp_call_arg(const void *a, const void *b, size_t n)
{
const be_abi_call_arg_t *p = a, *q = b;
(void) n;
return !(p->is_res == q->is_res && p->pos == q->pos);
return !(p->is_res == q->is_res && p->pos == q->pos && p->callee == q->callee);
}
/**
......@@ -150,8 +151,9 @@ static int cmp_call_arg(const void *a, const void *b, size_t n)
* @param call the abi call
* @param is_res true for call results, false for call arguments
* @param pos position of the argument
* @param callee context type - if we are callee or caller
*/
static be_abi_call_arg_t *get_call_arg(be_abi_call_t *call, int is_res, int pos)
static be_abi_call_arg_t *get_call_arg(be_abi_call_t *call, int is_res, int pos, int callee)
{
be_abi_call_arg_t arg;
unsigned hash;
......@@ -159,6 +161,7 @@ static be_abi_call_arg_t *get_call_arg(be_abi_call_t *call, int is_res, int pos)
memset(&arg, 0, sizeof(arg));
arg.is_res = is_res;
arg.pos = pos;
arg.callee = callee;
hash = is_res * 128 + pos;
......@@ -167,23 +170,18 @@ static be_abi_call_arg_t *get_call_arg(be_abi_call_t *call, int is_res, int pos)
/**
* Set an ABI call object argument.
*
* @param call the abi call
* @param is_res true for call results, false for call arguments
* @param pos position of the argument
*/
static be_abi_call_arg_t *create_call_arg(be_abi_call_t *call, int is_res, int pos)
static void remember_call_arg(be_abi_call_arg_t *arg, be_abi_call_t *call, be_abi_context_t context)
{
be_abi_call_arg_t arg;
unsigned hash;
memset(&arg, 0, sizeof(arg));
arg.is_res = is_res;
arg.pos = pos;
hash = is_res * 128 + pos;
return set_insert(call->params, &arg, sizeof(arg), hash);
unsigned hash = arg->is_res * 128 + arg->pos;
if (context & ABI_CONTEXT_CALLEE) {
arg->callee = 1;
set_insert(call->params, arg, sizeof(*arg), hash);
}
if (context & ABI_CONTEXT_CALLER) {
arg->callee = 0;
set_insert(call->params, arg, sizeof(*arg), hash);
}
}
/* Set the flags for a call. */
......@@ -207,29 +205,49 @@ void be_abi_call_set_call_address_reg_class(be_abi_call_t *call, const arch_regi
}
void be_abi_call_param_stack(be_abi_call_t *call, int arg_pos, ir_mode *load_mode, unsigned alignment, unsigned space_before, unsigned space_after)
void be_abi_call_param_stack(be_abi_call_t *call, int arg_pos,
ir_mode *load_mode, unsigned alignment,
unsigned space_before, unsigned space_after,
be_abi_context_t context)
{
be_abi_call_arg_t *arg = create_call_arg(call, 0, arg_pos);
arg->on_stack = 1;
arg->load_mode = load_mode;
arg->alignment = alignment;
arg->space_before = space_before;
arg->space_after = space_after;
be_abi_call_arg_t arg;
memset(&arg, 0, sizeof(arg));
assert(alignment > 0 && "Alignment must be greater than 0");
arg.on_stack = 1;
arg.load_mode = load_mode;
arg.alignment = alignment;
arg.space_before = space_before;
arg.space_after = space_after;
arg.is_res = 0;
arg.pos = arg_pos;
remember_call_arg(&arg, call, context);
}
void be_abi_call_param_reg(be_abi_call_t *call, int arg_pos, const arch_register_t *reg)
void be_abi_call_param_reg(be_abi_call_t *call, int arg_pos, const arch_register_t *reg, be_abi_context_t context)
{
be_abi_call_arg_t *arg = create_call_arg(call, 0, arg_pos);
arg->in_reg = 1;
arg->reg = reg;
be_abi_call_arg_t arg;
memset(&arg, 0, sizeof(arg));
arg.in_reg = 1;
arg.reg = reg;
arg.is_res = 0;
arg.pos = arg_pos;
remember_call_arg(&arg, call, context);
}
void be_abi_call_res_reg(be_abi_call_t *call, int arg_pos, const arch_register_t *reg)
void be_abi_call_res_reg(be_abi_call_t *call, int arg_pos, const arch_register_t *reg, be_abi_context_t context)
{
be_abi_call_arg_t *arg = create_call_arg(call, 1, arg_pos);
arg->in_reg = 1;
arg->reg = reg;
be_abi_call_arg_t arg;
memset(&arg, 0, sizeof(arg));
arg.in_reg = 1;
arg.reg = reg;
arg.is_res = 1;
arg.pos = arg_pos;
remember_call_arg(&arg, call, context);
}
/* Get the flags of a ABI call object. */
......@@ -379,16 +397,6 @@ static be_stack_layout_t *stack_frame_init(be_stack_layout_t *frame, ir_type *ar
return frame;
}
/**
* Returns non-zero if the call argument at given position
* is transfered on the stack.
*/
static inline int is_on_stack(be_abi_call_t *call, int pos)
{
be_abi_call_arg_t *arg = get_call_arg(call, 0, pos);
return arg && !arg->in_reg;
}
/*
____ _ _
/ ___|__ _| | |___
......@@ -456,7 +464,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
assert(obstack_object_size(obst) == 0);
stack_param_idx = ALLOCAN(int, n_params);
for (i = 0; i < n_params; ++i) {
be_abi_call_arg_t *arg = get_call_arg(call, 0, i);
be_abi_call_arg_t *arg = get_call_arg(call, 0, i, 0);
assert(arg);
if (arg->on_stack) {
int arg_size = get_type_size_bytes(get_method_param_type(call_tp, i));
......@@ -472,7 +480,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
/* Collect all arguments which are passed in registers. */
reg_param_idxs = ALLOCAN(int, n_params);
for (i = 0; i < n_params; ++i) {
be_abi_call_arg_t *arg = get_call_arg(call, 0, i);
be_abi_call_arg_t *arg = get_call_arg(call, 0, i, 0);
if (arg && arg->in_reg) {
reg_param_idxs[n_reg_params++] = i;
}
......@@ -519,7 +527,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
for (i = 0; i < n_stack_params; ++i) {
int p = stack_param_idx[i];
be_abi_call_arg_t *arg = get_call_arg(call, 0, p);
be_abi_call_arg_t *arg = get_call_arg(call, 0, p, 0);
ir_node *param = get_Call_param(irn, p);
ir_node *addr = curr_sp;
ir_node *mem = NULL;
......@@ -701,7 +709,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
for (i = 0; i < n_res; ++i) {
int pn;
ir_node *proj = res_projs[i];
be_abi_call_arg_t *arg = get_call_arg(call, 1, i);
be_abi_call_arg_t *arg = get_call_arg(call, 1, i, 0);
/* returns values on stack not supported yet */
assert(arg->in_reg);
......@@ -739,7 +747,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
/* Set the register classes and constraints of the Call parameters. */
for (i = 0; i < n_reg_params; ++i) {
int index = reg_param_idxs[i];
be_abi_call_arg_t *arg = get_call_arg(call, 0, index);
be_abi_call_arg_t *arg = get_call_arg(call, 0, index, 0);
assert(arg->reg != NULL);
be_set_constr_single_reg_in(low_call, be_pos_Call_first_arg + i,
......@@ -749,7 +757,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
/* Set the register constraints of the results. */
for (i = 0; i < n_res; ++i) {
ir_node *proj = res_projs[i];
const be_abi_call_arg_t *arg = get_call_arg(call, 1, i);
const be_abi_call_arg_t *arg = get_call_arg(call, 1, i, 0);
int pn = get_Proj_proj(proj);
assert(arg->in_reg);
......@@ -1226,7 +1234,7 @@ static ir_type *compute_arg_type(be_abi_irg_t *env, be_abi_call_t *call,
res = new_type_struct(id_mangle_u(id, new_id_from_chars("arg_type", 8)));
for (i = 0; i < n; ++i, curr += inc) {
ir_type *param_type = get_method_param_type(method_type, curr);
be_abi_call_arg_t *arg = get_call_arg(call, 0, curr);
be_abi_call_arg_t *arg = get_call_arg(call, 0, curr, 1);
map[i] = NULL;
if (arg->on_stack) {
......@@ -1388,7 +1396,7 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl,
/* Insert results for Return into the register map. */
for (i = 0; i < n_res; ++i) {
ir_node *res = get_Return_res(irn, i);
be_abi_call_arg_t *arg = get_call_arg(call, 1, i);
be_abi_call_arg_t *arg = get_call_arg(call, 1, i, 1);
assert(arg->in_reg && "return value must be passed in register");
pmap_insert(reg_map, (void *) arg->reg, res);
}
......@@ -1424,7 +1432,7 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl,
/* clear SP entry, since it has already been grown. */
pmap_insert(reg_map, (void *) arch_env->sp, NULL);
for (i = 0; i < n_res; ++i) {
be_abi_call_arg_t *arg = get_call_arg(call, 1, i);
be_abi_call_arg_t *arg = get_call_arg(call, 1, i, 1);
in[n] = be_abi_reg_map_get(reg_map, arg->reg);
regs[n++] = arg->reg;
......@@ -1583,7 +1591,7 @@ static void fix_address_of_parameter_access(be_abi_irg_t *env, ent_pos_pair *val
new_list = NULL;
for (i = 0; i < n; ++i) {
int pos = value_param_list[i].pos;
be_abi_call_arg_t *arg = get_call_arg(call, 0, pos);
be_abi_call_arg_t *arg = get_call_arg(call, 0, pos, 1);
if (arg->in_reg) {
DBG((dbg, LEVEL_2, "\targ #%d need backing store\n", pos));
......@@ -1890,7 +1898,7 @@ static void modify_irg(be_abi_irg_t *env)
/* Count the register params and add them to the number of Projs for the RegParams node */
for (i = 0; i < n_params; ++i) {
be_abi_call_arg_t *arg = get_call_arg(call, 0, i);
be_abi_call_arg_t *arg = get_call_arg(call, 0, i, 1);
if (arg->in_reg && args[i]) {
assert(arg->reg != sp && "cannot use stack pointer as parameter register");
assert(i == get_Proj_proj(args[i]));
......@@ -1995,7 +2003,7 @@ static void modify_irg(be_abi_irg_t *env)
ir_mode *mode;
nr = MIN(nr, n_params);
arg = get_call_arg(call, 0, nr);
arg = get_call_arg(call, 0, nr, 1);
param_type = get_method_param_type(method_type, nr);
if (arg->in_reg) {
......
......@@ -120,6 +120,16 @@ void be_abi_call_set_pop(be_abi_call_t *call, int pop);
*/
void be_abi_call_set_call_address_reg_class(be_abi_call_t *call, const arch_register_class_t *cls);
/**
* The ABI can change when we call a function vs. when we have
* been called.
*/
typedef enum {
ABI_CONTEXT_CALLEE = 1 << 0,
ABI_CONTEXT_CALLER = 1 << 1,
ABI_CONTEXT_BOTH = ABI_CONTEXT_CALLEE | ABI_CONTEXT_CALLER
} be_abi_context_t;
/**
* Record the that ABI transmits call argument pos on the stack. Modifies the abi object.
*
......@@ -130,7 +140,9 @@ void be_abi_call_set_call_address_reg_class(be_abi_call_t *call, const arch_regi
* @param space_before size of allocated additional space before the parameter
* @param space_after size of allocated additional space after the parameter
*/
void be_abi_call_param_stack(be_abi_call_t *call, int pos, ir_mode *load_mode, unsigned alignment, unsigned space_before, unsigned space_after);
void be_abi_call_param_stack(be_abi_call_t *call, int pos, ir_mode *load_mode,
unsigned alignment, unsigned space_before,
unsigned space_after, be_abi_context_t context);
/**
* Record the that ABI transmits call argument pos in the given register.
......@@ -139,7 +151,9 @@ void be_abi_call_param_stack(be_abi_call_t *call, int pos, ir_mode *load_mode, u
* @param pos the parameter position
* @param reg the register used
*/
void be_abi_call_param_reg(be_abi_call_t *call, int pos, const arch_register_t *reg);
void be_abi_call_param_reg(be_abi_call_t *call, int pos,
const arch_register_t *reg,
be_abi_context_t context);
/**
* Record the that ABI transmits return value pos in the given register.
......@@ -148,7 +162,9 @@ void be_abi_call_param_reg(be_abi_call_t *call, int pos, const arch_register_t *
* @param pos the return value position
* @param reg the register used
*/
void be_abi_call_res_reg(be_abi_call_t *call, int pos, const arch_register_t *reg);
void be_abi_call_res_reg(be_abi_call_t *call, int pos,
const arch_register_t *reg,
be_abi_context_t context);
/**
* Get the flags of a ABI call object.
......
......@@ -59,6 +59,7 @@ void be_init_arch_mips(void);
void be_init_arch_arm(void);
void be_init_arch_sparc(void);
void be_init_arch_sta(void);
void be_init_arch_sparc(void);
void be_init_arch_TEMPLATE(void);
void be_init_ilpsched(void);
void be_init_copyilp(void);
......
......@@ -1899,7 +1899,7 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type,
reg = ia32_get_RegParam_reg(cc, regnum, mode);
}
if (reg != NULL) {
be_abi_call_param_reg(abi, i, reg);
be_abi_call_param_reg(abi, i, reg, ABI_CONTEXT_BOTH);
++regnum;
} else {
/* Micro optimisation: if the mode is shorter than 4 bytes, load 4 bytes.
......@@ -1916,7 +1916,7 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type,
if (size < 4) load_mode = mode_Iu;
}
be_abi_call_param_stack(abi, i, load_mode, 4, 0, 0);
be_abi_call_param_stack(abi, i, load_mode, 4, 0, 0, ABI_CONTEXT_BOTH);
}
}
......@@ -1939,8 +1939,8 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type,
assert(!mode_is_float(mode) && "mixed INT, FP results not supported");
be_abi_call_res_reg(abi, 0, &ia32_gp_regs[REG_EAX]);
be_abi_call_res_reg(abi, 1, &ia32_gp_regs[REG_EDX]);
be_abi_call_res_reg(abi, 0, &ia32_gp_regs[REG_EAX], ABI_CONTEXT_BOTH);
be_abi_call_res_reg(abi, 1, &ia32_gp_regs[REG_EDX], ABI_CONTEXT_BOTH);
}
else if (n == 1) {
const arch_register_t *reg;
......@@ -1951,7 +1951,7 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type,
reg = mode_is_float(mode) ? &ia32_vfp_regs[REG_VF0] : &ia32_gp_regs[REG_EAX];
be_abi_call_res_reg(abi, 0, reg);
be_abi_call_res_reg(abi, 0, reg, ABI_CONTEXT_BOTH);
}
}
......
......@@ -603,10 +603,10 @@ static void mips_get_call_abi(const void *self, ir_type *method_type,
// 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);
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);
be_abi_call_param_stack(abi, i, modes[i], 4, 0, 0, ABI_CONTEXT_BOTH);
}
}
......@@ -621,7 +621,7 @@ static void mips_get_call_abi(const void *self, ir_type *method_type,
ASSERT_NO_FLOAT(mode);
reg = &mips_gp_regs[REG_V0 + i];
be_abi_call_res_reg(abi, i, reg);
be_abi_call_res_reg(abi, i, reg, ABI_CONTEXT_BOTH);
}
}
......
......@@ -660,17 +660,17 @@ static void ppc32_get_call_abi(const void *self, ir_type *method_type, be_abi_ca
}
if (reg)
be_abi_call_param_reg(abi, i, reg);
be_abi_call_param_reg(abi, i, reg, ABI_CONTEXT_BOTH);
else
{
be_abi_call_param_stack(abi, i, mode, 4, stackoffs - lastoffs, 0);
be_abi_call_param_stack(abi, i, mode, 4, stackoffs - lastoffs, 0, ABI_CONTEXT_BOTH);
lastoffs = stackoffs+stackparamsize;
}
stackoffs += stackparamsize;
}
else
{
be_abi_call_param_stack(abi, i, mode, 4, stackoffs - lastoffs, 0);
be_abi_call_param_stack(abi, i, mode, 4, stackoffs - lastoffs, 0, ABI_CONTEXT_BOTH);
stackoffs += (get_type_size_bytes(tp)+3) & -4;
lastoffs = stackoffs;
}
......@@ -682,7 +682,7 @@ static void ppc32_get_call_abi(const void *self, ir_type *method_type, be_abi_ca
mode = get_type_mode(tp);
be_abi_call_res_reg(abi, 0,
mode_is_float(mode) ? &ppc32_fp_regs[REG_F1] : &ppc32_gp_regs[REG_R3]);
mode_is_float(mode) ? &ppc32_fp_regs[REG_F1] : &ppc32_gp_regs[REG_R3], ABI_CONTEXT_BOTH);
}
}
......
......@@ -60,6 +60,7 @@
#include "../beflags.h"
#include "bearch_sparc_t.h"
#include "bearch_sparc.h"
#include "sparc_new_nodes.h"
#include "gen_sparc_regalloc_if.h"
......@@ -121,7 +122,7 @@ static void sparc_set_frame_offset(ir_node *irn, int offset)
static int sparc_get_sp_bias(const ir_node *irn)
{
(void) irn;
return 0;
return SPARC_MIN_STACKSIZE;
}
/* fill register allocator interface */
......@@ -158,18 +159,6 @@ static void sparc_prepare_graph(void *self)
/**
* Called immediatly before emit phase.
*/
static void sparc_finish_irg(void *self)
{
sparc_code_gen_t *cg = self;
ir_graph *irg = cg->irg;
dump_ir_block_graph_sched(irg, "-sparc-finished");
}
static ir_node *sparc_flags_remat(ir_node *node, ir_node *after)
{
ir_node *block;
......@@ -302,7 +291,7 @@ static const arch_code_generator_if_t sparc_code_gen_if = {
NULL, /* spill hook */
sparc_before_ra, /* before register allocation hook */
sparc_after_ra, /* after register allocation hook */
sparc_finish_irg,
NULL,
sparc_emit_and_done
};
......@@ -459,6 +448,7 @@ static ir_type *sparc_get_between_type(void *self)
return between_type;
}
/**
* Build the prolog, return the BASE POINTER register
*/
......@@ -466,15 +456,34 @@ static const arch_register_t *sparc_abi_prologue(void *self, ir_node **mem,
pmap *reg_map, int *stack_bias)
{
sparc_abi_env_t *env = self;
ir_node *block = get_irg_start_block(env->irg);
const arch_register_t *fp = &sparc_gp_regs[REG_FP];
const arch_register_t *sp = &sparc_gp_regs[REG_SP];
// sp
ir_node *sp_proj = be_abi_reg_map_get(reg_map, sp);
//ir_type *frame_type = get_irg_frame_type(env->irg);
//frame_alloc_area(frame_type, reserved_stack_size, 1, 1);
(void) reg_map;
(void) mem;
(void) stack_bias;
if (env->flags.try_omit_fp)
return env->arch_env->sp;
// alloc min required stack space
// TODO: the min stacksize depends on wether this is a leaf procedure or not
ir_node *save = new_bd_sparc_Save(NULL, block, sp_proj, *mem, SPARC_MIN_STACKSIZE);
//panic("framepointer not implemented yet");
return env->arch_env->bp;
*stack_bias -= SPARC_MIN_STACKSIZE;
sp_proj = new_r_Proj(block, save, sp->reg_class->mode, pn_sparc_Save_stack);
*mem = new_r_Proj(block, save, mode_M, pn_sparc_Save_mem);
arch_set_irn_register(sp_proj, sp);
be_abi_reg_map_set(reg_map, sp, sp_proj);
// we always have a framepointer
return fp;
}
/* Build the epilog */
......@@ -513,7 +522,8 @@ static void sparc_get_call_abi(const void *self, ir_type *method_type,
/* 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.try_omit_fp = 0;
call_flags.bits.fp_free = 0;
call_flags.bits.call_has_imm = 1;
......@@ -524,24 +534,28 @@ static void sparc_get_call_abi(const void *self, ir_type *method_type,
/* reg = get reg for param i; */
/* be_abi_call_param_reg(abi, i, reg); */
/* pass args 0-5 via registers, remaining via stack */
/* pass outgoing params 0-5 via registers, remaining via stack */
/* on sparc we need to set the ABI context since register names of parameters change to i0-i5 if we are the callee */
if (i < 6) {
be_abi_call_param_reg(abi, i, sparc_get_RegParam_reg(i));
be_abi_call_param_reg(abi, i, sparc_get_RegParamOut_reg(i), ABI_CONTEXT_CALLER);
be_abi_call_param_reg(abi, i, sparc_get_RegParamIn_reg(i), ABI_CONTEXT_CALLEE);
} else {
tp = get_method_param_type(method_type, i);
mode = get_type_mode(tp);
be_abi_call_param_stack(abi, i, mode, 4, 0, 0);
be_abi_call_param_stack(abi, i, mode, 4, 0, 0, ABI_CONTEXT_BOTH); /*< stack args have no special context >*/
}
}
/* TODO: set correct return register */
/* default: return value is in O0 resp. F0 */
/* set return value register: return value is in i0 resp. f0 */
if (get_method_n_ress(method_type) > 0) {
tp = get_method_res_type(method_type, 0);
mode = get_type_mode(tp);
be_abi_call_res_reg(abi, 0,
mode_is_float(mode) ? &sparc_fp_regs[REG_F0] : &sparc_gp_regs[REG_O0]);
mode_is_float(mode) ? &sparc_fp_regs[REG_F0] : &sparc_gp_regs[REG_I0], ABI_CONTEXT_CALLEE); /*< return has no special context >*/
be_abi_call_res_reg(abi, 0,
mode_is_float(mode) ? &sparc_fp_regs[REG_F0] : &sparc_gp_regs[REG_O0], ABI_CONTEXT_CALLER); /*< return has no special context >*/
}
}
......
......@@ -31,6 +31,11 @@
#include "../beemitter.h"
#include "set.h"
// sparc ABI requires a min stacksize to
// save registers in case of a trap etc.
// by now we assume only non-leaf procedures: 92 + 4 (padding)
#define SPARC_MIN_STACKSIZE 96
typedef struct sparc_transform_env_t sparc_transform_env_t;
typedef struct _sparc_isa_t sparc_isa_t;
......@@ -62,4 +67,6 @@ struct sparc_transform_env_t {
ir_mode *mode; /**< The mode of the irn */
};
void sparc_finish_irg(sparc_code_gen_t *cg);
#endif
......@@ -55,6 +55,13 @@
#define SNPRINTF_BUF_LEN 128