[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;
    }
This commit is contained in:
Bill Currie 2022-02-04 08:46:58 +09:00
parent 1487fa6b50
commit 52a399daeb
3 changed files with 14 additions and 8 deletions

View file

@ -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

View file

@ -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) {

View file

@ -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;
}