mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 12:31:10 +00:00
[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:
parent
1487fa6b50
commit
52a399daeb
3 changed files with 14 additions and 8 deletions
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue