diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index ca53c6da0..8e95ce929 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -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 { diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 451bd41b9..817e07731 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -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; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 9c5441f94..7a8ea7065 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -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; } diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 6c6cc92cc..86d047fe0 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -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