[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:
Bill Currie 2024-11-26 10:45:20 +09:00
parent 9c394c02f8
commit 43716e5d6a
4 changed files with 70 additions and 40 deletions

View file

@ -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 {

View file

@ -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;

View file

@ -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;
}

View file

@ -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