mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-04-11 20:03:11 +00:00
[qfcc] Use columns for selecting instructions
Now both width and columns must match for an instruction to be selected. Found a few errors in my opcode specs, and some minor goofs in the type system (really just overthinking things when I added matrices).
This commit is contained in:
parent
9c394c02f8
commit
43716e5d6a
4 changed files with 70 additions and 40 deletions
|
@ -70,6 +70,7 @@ typedef struct operand_s {
|
|||
const struct type_s *type; ///< possibly override def's/nil's type
|
||||
int size; ///< for structures
|
||||
int width; ///< for SIMD selection
|
||||
int columns; ///< for matrix selection
|
||||
const struct expr_s *expr; ///< expression generating this operand
|
||||
void *return_addr; ///< who created this operand
|
||||
union {
|
||||
|
|
|
@ -142,6 +142,8 @@ rua_get_hash (const void *_op, void *_tab)
|
|||
+ ROTL (~op->types[2], 24);
|
||||
hash += ROTL (~op->widths[0], 12) + ROTL (~op->widths[1], 20)
|
||||
+ ROTL (~op->widths[2], 28);
|
||||
hash += ROTL (~op->columns[0], 12) + ROTL (~op->columns[1], 20)
|
||||
+ ROTL (~op->columns[2], 28);
|
||||
return hash + Hash_String (op->opname);
|
||||
}
|
||||
|
||||
|
@ -158,6 +160,9 @@ rua_compare (const void *_opa, const void *_opb, void *unused)
|
|||
cmp &= (opa->widths[0] == opb->widths[0])
|
||||
&& (opa->widths[1] == opb->widths[1])
|
||||
&& (opa->widths[2] == opb->widths[2]);
|
||||
cmp &= (opa->columns[0] == opb->columns[0])
|
||||
&& (opa->columns[1] == opb->columns[1])
|
||||
&& (opa->columns[2] == opb->columns[2]);
|
||||
return cmp && !strcmp (opa->opname, opb->opname);
|
||||
}
|
||||
|
||||
|
@ -177,7 +182,7 @@ check_operand_type (etype_t ot1, etype_t ot2)
|
|||
}
|
||||
|
||||
static int
|
||||
check_operand_width (int ow1, int ow2)
|
||||
check_operand_wc (int ow1, int ow2)
|
||||
{
|
||||
return (ow1 == -1 || ow1 == ow2);
|
||||
}
|
||||
|
@ -303,26 +308,25 @@ operand_width (const char *opname, operand_t *op)
|
|||
}
|
||||
return op->width;
|
||||
}
|
||||
#if 0
|
||||
if (!strcmp (name, "swizzle")) {
|
||||
adjust_swizzle_op (&search_op, 0);
|
||||
adjust_swizzle_op (&search_op, 2);
|
||||
}
|
||||
static void
|
||||
adjust_swizzle_op (opcode_t *op, int opind)
|
||||
|
||||
static int
|
||||
operand_columns (const char *opname, operand_t *op)
|
||||
{
|
||||
// swizzle instructions require both operands to be 4 components (4 or 8
|
||||
// words) in size with the same alignment.
|
||||
op->widths[opind] = 4;
|
||||
if (pr_type_size[op->types[opind]] == 1) {
|
||||
op->types[opind] = ev_float;
|
||||
} else if (pr_type_size[op->types[opind]] == 2) {
|
||||
op->types[opind] = ev_double;
|
||||
} else {
|
||||
internal_error (0, "unexpected swizzle op size");
|
||||
if (!op) {
|
||||
return 0;
|
||||
}
|
||||
return op->columns;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
print_search_op (opcode_t *op)
|
||||
{
|
||||
printf ("%s [%s %d %d] [%s %d %d] [%s %d %d]\n", op->opname,
|
||||
pr_type_name[op->types[0]], op->widths[0], op->columns[0],
|
||||
pr_type_name[op->types[1]], op->widths[1], op->columns[1],
|
||||
pr_type_name[op->types[2]], op->widths[2], op->columns[2]);
|
||||
}
|
||||
|
||||
static opcode_t *
|
||||
rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b,
|
||||
operand_t *op_c)
|
||||
|
@ -371,18 +375,20 @@ rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b,
|
|||
operand_width ("", op_b),
|
||||
operand_width (opname_c, op_c),
|
||||
},
|
||||
.columns = {
|
||||
operand_columns (opname_a, op_a),
|
||||
operand_columns ("", op_b),
|
||||
operand_columns (opname_c, op_c),
|
||||
},
|
||||
};
|
||||
opcode_t *op;
|
||||
opcode_t *sop;
|
||||
void **op_list;
|
||||
int i;
|
||||
|
||||
#if 0
|
||||
printf ("%s [%s %d] [%s %d] [%s %d]\n", search_op.opname,
|
||||
pr_type_name[search_op.types[0]], search_op.widths[0],
|
||||
pr_type_name[search_op.types[1]], search_op.widths[1],
|
||||
pr_type_name[search_op.types[2]], search_op.widths[2]);
|
||||
#endif
|
||||
if (0) {
|
||||
print_search_op (&search_op);
|
||||
}
|
||||
op = Hash_FindElement (rua_opcode_type_table, &search_op);
|
||||
if (op)
|
||||
return op;
|
||||
|
@ -396,15 +402,15 @@ rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b,
|
|||
&& check_operand_type (sop->types[2], search_op.types[2]))) {
|
||||
continue;
|
||||
}
|
||||
if (!(check_operand_width (sop->widths[0], search_op.widths[0])
|
||||
&& check_operand_width (sop->widths[1], search_op.widths[1])
|
||||
&& check_operand_width (sop->widths[2], search_op.widths[2]))) {
|
||||
#if 0
|
||||
printf ("%s [%s %d] [%s %d] [%s %d]\n", sop->opname,
|
||||
pr_type_name[sop->types[0]], sop->widths[0],
|
||||
pr_type_name[sop->types[1]], sop->widths[1],
|
||||
pr_type_name[sop->types[2]], sop->widths[2]);
|
||||
#endif
|
||||
if (!(check_operand_wc (sop->widths[0], search_op.widths[0])
|
||||
&& check_operand_wc (sop->widths[1], search_op.widths[1])
|
||||
&& check_operand_wc (sop->widths[2], search_op.widths[2]))
|
||||
|| !(check_operand_wc (sop->columns[0], search_op.columns[0])
|
||||
&& check_operand_wc (sop->columns[1], search_op.columns[1])
|
||||
&& check_operand_wc (sop->columns[2], search_op.columns[2]))) {
|
||||
if (0) {
|
||||
printf (" "); print_search_op (sop);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
op = sop;
|
||||
|
|
|
@ -362,6 +362,7 @@ nil_operand (const type_t *type, const expr_t *expr)
|
|||
op->type = type;
|
||||
op->size = type_size (type);
|
||||
op->width = type_width (type);
|
||||
op->columns = type_cols (type);
|
||||
return op;
|
||||
}
|
||||
|
||||
|
@ -376,6 +377,7 @@ def_operand (def_t *def, const type_t *type, const expr_t *expr)
|
|||
op->type = type;
|
||||
op->size = type_size (type);
|
||||
op->width = type_width (type);
|
||||
op->columns = type_cols (type);
|
||||
op->def = def;
|
||||
return op;
|
||||
}
|
||||
|
@ -401,6 +403,7 @@ value_operand (ex_value_t *value, const expr_t *expr)
|
|||
op->type = value->type;
|
||||
op->size = type_size (value->type);
|
||||
op->width = type_width (value->type);
|
||||
op->columns = type_cols (value->type);
|
||||
op->value = value;
|
||||
return op;
|
||||
}
|
||||
|
@ -414,6 +417,7 @@ temp_operand (const type_t *type, const expr_t *expr)
|
|||
op->type = type;
|
||||
op->size = type_size (type);
|
||||
op->width = type_width (type);
|
||||
op->columns = type_cols (type);
|
||||
return op;
|
||||
}
|
||||
|
||||
|
@ -550,6 +554,7 @@ alias_operand (const type_t *type, operand_t *op, const expr_t *expr)
|
|||
aop->type = type;
|
||||
aop->size = type_size (type);
|
||||
aop->width = type_width (type);
|
||||
aop->columns = type_cols (type);
|
||||
return aop;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,8 @@
|
|||
.alignment = PR_ALIGNOF(t), \
|
||||
.width = __builtin_choose_expr (ev_##t == ev_short \
|
||||
|| ev_##t == ev_ushort, 0, 1), \
|
||||
.columns = 1, \
|
||||
.columns = __builtin_choose_expr (ev_##t == ev_short \
|
||||
|| ev_##t == ev_ushort, 0, 1), \
|
||||
.meta = ty_basic, \
|
||||
{{ __builtin_choose_expr (ev_##t == ev_field \
|
||||
|| ev_##t == ev_func \
|
||||
|
@ -1899,13 +1900,30 @@ type_width (const type_t *type)
|
|||
int
|
||||
type_cols (const type_t *type)
|
||||
{
|
||||
if (is_matrix (type)) {
|
||||
type = unalias_type (type);
|
||||
return type->columns;
|
||||
} else {
|
||||
// non-matrices have only 1 column
|
||||
return 1;
|
||||
switch (type->meta) {
|
||||
case ty_bool:
|
||||
case ty_basic:
|
||||
return type->columns;
|
||||
case ty_handle:
|
||||
case ty_struct:
|
||||
case ty_union:
|
||||
return 1;
|
||||
case ty_enum:
|
||||
if (!type->symtab)
|
||||
return 0;
|
||||
return type_cols (&type_int);
|
||||
case ty_array:
|
||||
return type_cols (type->array.type);
|
||||
case ty_class:
|
||||
return 1;
|
||||
case ty_alias:
|
||||
return type_cols (type->alias.aux_type);
|
||||
case ty_algebra:
|
||||
return 1;
|
||||
case ty_meta_count:
|
||||
break;
|
||||
}
|
||||
internal_error (0, "invalid type meta: %d", type->meta);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
Loading…
Reference in a new issue