mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 20:41:20 +00:00
[qfcc] Add support for horizontal vector ops
And reimplement vector comparison for Ruamoko.
This commit is contained in:
parent
feb3be4e6b
commit
3f389b602a
8 changed files with 134 additions and 5 deletions
|
@ -249,6 +249,12 @@ typedef struct {
|
||||||
struct expr_s *with; ///< value to load
|
struct expr_s *with; ///< value to load
|
||||||
} ex_with_t;
|
} ex_with_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int op; ///< operation to perform
|
||||||
|
struct expr_s *vec; ///< vector expression on which to operate
|
||||||
|
struct type_s *type; ///< result type
|
||||||
|
} ex_horizontal_t;
|
||||||
|
|
||||||
#define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val)
|
#define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val)
|
||||||
|
|
||||||
typedef struct expr_s {
|
typedef struct expr_s {
|
||||||
|
@ -283,6 +289,7 @@ typedef struct expr_s {
|
||||||
ex_adjstk_t adjstk; ///< stack adjust param
|
ex_adjstk_t adjstk; ///< stack adjust param
|
||||||
ex_with_t with; ///< with expr param
|
ex_with_t with; ///< with expr param
|
||||||
struct type_s *nil; ///< type for nil if known
|
struct type_s *nil; ///< type for nil if known
|
||||||
|
ex_horizontal_t hop; ///< horizontal vector operation
|
||||||
} e;
|
} e;
|
||||||
} expr_t;
|
} expr_t;
|
||||||
|
|
||||||
|
@ -432,7 +439,7 @@ void build_element_chain (element_chain_t *element_chain,
|
||||||
expr_t *eles, int base_offset);
|
expr_t *eles, int base_offset);
|
||||||
void free_element_chain (element_chain_t *element_chain);
|
void free_element_chain (element_chain_t *element_chain);
|
||||||
|
|
||||||
/** Create a new binary expression node node.
|
/** Create a new binary expression node.
|
||||||
|
|
||||||
If either \a e1 or \a e2 are error expressions, then that expression will
|
If either \a e1 or \a e2 are error expressions, then that expression will
|
||||||
be returned instead of a new binary expression.
|
be returned instead of a new binary expression.
|
||||||
|
@ -446,7 +453,7 @@ void free_element_chain (element_chain_t *element_chain);
|
||||||
*/
|
*/
|
||||||
expr_t *new_binary_expr (int op, expr_t *e1, expr_t *e2);
|
expr_t *new_binary_expr (int op, expr_t *e1, expr_t *e2);
|
||||||
|
|
||||||
/** Create a new unary expression node node.
|
/** Create a new unary expression node.
|
||||||
|
|
||||||
If \a e1 is an error expression, then it will be returned instead of a
|
If \a e1 is an error expression, then it will be returned instead of a
|
||||||
new unary expression.
|
new unary expression.
|
||||||
|
@ -458,6 +465,19 @@ expr_t *new_binary_expr (int op, expr_t *e1, expr_t *e2);
|
||||||
*/
|
*/
|
||||||
expr_t *new_unary_expr (int op, expr_t *e1);
|
expr_t *new_unary_expr (int op, expr_t *e1);
|
||||||
|
|
||||||
|
/** Create a new horizontal vector operantion node.
|
||||||
|
|
||||||
|
If \a vec is an error expression, then it will be returned instead of a
|
||||||
|
new unary expression.
|
||||||
|
|
||||||
|
\param op The op-code of the horizontal operation.
|
||||||
|
\param vec The expression (must be a vector type) on which to operate.
|
||||||
|
\param type The result type (must be scalar type)
|
||||||
|
\return The new unary expression node (::ex_expr_t) if \a e1
|
||||||
|
is not an error expression, otherwise \a e1.
|
||||||
|
*/
|
||||||
|
expr_t *new_horizontal_expr (int op, expr_t *vec, struct type_s *type);
|
||||||
|
|
||||||
/** Create a new def reference (non-temporary variable) expression node.
|
/** Create a new def reference (non-temporary variable) expression node.
|
||||||
|
|
||||||
\return The new def reference expression node (::def_t).
|
\return The new def reference expression node (::def_t).
|
||||||
|
|
|
@ -62,5 +62,6 @@ EX_EXPR(return) ///< return expression (::ex_return_t)
|
||||||
EX_EXPR(adjstk) ///< stack adjust expression (::ex_adjstk_t)
|
EX_EXPR(adjstk) ///< stack adjust expression (::ex_adjstk_t)
|
||||||
EX_EXPR(with) ///< with expression (::ex_with_t)
|
EX_EXPR(with) ///< with expression (::ex_with_t)
|
||||||
EX_EXPR(args) ///< @args marker in parameter list. no data
|
EX_EXPR(args) ///< @args marker in parameter list. no data
|
||||||
|
EX_EXPR(horizontal) ///< horizontal vector operation (::ex_horzontal_t)
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
|
@ -276,6 +276,8 @@ get_type (expr_t *e)
|
||||||
return get_type (e->e.assign.dst);
|
return get_type (e->e.assign.dst);
|
||||||
case ex_args:
|
case ex_args:
|
||||||
return &type_va_list;
|
return &type_va_list;
|
||||||
|
case ex_horizontal:
|
||||||
|
return e->e.hop.type;
|
||||||
case ex_count:
|
case ex_count:
|
||||||
internal_error (e, "invalid expression");
|
internal_error (e, "invalid expression");
|
||||||
}
|
}
|
||||||
|
@ -531,6 +533,11 @@ copy_expr (expr_t *e)
|
||||||
n = new_expr ();
|
n = new_expr ();
|
||||||
*n = *e;
|
*n = *e;
|
||||||
return n;
|
return n;
|
||||||
|
case ex_horizontal:
|
||||||
|
n = new_expr ();
|
||||||
|
*n = *e;
|
||||||
|
e->e.hop.vec = copy_expr (e->e.hop.vec);
|
||||||
|
return n;
|
||||||
case ex_count:
|
case ex_count:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -695,6 +702,28 @@ new_unary_expr (int op, expr_t *e1)
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expr_t *
|
||||||
|
new_horizontal_expr (int op, expr_t *vec, type_t *type)
|
||||||
|
{
|
||||||
|
type_t *vec_type = get_type (vec);
|
||||||
|
if (!vec_type) {
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
if (!is_math (vec_type) || is_scalar (vec_type)) {
|
||||||
|
internal_error (vec, "horizontal operand not a vector type");
|
||||||
|
}
|
||||||
|
if (!is_scalar (type)) {
|
||||||
|
internal_error (vec, "horizontal result not a scalar type");
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_t *e = new_expr ();
|
||||||
|
e->type = ex_horizontal;
|
||||||
|
e->e.hop.op = op;
|
||||||
|
e->e.hop.vec = vec;
|
||||||
|
e->e.hop.type = type;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
expr_t *
|
expr_t *
|
||||||
new_def_expr (def_t *def)
|
new_def_expr (def_t *def)
|
||||||
{
|
{
|
||||||
|
@ -1733,6 +1762,8 @@ has_function_call (expr_t *e)
|
||||||
return has_function_call (e->e.branch.test);
|
return has_function_call (e->e.branch.test);
|
||||||
case ex_return:
|
case ex_return:
|
||||||
return has_function_call (e->e.retrn.ret_val);
|
return has_function_call (e->e.retrn.ret_val);
|
||||||
|
case ex_horizontal:
|
||||||
|
return has_function_call (e->e.hop.vec);
|
||||||
case ex_error:
|
case ex_error:
|
||||||
case ex_state:
|
case ex_state:
|
||||||
case ex_label:
|
case ex_label:
|
||||||
|
@ -1873,6 +1904,7 @@ unary_expr (int op, expr_t *e)
|
||||||
case ex_vector:
|
case ex_vector:
|
||||||
case ex_alias:
|
case ex_alias:
|
||||||
case ex_assign:
|
case ex_assign:
|
||||||
|
case ex_horizontal:
|
||||||
{
|
{
|
||||||
expr_t *n = new_unary_expr (op, e);
|
expr_t *n = new_unary_expr (op, e);
|
||||||
|
|
||||||
|
@ -1965,6 +1997,7 @@ unary_expr (int op, expr_t *e)
|
||||||
case ex_alias:
|
case ex_alias:
|
||||||
case ex_address:
|
case ex_address:
|
||||||
case ex_assign:
|
case ex_assign:
|
||||||
|
case ex_horizontal:
|
||||||
if (options.code.progsversion == PROG_VERSION) {
|
if (options.code.progsversion == PROG_VERSION) {
|
||||||
return binary_expr (EQ, e, new_nil_expr ());
|
return binary_expr (EQ, e, new_nil_expr ());
|
||||||
} else {
|
} else {
|
||||||
|
@ -2053,6 +2086,7 @@ unary_expr (int op, expr_t *e)
|
||||||
case ex_vector:
|
case ex_vector:
|
||||||
case ex_alias:
|
case ex_alias:
|
||||||
case ex_assign:
|
case ex_assign:
|
||||||
|
case ex_horizontal:
|
||||||
bitnot_expr:
|
bitnot_expr:
|
||||||
if (options.code.progsversion == PROG_ID_VERSION) {
|
if (options.code.progsversion == PROG_ID_VERSION) {
|
||||||
expr_t *n1 = new_int_expr (-1);
|
expr_t *n1 = new_int_expr (-1);
|
||||||
|
|
|
@ -141,6 +141,7 @@ is_lvalue (const expr_t *expr)
|
||||||
case ex_adjstk:
|
case ex_adjstk:
|
||||||
case ex_with:
|
case ex_with:
|
||||||
case ex_args:
|
case ex_args:
|
||||||
|
case ex_horizontal:
|
||||||
break;
|
break;
|
||||||
case ex_count:
|
case ex_count:
|
||||||
internal_error (expr, "invalid expression");
|
internal_error (expr, "invalid expression");
|
||||||
|
|
|
@ -51,6 +51,7 @@ static expr_t *pointer_compare (int op, expr_t *e1, expr_t *e2);
|
||||||
static expr_t *func_compare (int op, expr_t *e1, expr_t *e2);
|
static expr_t *func_compare (int op, expr_t *e1, expr_t *e2);
|
||||||
static expr_t *inverse_multiply (int op, expr_t *e1, expr_t *e2);
|
static expr_t *inverse_multiply (int op, expr_t *e1, expr_t *e2);
|
||||||
static expr_t *double_compare (int op, expr_t *e1, expr_t *e2);
|
static expr_t *double_compare (int op, expr_t *e1, expr_t *e2);
|
||||||
|
static expr_t *vector_compare (int op, expr_t *e1, expr_t *e2);
|
||||||
|
|
||||||
static expr_type_t string_string[] = {
|
static expr_type_t string_string[] = {
|
||||||
{'+', &type_string},
|
{'+', &type_string},
|
||||||
|
@ -145,8 +146,8 @@ static expr_type_t vector_vector[] = {
|
||||||
{'+', &type_vector},
|
{'+', &type_vector},
|
||||||
{'-', &type_vector},
|
{'-', &type_vector},
|
||||||
{'*', &type_float},
|
{'*', &type_float},
|
||||||
{EQ, &type_int},
|
{EQ, 0, 0, 0, vector_compare},
|
||||||
{NE, &type_int},
|
{NE, 0, 0, 0, vector_compare},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -721,6 +722,22 @@ inverse_multiply (int op, expr_t *e1, expr_t *e2)
|
||||||
return binary_expr ('*', e1, binary_expr ('/', one, e2));
|
return binary_expr ('*', e1, binary_expr ('/', one, e2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static expr_t *
|
||||||
|
vector_compare (int op, expr_t *e1, expr_t *e2)
|
||||||
|
{
|
||||||
|
if (options.code.progsversion < PROG_VERSION) {
|
||||||
|
expr_t *e = new_binary_expr (op, e1, e2);
|
||||||
|
e->e.expr.type = &type_int;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
int hop = op == EQ ? '&' : '|';
|
||||||
|
e1 = new_alias_expr (&type_vec3, e1);
|
||||||
|
e2 = new_alias_expr (&type_vec3, e2);
|
||||||
|
expr_t *e = new_binary_expr (op, e1, e2);
|
||||||
|
e->e.expr.type = &type_ivec3;
|
||||||
|
return new_horizontal_expr (hop, e, &type_int);
|
||||||
|
}
|
||||||
|
|
||||||
static expr_t *
|
static expr_t *
|
||||||
double_compare (int op, expr_t *e1, expr_t *e2)
|
double_compare (int op, expr_t *e1, expr_t *e2)
|
||||||
{
|
{
|
||||||
|
|
|
@ -133,6 +133,7 @@ int yylex (void);
|
||||||
%left '&'
|
%left '&'
|
||||||
%left EQ NE
|
%left EQ NE
|
||||||
%left LT GT GE LE
|
%left LT GT GE LE
|
||||||
|
%token NAND NOR XNOR
|
||||||
// end of tokens common between qc and qp
|
// end of tokens common between qc and qp
|
||||||
|
|
||||||
%left SHL SHR
|
%left SHL SHR
|
||||||
|
|
|
@ -114,6 +114,7 @@ int yylex (void);
|
||||||
%left '&'
|
%left '&'
|
||||||
%left EQ NE
|
%left EQ NE
|
||||||
%left LT GT GE LE
|
%left LT GT GE LE
|
||||||
|
%token NAND NOR XNOR
|
||||||
// end of tokens common between qc and qp
|
// end of tokens common between qc and qp
|
||||||
|
|
||||||
%left <op> RELOP
|
%left <op> RELOP
|
||||||
|
|
|
@ -1666,6 +1666,59 @@ expr_uexpr (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
return sblock;
|
return sblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static sblock_t *
|
||||||
|
expr_horizontal (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
|
{
|
||||||
|
const char *opcode = "hops";
|
||||||
|
statement_t *s;
|
||||||
|
int hop;
|
||||||
|
type_t *res_type = e->e.hop.type;
|
||||||
|
type_t *vec_type = get_type (e->e.hop.vec);
|
||||||
|
|
||||||
|
switch (e->e.hop.op) {
|
||||||
|
case '&':
|
||||||
|
hop = 0;
|
||||||
|
break;
|
||||||
|
case '|':
|
||||||
|
hop = 1;
|
||||||
|
break;
|
||||||
|
case '^':
|
||||||
|
hop = 2;
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
if (is_integral (vec_type)) {
|
||||||
|
hop = 3;
|
||||||
|
} else {
|
||||||
|
hop = 7;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NAND:
|
||||||
|
hop = 4;
|
||||||
|
break;
|
||||||
|
case NOR:
|
||||||
|
hop = 5;
|
||||||
|
break;
|
||||||
|
case XNOR:
|
||||||
|
hop = 6;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
internal_error (e, "invalid horizontal op");
|
||||||
|
}
|
||||||
|
hop |= (type_width (vec_type) - 1) << 3;
|
||||||
|
hop |= (pr_type_size[vec_type->type] - 1) << 5;
|
||||||
|
|
||||||
|
s = new_statement (st_expr, opcode, e);
|
||||||
|
sblock = statement_subexpr (sblock, e->e.hop.vec, &s->opa);
|
||||||
|
s->opb = short_operand (hop, e);
|
||||||
|
if (!*op) {
|
||||||
|
*op = temp_operand (res_type, e);
|
||||||
|
}
|
||||||
|
s->opc = *op;
|
||||||
|
sblock_add_statement (sblock, s);
|
||||||
|
|
||||||
|
return sblock;
|
||||||
|
}
|
||||||
|
|
||||||
static sblock_t *
|
static sblock_t *
|
||||||
expr_def (sblock_t *sblock, expr_t *e, operand_t **op)
|
expr_def (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
{
|
{
|
||||||
|
@ -1826,6 +1879,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
[ex_block] = expr_block,
|
[ex_block] = expr_block,
|
||||||
[ex_expr] = expr_expr,
|
[ex_expr] = expr_expr,
|
||||||
[ex_uexpr] = expr_uexpr,
|
[ex_uexpr] = expr_uexpr,
|
||||||
|
[ex_horizontal] = expr_horizontal,
|
||||||
[ex_def] = expr_def,
|
[ex_def] = expr_def,
|
||||||
[ex_symbol] = expr_symbol,
|
[ex_symbol] = expr_symbol,
|
||||||
[ex_temp] = expr_temp,
|
[ex_temp] = expr_temp,
|
||||||
|
@ -1844,7 +1898,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e->type >= ex_count)
|
if (e->type >= ex_count)
|
||||||
internal_error (e, "bad sub-expression type");
|
internal_error (e, "bad sub-expression type: %d", e->type);
|
||||||
if (!sfuncs[e->type])
|
if (!sfuncs[e->type])
|
||||||
internal_error (e, "unexpected sub-expression type: %s",
|
internal_error (e, "unexpected sub-expression type: %s",
|
||||||
expr_names[e->type]);
|
expr_names[e->type]);
|
||||||
|
|
Loading…
Reference in a new issue