X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=ir%2Fbe%2Fsparc%2Fsparc_cconv.c;h=132f704cef2e9c131b93d386fedce6c150f877ad;hb=52a818d61941174d4a7d39f37db43b1c7a7b984d;hp=d1b38f67e4e420d09b4014d40c047c3fe0b3dfdf;hpb=595a5d410e24d1ecb517de36a29282bb2ac64eff;p=libfirm diff --git a/ir/be/sparc/sparc_cconv.c b/ir/be/sparc/sparc_cconv.c index d1b38f67e..132f704ce 100644 --- a/ir/be/sparc/sparc_cconv.c +++ b/ir/be/sparc/sparc_cconv.c @@ -21,7 +21,6 @@ * @file * @brief calling convention helpers * @author Matthias Braun - * @version $Id$ */ #include "config.h" @@ -37,7 +36,9 @@ static const unsigned ignore_regs[] = { REG_G0, - /* reserved for sparc ABI: */ + /* used in case an address offset does not fit into an immediate: */ + REG_G4, + /* reserved for SPARC ABI: */ REG_G5, REG_G6, REG_G7, @@ -75,52 +76,58 @@ static const arch_register_t* const float_result_regs[] = { static arch_register_req_t float_result_reqs_double[8]; static arch_register_req_t float_result_reqs_quad[8]; -static const arch_register_t *const caller_saves[] = { - &sparc_registers[REG_G1], - &sparc_registers[REG_G2], - &sparc_registers[REG_G3], - &sparc_registers[REG_G4], - &sparc_registers[REG_O0], - &sparc_registers[REG_O1], - &sparc_registers[REG_O2], - &sparc_registers[REG_O3], - &sparc_registers[REG_O4], - &sparc_registers[REG_O5], - &sparc_registers[REG_F0], - &sparc_registers[REG_F1], - &sparc_registers[REG_F2], - &sparc_registers[REG_F3], - &sparc_registers[REG_F4], - &sparc_registers[REG_F5], - &sparc_registers[REG_F6], - &sparc_registers[REG_F7], - &sparc_registers[REG_F8], - &sparc_registers[REG_F9], - &sparc_registers[REG_F10], - &sparc_registers[REG_F11], - &sparc_registers[REG_F12], - &sparc_registers[REG_F13], - &sparc_registers[REG_F14], - &sparc_registers[REG_F15], - &sparc_registers[REG_F16], - &sparc_registers[REG_F17], - &sparc_registers[REG_F18], - &sparc_registers[REG_F19], - &sparc_registers[REG_F20], - &sparc_registers[REG_F21], - &sparc_registers[REG_F22], - &sparc_registers[REG_F23], - &sparc_registers[REG_F24], - &sparc_registers[REG_F25], - &sparc_registers[REG_F26], - &sparc_registers[REG_F27], - &sparc_registers[REG_F28], - &sparc_registers[REG_F29], - &sparc_registers[REG_F30], - &sparc_registers[REG_F31], +static const unsigned caller_saves[] = { + REG_G1, + REG_G2, + REG_G3, + REG_O0, + REG_O1, + REG_O2, + REG_O3, + REG_O4, + REG_O5, + REG_F0, + REG_F1, + REG_F2, + REG_F3, + REG_F4, + REG_F5, + REG_F6, + REG_F7, + REG_F8, + REG_F9, + REG_F10, + REG_F11, + REG_F12, + REG_F13, + REG_F14, + REG_F15, + REG_F16, + REG_F17, + REG_F18, + REG_F19, + REG_F20, + REG_F21, + REG_F22, + REG_F23, + REG_F24, + REG_F25, + REG_F26, + REG_F27, + REG_F28, + REG_F29, + REG_F30, + REG_F31, }; static unsigned default_caller_saves[BITSET_SIZE_ELEMS(N_SPARC_REGISTERS)]; +static const unsigned returns_twice_saved[] = { + REG_SP, + REG_FRAME_POINTER, + REG_I7 +}; +static unsigned default_returns_twice_saves[BITSET_SIZE_ELEMS(N_SPARC_REGISTERS)]; + /** * Maps an input register representing the i'th register input * to the i'th register output. @@ -172,6 +179,8 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type, int n_param_regs = ARRAY_SIZE(param_regs); unsigned n_float_result_regs = ARRAY_SIZE(float_result_regs); bool omit_fp = false; + mtp_additional_properties mtp + = get_method_additional_properties(function_type); reg_or_stackslot_t *params; reg_or_stackslot_t *results; int n_params; @@ -186,11 +195,22 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type, if (irg != NULL) { const be_options_t *options = be_get_irg_options(irg); omit_fp = options->omit_fp; - irg_walk_graph(irg, check_omit_fp, NULL, &omit_fp); + /* our current vaarg handling needs the standard space to store the + * args 0-5 in it */ + if (get_method_variadicity(function_type) == variadicity_variadic) + omit_fp = false; + if (omit_fp == true) { + irg_walk_graph(irg, check_omit_fp, NULL, &omit_fp); + } } caller_saves = rbitset_malloc(N_SPARC_REGISTERS); - rbitset_copy(caller_saves, default_caller_saves, N_SPARC_REGISTERS); + if (mtp & mtp_property_returns_twice) { + rbitset_copy(caller_saves, default_returns_twice_saves, + N_SPARC_REGISTERS); + } else { + rbitset_copy(caller_saves, default_caller_saves, N_SPARC_REGISTERS); + } /* determine how parameters are passed */ n_params = get_method_n_params(function_type); @@ -231,8 +251,8 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type, } else { param->type = param_type; param->offset = stack_offset; - /* increase offset 4 bytes so everything is aligned */ - stack_offset += bits > 32 ? bits/8 : 4; + /* increase offset by at least SPARC_REGISTER_SIZE bytes so everything is aligned */ + stack_offset += bits > 8 * SPARC_REGISTER_SIZE ? bits / 8 : SPARC_REGISTER_SIZE; continue; } @@ -254,7 +274,7 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type, param->type = type; param->offset = stack_offset; assert(get_mode_size_bits(regmode) == 32); - stack_offset += 4; + stack_offset += SPARC_REGISTER_SIZE; } } } @@ -354,7 +374,15 @@ void sparc_cconv_init(void) { size_t i; for (i = 0; i < ARRAY_SIZE(caller_saves); ++i) { - rbitset_set(default_caller_saves, caller_saves[i]->global_index); + rbitset_set(default_caller_saves, caller_saves[i]); + } + + rbitset_set_all(default_returns_twice_saves, N_SPARC_REGISTERS); + for (i = 0; i < ARRAY_SIZE(returns_twice_saved); ++i) { + rbitset_clear(default_returns_twice_saves, returns_twice_saved[i]); + } + for (i = 0; i < ARRAY_SIZE(ignore_regs); ++i) { + rbitset_clear(default_returns_twice_saves, ignore_regs[i]); } for (i = 0; i < ARRAY_SIZE(float_result_reqs_double); i += 2) {