From 52a399daeb8e80f76882aee0e13d469ac35be837 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 08:46:58 +0900 Subject: [PATCH] [qfcc] Update sizes and alignments for dvec4 and friends dvec4, lvec4 and ulvec4 need to be aligned to 8 words (32 bytes) in order to avoid hardware exceptions. Rather than dealing with possibly mixed alignment when a function has 8-word aligned locals but only 4-word aligned parameters, simply keep the stack frame 8-word aligned at all times. As for sizes, the temp def recycler was written before the Ruamoko ISA was even a pipe dream and thus never expected temp def sizes over 4. At least now any future adjustments can be done in one place. My quick and dirty test program works :) dvec4 xy = {1d, 2d, 0d, 0.5}; void printf(string fmt, ...) = #0; int main() { dvec4 u = {3, 4, 3.14}; dvec4 v = {3, 4, 0, 1}; dvec4 w = v * xy + u; printf ("[%g, %g, %g, %g]\n", w[0], w[1], w[2], w[3]); return 0; } --- tools/qfcc/include/function.h | 4 +++- tools/qfcc/source/def.c | 2 +- tools/qfcc/source/function.c | 16 ++++++++++------ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 3a089a4c2..83b455555 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -41,6 +41,8 @@ #include "def.h" +#define MAX_DEF_SIZE ((int)PR_SIZEOF(lvec4)) + /** Represent an overloading of a function. Every function, whether overloaded or not, has an entry in the overloaded @@ -71,7 +73,7 @@ typedef struct function_s { const struct type_s *type; ///< function's type without aliases int temp_reg; ///< base register to use for temp defs int temp_num; ///< number for next temp var - struct def_s *temp_defs[4]; ///< freed temp vars (by size) + struct def_s *temp_defs[MAX_DEF_SIZE];///< freed temp vars (by size) struct def_s *def; ///< output def holding function number struct symbol_s *sym; ///< internal symbol for this function /** \name Local data space diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index cf2a70c10..849723a44 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -209,7 +209,7 @@ temp_def (type_t *type) int size = type_size (type); int alignment = type->alignment; - if (size < 1 || size > 4) { + if (size < 1 || size > MAX_DEF_SIZE) { internal_error (0, "%d invalid size for temp def", size); } if (alignment < 1) { diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index c85b68edf..42f757b9e 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -74,6 +74,9 @@ static hashtab_t *function_map; // standardized base register to use for all locals (arguments, local defs, // params) #define LOCALS_REG 1 +// keep the stack aligned to 8 words (32 bytes) so lvec etc can be used without +// having to do shenanigans with mixed-alignment stack frames +#define STACK_ALIGN 8 static const char * ol_func_get_key (const void *_f, void *unused) @@ -785,26 +788,27 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) if (func->arguments) { func->arguments->size = func->arguments->max_size; - merge_spaces (space, func->arguments, 4); + merge_spaces (space, func->arguments, STACK_ALIGN); func->arguments = 0; } - merge_spaces (space, func->locals->space, 4); + merge_spaces (space, func->locals->space, STACK_ALIGN); func->locals->space = space; // allocate 0 words to force alignment and get the address - func->params_start = defspace_alloc_aligned_highwater (space, 0, 4); + func->params_start = defspace_alloc_aligned_highwater (space, 0, + STACK_ALIGN); dstatement_t *st = &pr.code->code[func->code]; if (st->op == OP_ADJSTK) { st->b = -func->params_start; } - merge_spaces (space, func->parameters->space, 4); + merge_spaces (space, func->parameters->space, STACK_ALIGN); func->parameters->space = space; // force the alignment again so the full stack slot is counted when - // the final parameter is smaller than 4 words - defspace_alloc_aligned_highwater (space, 0, 4); + // the final parameter is smaller than STACK_ALIGN words + defspace_alloc_aligned_highwater (space, 0, STACK_ALIGN); } return fsym->s.func; }