mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-24 19:23:00 +00:00
[qfcc] Support the new memset instructions
This commit is contained in:
parent
6ca85d770d
commit
be5f11f33a
4 changed files with 73 additions and 1 deletions
|
@ -56,6 +56,7 @@ typedef enum {
|
|||
ex_nil, ///< umm, nil, null. nuff said (0 of any type)
|
||||
ex_value, ///< constant value (::ex_value_t)
|
||||
ex_compound, ///< compound initializer
|
||||
ex_memset, ///< memset needs three params...
|
||||
} expr_type;
|
||||
|
||||
/** Binary and unary expressions.
|
||||
|
@ -142,6 +143,12 @@ typedef struct {
|
|||
struct expr_s *e;
|
||||
} ex_bool_t;
|
||||
|
||||
typedef struct ex_memset_s {
|
||||
struct expr_s *dst;
|
||||
struct expr_s *val;
|
||||
struct expr_s *count;
|
||||
} ex_memset_t;
|
||||
|
||||
/** State expression used for think function state-machines.
|
||||
|
||||
State expressions are of the form <code>[framenum, nextthink]</code>
|
||||
|
@ -225,6 +232,7 @@ typedef struct expr_s {
|
|||
ex_vector_t vector; ///< vector expression list
|
||||
ex_value_t *value; ///< constant value
|
||||
element_chain_t compound; ///< compound initializer
|
||||
ex_memset_t memset; ///< memset expr params
|
||||
} e;
|
||||
} expr_t;
|
||||
|
||||
|
@ -640,6 +648,9 @@ expr_t *new_param_expr (struct type_s *type, int num);
|
|||
expr_t *new_move_expr (expr_t *e1, expr_t *e2, struct type_s *type,
|
||||
int indirect);
|
||||
|
||||
expr_t *new_memset_expr (expr_t *dst, expr_t *val, expr_t *count);
|
||||
|
||||
|
||||
/** Convert a name to an expression of the appropriate type.
|
||||
|
||||
Converts the expression in-place. If the exprssion is not a name
|
||||
|
|
|
@ -214,6 +214,7 @@ get_type (expr_t *e)
|
|||
convert_name (e);
|
||||
switch (e->type) {
|
||||
case ex_labelref:
|
||||
case ex_memset:
|
||||
return &type_void;
|
||||
case ex_label:
|
||||
case ex_error:
|
||||
|
@ -436,6 +437,13 @@ copy_expr (expr_t *e)
|
|||
append_element (n, new_element (i->expr, i->symbol));
|
||||
}
|
||||
return n;
|
||||
case ex_memset:
|
||||
n = new_expr ();
|
||||
*n = *e;
|
||||
n->e.memset.dst = copy_expr (e->e.memset.dst);
|
||||
n->e.memset.val = copy_expr (e->e.memset.val);
|
||||
n->e.memset.count = copy_expr (e->e.memset.count);
|
||||
return n;
|
||||
}
|
||||
internal_error (e, "invalid expression");
|
||||
}
|
||||
|
@ -1171,6 +1179,27 @@ new_move_expr (expr_t *e1, expr_t *e2, type_t *type, int indirect)
|
|||
return e;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_memset_expr (expr_t *dst, expr_t *val, expr_t *count)
|
||||
{
|
||||
expr_t *e;
|
||||
if (!is_pointer (get_type (dst))) {
|
||||
return error (dst, "incorrect destination type for memset");
|
||||
}
|
||||
if (!is_scalar (get_type (val))) {
|
||||
return error (val, "memset value must be a scalar");
|
||||
}
|
||||
if (!is_integral (get_type (count))) {
|
||||
return error (val, "memset count must be integral");
|
||||
}
|
||||
e = new_expr ();
|
||||
e->type = ex_memset;
|
||||
e->e.memset.dst = dst;
|
||||
e->e.memset.val = val;
|
||||
e->e.memset.count = count;
|
||||
return e;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
append_expr (expr_t *block, expr_t *e)
|
||||
{
|
||||
|
@ -1508,6 +1537,7 @@ unary_expr (int op, expr_t *e)
|
|||
case ex_labelref:
|
||||
case ex_state:
|
||||
case ex_compound:
|
||||
case ex_memset:
|
||||
internal_error (e, 0);
|
||||
case ex_uexpr:
|
||||
if (e->e.expr.op == '-')
|
||||
|
@ -1575,6 +1605,7 @@ unary_expr (int op, expr_t *e)
|
|||
case ex_labelref:
|
||||
case ex_state:
|
||||
case ex_compound:
|
||||
case ex_memset:
|
||||
internal_error (e, 0);
|
||||
case ex_bool:
|
||||
return new_bool_expr (e->e.bool.false_list,
|
||||
|
@ -1641,6 +1672,7 @@ unary_expr (int op, expr_t *e)
|
|||
case ex_labelref:
|
||||
case ex_state:
|
||||
case ex_compound:
|
||||
case ex_memset:
|
||||
internal_error (e, 0);
|
||||
case ex_uexpr:
|
||||
if (e->e.expr.op == '~')
|
||||
|
|
|
@ -123,6 +123,7 @@ check_valid_lvalue (expr_t *expr)
|
|||
return check_valid_lvalue (expr->e.expr.e1);
|
||||
}
|
||||
break;
|
||||
case ex_memset:
|
||||
case ex_compound:
|
||||
case ex_state:
|
||||
case ex_bool:
|
||||
|
|
|
@ -1438,6 +1438,32 @@ statement_uexpr (sblock_t *sblock, expr_t *e)
|
|||
return sblock;
|
||||
}
|
||||
|
||||
static sblock_t *
|
||||
statement_memset (sblock_t *sblock, expr_t *e)
|
||||
{
|
||||
expr_t *dst = e->e.memset.dst;
|
||||
expr_t *val = e->e.memset.val;
|
||||
expr_t *count = e->e.memset.count;
|
||||
const char *opcode = "<MEMSET>";
|
||||
statement_t *s;
|
||||
|
||||
if (is_constant (count)) {
|
||||
if (is_integer (get_type (count))
|
||||
&& (unsigned) expr_integer (count) < 0x10000) {
|
||||
count = new_short_expr (expr_integer (count));
|
||||
}
|
||||
if (is_uinteger (get_type (count)) && expr_integer (count) < 0x10000) {
|
||||
count = new_short_expr (expr_uinteger (count));
|
||||
}
|
||||
}
|
||||
s = new_statement (st_move, opcode, e);
|
||||
sblock = statement_subexpr (sblock, dst, &s->opc);
|
||||
sblock = statement_subexpr (sblock, count, &s->opb);
|
||||
sblock = statement_subexpr (sblock, val, &s->opa);
|
||||
sblock_add_statement (sblock, s);
|
||||
return sblock;
|
||||
}
|
||||
|
||||
static sblock_t *
|
||||
statement_nonexec (sblock_t *sblock, expr_t *e)
|
||||
{
|
||||
|
@ -1463,10 +1489,12 @@ statement_slist (sblock_t *sblock, expr_t *e)
|
|||
statement_nonexec, // ex_vector
|
||||
statement_nonexec, // ex_nil
|
||||
statement_nonexec, // ex_value
|
||||
0, // ex_compound
|
||||
statement_memset,
|
||||
};
|
||||
|
||||
for (/**/; e; e = e->next) {
|
||||
if (e->type > ex_value)
|
||||
if (e->type > ex_memset)
|
||||
internal_error (e, "bad expression type");
|
||||
sblock = sfuncs[e->type] (sblock, e);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue