[qfcc] Map uint to int for some intructions

Many math instructions don't care about the difference between signed
and unsigned operands and are thus specified using int, but need to be
usable with uint. div is NOT mapped because there is a difference:
0x8000 / 2 (16-bit) is 0x4000 unsigned but 0xc000 signed, and 0x8000 /
0xfffe is 0 unsigned and 0x4000 signed. This means I'll need to add some
more instructions. Not sure what to do about % and %% though as that's a
lot of instructions (12).
This commit is contained in:
Bill Currie 2022-01-30 22:40:37 +09:00
parent 8dc4a0ea80
commit edf7a781fd

View file

@ -230,8 +230,30 @@ v6p_opcode_find (const char *name, operand_t *op_a, operand_t *op_b,
return op;
}
static etype_t
operand_type (operand_t *op)
static const char *unsigned_demote_ops[] = {
"add",
"bitand",
"bitnot",
"bitor",
"bitxor",
"eq",
"ifnz",
"ifz",
"mul",
"ne",
"sub",
};
static int
ud_compare (const void *_a, const void *_b)
{
const char *a = _a;
const char *b = *(const char **)_b;
return strcmp (a, b);
}
static etype_t __attribute__((pure))
operand_type (const operand_t *op, const char *name)
{
if (!op) {
return ev_invalid;
@ -240,6 +262,20 @@ operand_type (operand_t *op)
if (type == ev_vector || type == ev_quaternion) {
return ev_float;
}
if (type == ev_uint || type == ev_ulong) {
if (bsearch (name, unsigned_demote_ops,
sizeof (unsigned_demote_ops)
/ sizeof (unsigned_demote_ops[0]),
sizeof (unsigned_demote_ops[0]),
ud_compare)) {
if (type == ev_uint) {
type = ev_int;
}
if (type == ev_ulong) {
type = ev_long;
}
}
}
return type;
}
@ -266,9 +302,9 @@ rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b,
opcode_t search_op = {
.opname = name,
.types = {
operand_type (op_a),
operand_type (op_b),
operand_type (op_c),
operand_type (op_a, name),
operand_type (op_b, name),
operand_type (op_c, name),
},
.widths = {
operand_width (op_a),