mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-21 01:41:10 +00:00
[qfcc] Use new extend instruction instead of swizzle
While swizzle does work, it requires the source to be properly aligned and thus is not really the best choice. The extend instruction has no alignment requirements (at all) and thus is much better suited to converting a scalar to a vector type. Fixes #30
This commit is contained in:
parent
d9d0a80752
commit
95b8424ddf
6 changed files with 71 additions and 8 deletions
|
@ -269,6 +269,12 @@ typedef struct {
|
|||
struct type_s *type; ///< result type
|
||||
} ex_swizzle_t;
|
||||
|
||||
typedef struct {
|
||||
struct expr_s *src; ///< source expression
|
||||
int extend; ///< extend mode 0: 0, 1: 1, 2: copy/0 3:-1
|
||||
struct type_s *type; ///< result type;
|
||||
} ex_extend_t;
|
||||
|
||||
#define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val)
|
||||
|
||||
typedef struct expr_s {
|
||||
|
@ -305,6 +311,7 @@ typedef struct expr_s {
|
|||
struct type_s *nil; ///< type for nil if known
|
||||
ex_horizontal_t hop; ///< horizontal vector operation
|
||||
ex_swizzle_t swizzle; ///< vector swizzle operation
|
||||
ex_extend_t extend; ///< vector extend operation
|
||||
} e;
|
||||
} expr_t;
|
||||
|
||||
|
@ -494,6 +501,8 @@ expr_t *new_horizontal_expr (int op, expr_t *vec, struct type_s *type);
|
|||
|
||||
expr_t *new_swizzle_expr (expr_t *src, const char *swizzle);
|
||||
|
||||
expr_t *new_extend_expr (expr_t *src, struct type_s *type, int ext);
|
||||
|
||||
/** Create a new def reference (non-temporary variable) expression node.
|
||||
|
||||
\return The new def reference expression node (::def_t).
|
||||
|
|
|
@ -64,5 +64,6 @@ EX_EXPR(with) ///< with expression (::ex_with_t)
|
|||
EX_EXPR(args) ///< @args marker in parameter list. no data
|
||||
EX_EXPR(horizontal) ///< horizontal vector operation (::ex_horzontal_t)
|
||||
EX_EXPR(swizzle) ///< vector swizzle operation (::ex_swizzle_t)
|
||||
EX_EXPR(extend) ///< vector extend operation (::ex_extend_t)
|
||||
|
||||
///@}
|
||||
|
|
|
@ -197,6 +197,8 @@ get_type (expr_t *e)
|
|||
return e->e.hop.type;
|
||||
case ex_swizzle:
|
||||
return e->e.swizzle.type;
|
||||
case ex_extend:
|
||||
return e->e.extend.type;
|
||||
case ex_count:
|
||||
internal_error (e, "invalid expression");
|
||||
}
|
||||
|
@ -432,6 +434,11 @@ copy_expr (expr_t *e)
|
|||
*n = *e;
|
||||
e->e.swizzle.src = copy_expr (e->e.swizzle.src);
|
||||
return n;
|
||||
case ex_extend:
|
||||
n = new_expr ();
|
||||
*n = *e;
|
||||
e->e.extend.src = copy_expr (e->e.extend.src);
|
||||
return n;
|
||||
case ex_count:
|
||||
break;
|
||||
}
|
||||
|
@ -686,6 +693,17 @@ new_swizzle_expr (expr_t *src, const char *swizzle)
|
|||
return expr;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_extend_expr (expr_t *src, type_t *type, int ext)
|
||||
{
|
||||
expr_t *expr = new_expr ();
|
||||
expr->type = ex_extend;
|
||||
expr->e.extend.src = src;
|
||||
expr->e.extend.extend = ext;
|
||||
expr->e.extend.type = type;
|
||||
return expr;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_def_expr (def_t *def)
|
||||
{
|
||||
|
@ -1624,6 +1642,8 @@ has_function_call (expr_t *e)
|
|||
return has_function_call (e->e.hop.vec);
|
||||
case ex_swizzle:
|
||||
return has_function_call (e->e.swizzle.src);
|
||||
case ex_extend:
|
||||
return has_function_call (e->e.extend.src);
|
||||
case ex_error:
|
||||
case ex_state:
|
||||
case ex_label:
|
||||
|
@ -1770,6 +1790,7 @@ unary_expr (int op, expr_t *e)
|
|||
case ex_assign:
|
||||
case ex_horizontal:
|
||||
case ex_swizzle:
|
||||
case ex_extend:
|
||||
{
|
||||
expr_t *n = new_unary_expr (op, e);
|
||||
|
||||
|
@ -1864,6 +1885,7 @@ unary_expr (int op, expr_t *e)
|
|||
case ex_assign:
|
||||
case ex_horizontal:
|
||||
case ex_swizzle:
|
||||
case ex_extend:
|
||||
if (options.code.progsversion == PROG_VERSION) {
|
||||
return binary_expr (EQ, e, new_nil_expr ());
|
||||
} else {
|
||||
|
@ -1954,6 +1976,7 @@ unary_expr (int op, expr_t *e)
|
|||
case ex_assign:
|
||||
case ex_horizontal:
|
||||
case ex_swizzle:
|
||||
case ex_extend:
|
||||
bitnot_expr:
|
||||
if (options.code.progsversion == PROG_ID_VERSION) {
|
||||
expr_t *n1 = new_int_expr (-1);
|
||||
|
|
|
@ -143,6 +143,7 @@ is_lvalue (const expr_t *expr)
|
|||
case ex_args:
|
||||
case ex_horizontal:
|
||||
case ex_swizzle:
|
||||
case ex_extend:
|
||||
break;
|
||||
case ex_count:
|
||||
internal_error (expr, "invalid expression");
|
||||
|
|
|
@ -667,14 +667,7 @@ convert_scalar (expr_t *scalar, int op, expr_t *vec)
|
|||
return new_vector_list (scalar);
|
||||
}
|
||||
|
||||
char swizzle[] = "xxxx";
|
||||
type_t *vec_base = base_type (vec_type);
|
||||
expr_t *tmp = new_temp_def_expr (vector_type (vec_base, 4));
|
||||
expr_t *block = new_block_expr ();
|
||||
swizzle[type_width (vec_type)] = 0;
|
||||
append_expr (block, assign_expr (tmp, new_swizzle_expr (scalar, swizzle)));
|
||||
block->e.block.result = new_alias_expr (vec_type, tmp);
|
||||
return block;
|
||||
return new_extend_expr (scalar, vec_type, 2);//2 = copy
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
|
|
|
@ -1810,6 +1810,41 @@ expr_swizzle (sblock_t *sblock, expr_t *e, operand_t **op)
|
|||
return sblock;
|
||||
}
|
||||
|
||||
static sblock_t *
|
||||
expr_extend (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||
{
|
||||
type_t *src_type = get_type (e->e.extend.src);
|
||||
type_t *res_type = e->e.extend.type;
|
||||
int src_width = type_width (src_type);
|
||||
int res_width = type_width (res_type);
|
||||
type_t *src_base = base_type (src_type);
|
||||
type_t *res_base = base_type (res_type);
|
||||
static int mode[4][4] = {
|
||||
{-1, 0, 1, 2},
|
||||
{-1,-1, 3, 4},
|
||||
{-1,-1,-1, 5},
|
||||
{-1,-1,-1,-1},
|
||||
};
|
||||
int ext = mode[src_width - 1][res_width - 1];
|
||||
ext |= (e->e.extend.extend & 3) << 3;
|
||||
ext |= (pr_type_size[res_base->type] - 1) << 5;
|
||||
if (ext < 0 || res_base != src_base) {
|
||||
internal_error (e, "invalid type combination for extend %d %d %d",
|
||||
ext, src_width, res_width);
|
||||
}
|
||||
|
||||
statement_t *s = new_statement (st_expr, "extend", e);
|
||||
sblock = statement_subexpr (sblock, e->e.extend.src, &s->opa);
|
||||
s->opb = short_operand (ext, e);
|
||||
if (!*op) {
|
||||
*op = temp_operand (res_type, e);
|
||||
}
|
||||
s->opc = *op;
|
||||
sblock_add_statement (sblock, s);
|
||||
|
||||
return sblock;
|
||||
}
|
||||
|
||||
static sblock_t *
|
||||
expr_def (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||
{
|
||||
|
@ -1954,6 +1989,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op)
|
|||
[ex_address] = expr_address,
|
||||
[ex_assign] = expr_assign,
|
||||
[ex_branch] = expr_branch,
|
||||
[ex_extend] = expr_extend,
|
||||
};
|
||||
if (!e) {
|
||||
*op = 0;
|
||||
|
|
Loading…
Reference in a new issue