X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Farm%2Farm_cconv.c;h=8ca715ca87bdc438cbf527f91b6d79d33b71a5ac;hb=792661421a71bcfa9b64da8c6b655e826e94d2c1;hp=287a6ddf52c8d4f83a158df0735c9235bb56b438;hpb=637450acaf2ef255b2841785a6c6e6b809c9ac27;p=libfirm diff --git a/ir/be/arm/arm_cconv.c b/ir/be/arm/arm_cconv.c index 287a6ddf5..8ca715ca8 100644 --- a/ir/be/arm/arm_cconv.c +++ b/ir/be/arm/arm_cconv.c @@ -21,7 +21,6 @@ * @file * @brief calling convention helpers * @author Matthias Braun - * @version $Id$ */ #include "config.h" @@ -30,23 +29,49 @@ #include "typerep.h" #include "xmalloc.h" #include "error.h" +#include "util.h" -calling_convention_t *arm_decide_calling_convention(ir_type *function_type) +static const unsigned ignore_regs[] = { + REG_R12, + REG_SP, + REG_PC, + REG_FL, +}; + +static const arch_register_t* const param_regs[] = { + &arm_registers[REG_R0], + &arm_registers[REG_R1], + &arm_registers[REG_R2], + &arm_registers[REG_R3] +}; + +static const arch_register_t* const result_regs[] = { + &arm_registers[REG_R0], + &arm_registers[REG_R1], + &arm_registers[REG_R2], + &arm_registers[REG_R3] +}; + +static const arch_register_t* const float_result_regs[] = { + &arm_registers[REG_F0], + &arm_registers[REG_F1] +}; + +calling_convention_t *arm_decide_calling_convention(const ir_graph *irg, + ir_type *function_type) { - int stack_offset = 0; + unsigned stack_offset = 0; + unsigned n_param_regs_used = 0; reg_or_stackslot_t *params; reg_or_stackslot_t *results; - int n_param_regs - = sizeof(param_regs)/sizeof(param_regs[0]); - int n_result_regs - = sizeof(result_regs)/sizeof(result_regs[0]); - int n_float_result_regs - = sizeof(float_result_regs)/sizeof(float_result_regs[0]); - int n_params; - int n_results; - int i; - int regnum; - int float_regnum; + size_t const n_param_regs = ARRAY_SIZE(param_regs); + size_t const n_result_regs = ARRAY_SIZE(result_regs); + size_t const n_float_result_regs = ARRAY_SIZE(float_result_regs); + size_t n_params; + size_t n_results; + size_t i; + size_t regnum; + size_t float_regnum; calling_convention_t *cconv; /* determine how parameters are passed */ @@ -74,21 +99,22 @@ calling_convention_t *arm_decide_calling_convention(ir_type *function_type) /* we might need a 2nd 32bit component (for 64bit or double values) */ if (bits > 32) { if (bits > 64) - panic("only 32 and 64bit modes supported in arm backend"); + panic("only 32 and 64bit modes supported"); if (regnum < n_param_regs) { const arch_register_t *reg = param_regs[regnum++]; param->reg1 = reg; } else { - ir_mode *mode = param_regs[0]->reg_class->mode; - ir_type *type = get_type_for_mode(mode); - param->type = type; - param->offset = stack_offset; - assert(get_mode_size_bits(mode) == 32); + ir_mode *pmode = param_regs[0]->reg_class->mode; + ir_type *type = get_type_for_mode(pmode); + param->type = type; + param->offset = stack_offset; + assert(get_mode_size_bits(pmode) == 32); stack_offset += 4; } } } + n_param_regs_used = regnum; n_results = get_method_n_ress(function_type); regnum = 0; @@ -101,18 +127,18 @@ calling_convention_t *arm_decide_calling_convention(ir_type *function_type) if (mode_is_float(result_mode)) { if (float_regnum >= n_float_result_regs) { - panic("Too many float results for arm backend"); + panic("Too many float results"); } else { const arch_register_t *reg = float_result_regs[float_regnum++]; result->reg0 = reg; } } else { if (get_mode_size_bits(result_mode) > 32) { - panic("Results with more than 32bits not supported by arm backend yet"); + panic("Results with more than 32bits not supported yet"); } if (regnum >= n_result_regs) { - panic("Too many results for arm backend"); + panic("Too many results"); } else { const arch_register_t *reg = result_regs[regnum++]; result->reg0 = reg; @@ -123,8 +149,24 @@ calling_convention_t *arm_decide_calling_convention(ir_type *function_type) cconv = XMALLOCZ(calling_convention_t); cconv->parameters = params; cconv->param_stack_size = stack_offset; + cconv->n_reg_params = n_param_regs_used; cconv->results = results; + /* setup allocatable registers */ + if (irg != NULL) { + be_irg_t *birg = be_birg_from_irg(irg); + size_t n_ignores = ARRAY_SIZE(ignore_regs); + struct obstack *obst = &birg->obst; + size_t r; + + assert(birg->allocatable_regs == NULL); + birg->allocatable_regs = rbitset_obstack_alloc(obst, N_ARM_REGISTERS); + rbitset_set_all(birg->allocatable_regs, N_ARM_REGISTERS); + for (r = 0; r < n_ignores; ++r) { + rbitset_clear(birg->allocatable_regs, ignore_regs[r]); + } + } + return cconv; }