[qfcc] Correct handling of 64-bit comparisons

While the progs engine itself implements the instructions correctly, the
opcode specs (and thus qfcc) treated the results as 32-bit (which was,
really, a hidden fixme, it seems).
This commit is contained in:
Bill Currie 2023-08-26 22:57:11 +09:00
parent 8a0246c910
commit 29a57b7128
6 changed files with 62 additions and 52 deletions

View file

@ -155,11 +155,12 @@ compare_formats = {
"mnemonic": "{op_cmp[ccc]}.{cmp_type[tt]}", "mnemonic": "{op_cmp[ccc]}.{cmp_type[tt]}",
"opname": "{op_cmp[ccc]}", "opname": "{op_cmp[ccc]}",
"widths": "{ss+1}, {ss+1}, {ss+1}", "widths": "{ss+1}, {ss+1}, {ss+1}",
"types": "{cmp_types[tt]}, {cmp_types[tt]}, ev_int", "types": "{cmp_types[tt]}, {cmp_types[tt]}, {res_types[tt & 2]}",
"args": { "args": {
"op_cmp": compare_ccc, "op_cmp": compare_ccc,
"cmp_type": type_tt, "cmp_type": type_tt,
"cmp_types": etype_tt, "cmp_types": etype_tt,
"res_types": etype_tt,
}, },
} }
compare2_formats = { compare2_formats = {

View file

@ -323,7 +323,7 @@ do_op_double (int op, expr_t *e, expr_t *e1, expr_t *e2)
e->e.expr.e2 = e2 = conv; e->e.expr.e2 = e2 = conv;
} }
if (is_compare (op) || is_logic (op)) { if (is_compare (op) || is_logic (op)) {
type = &type_int; type = int_type (get_type (e));
} }
e->e.expr.type = type; e->e.expr.type = type;
@ -1736,8 +1736,10 @@ fold_constants (expr_t *e)
t2 = extract_type (e2); t2 = extract_type (e2);
if (t1 >= ev_type_count || t2 >= ev_type_count if (t1 >= ev_type_count || t2 >= ev_type_count
|| !do_op[t1] || !do_op[t1][t2]) || !do_op[t1] || !do_op[t1][t2]) {
internal_error (e, "invalid type %d %d", t1, t2); debug (e, "unhandled type %d %d", t1, t2);
return e;
}
return do_op[t1][t2] (op, e, e1, e2); return do_op[t1][t2] (op, e, e1, e2);
} }
return e; return e;

View file

@ -348,12 +348,12 @@ static expr_type_t int_double[] = {
{'/', &type_double, &type_double, 0}, {'/', &type_double, &type_double, 0},
{'%', &type_double, &type_double, 0}, {'%', &type_double, &type_double, 0},
{MOD, &type_double, &type_double, 0}, {MOD, &type_double, &type_double, 0},
{EQ, &type_int, &type_double, 0}, {EQ, &type_long, &type_double, 0},
{NE, &type_int, &type_double, 0}, {NE, &type_long, &type_double, 0},
{LE, &type_int, &type_double, 0}, {LE, &type_long, &type_double, 0},
{GE, &type_int, &type_double, 0}, {GE, &type_long, &type_double, 0},
{LT, &type_int, &type_double, 0}, {LT, &type_long, &type_double, 0},
{GT, &type_int, &type_double, 0}, {GT, &type_long, &type_double, 0},
{0, 0} {0, 0}
}; };
@ -526,12 +526,12 @@ static expr_type_t double_double[] = {
{'/', &type_double}, {'/', &type_double},
{'%', &type_double}, {'%', &type_double},
{MOD, &type_double}, {MOD, &type_double},
{EQ, &type_int}, {EQ, &type_long},
{NE, &type_int}, {NE, &type_long},
{LE, &type_int}, {LE, &type_long},
{GE, &type_int}, {GE, &type_long},
{LT, &type_int}, {LT, &type_long},
{GT, &type_int}, {GT, &type_long},
{0, 0} {0, 0}
}; };
@ -547,33 +547,33 @@ static expr_type_t long_long[] = {
{MOD, &type_long}, {MOD, &type_long},
{SHL, &type_long}, {SHL, &type_long},
{SHR, &type_long}, {SHR, &type_long},
{EQ, &type_int}, {EQ, &type_long},
{NE, &type_int}, {NE, &type_long},
{LE, &type_int}, {LE, &type_long},
{GE, &type_int}, {GE, &type_long},
{LT, &type_int}, {LT, &type_long},
{GT, &type_int}, {GT, &type_long},
{0, 0} {0, 0}
}; };
static expr_type_t ulong_ulong[] = { static expr_type_t ulong_ulong[] = {
{'+', &type_long}, {'+', &type_ulong},
{'-', &type_long}, {'-', &type_ulong},
{'*', &type_long}, {'*', &type_ulong},
{'/', &type_long}, {'/', &type_ulong},
{'&', &type_long}, {'&', &type_ulong},
{'|', &type_long}, {'|', &type_ulong},
{'^', &type_long}, {'^', &type_ulong},
{'%', &type_long}, {'%', &type_ulong},
{MOD, &type_long}, {MOD, &type_ulong},
{SHL, &type_long}, {SHL, &type_ulong},
{SHR, &type_long}, {SHR, &type_ulong},
{EQ, &type_int}, {EQ, &type_long},
{NE, &type_int}, {NE, &type_long},
{LE, &type_int}, {LE, &type_long},
{GE, &type_int}, {GE, &type_long},
{LT, &type_int}, {LT, &type_long},
{GT, &type_int}, {GT, &type_long},
{0, 0} {0, 0}
}; };
@ -908,7 +908,7 @@ double_compare (int op, expr_t *e1, expr_t *e2)
e1 = cast_expr (&type_double, e1); e1 = cast_expr (&type_double, e1);
} }
e = new_binary_expr (op, e1, e2); e = new_binary_expr (op, e1, e2);
e->e.expr.type = &type_int; e->e.expr.type = &type_long;
return e; return e;
} }
@ -1221,6 +1221,9 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
// both widths are the same at this point // both widths are the same at this point
if (t1->width > 1) { if (t1->width > 1) {
e = new_binary_expr (op, e1, e2); e = new_binary_expr (op, e1, e2);
if (is_compare (op)) {
t1 = int_type (t1);
}
e->e.expr.type = t1; e->e.expr.type = t1;
return e; return e;
} }

View file

@ -96,8 +96,10 @@ test_expr (expr_t *e)
break; break;
case ev_long: case ev_long:
case ev_ulong: case ev_ulong:
e = new_alias_expr (&type_ivec2, e);
return new_horizontal_expr ('|', e, &type_int);
case ev_ushort: case ev_ushort:
internal_error (e, "long not implemented"); internal_error (e, "ushort not implemented");
case ev_uint: case ev_uint:
case ev_int: case ev_int:
case ev_short: case ev_short:
@ -123,8 +125,9 @@ test_expr (expr_t *e)
new = new_float_expr (0); new = new_float_expr (0);
break; break;
case ev_double: case ev_double:
new = new_double_expr (0); new = expr_file_line (new_double_expr (0), e);
break; new = expr_file_line (binary_expr (NE, e, new), e);
return test_expr (new);
case ev_vector: case ev_vector:
new = new_vector_expr (zero); new = new_vector_expr (zero);
break; break;

View file

@ -138,7 +138,8 @@ cast_expr (type_t *dstType, expr_t *e)
} }
if (is_constant (e) && is_math (dstType) && is_math (srcType)) { if (is_constant (e) && is_math (dstType) && is_math (srcType)) {
return cast_math (dstType, srcType, e); return cast_math (dstType, srcType, e);
} else if (is_integral (dstType) && is_integral (srcType)) { } else if (is_integral (dstType) && is_integral (srcType)
&& type_size (dstType) == type_size (srcType)) {
c = new_alias_expr (dstType, e); c = new_alias_expr (dstType, e);
} else if (is_scalar (dstType) && is_scalar (srcType)) { } else if (is_scalar (dstType) && is_scalar (srcType)) {
c = new_unary_expr ('C', e); c = new_unary_expr ('C', e);

View file

@ -6,7 +6,7 @@ union {
int i[2]; int i[2];
} type_pun; } type_pun;
int long
test_format () test_format ()
{ {
int fail = 0; int fail = 0;
@ -17,10 +17,10 @@ test_format ()
return fail; return fail;
} }
int long
test_constant () test_constant ()
{ {
int fail = 0; long fail = 0;
double a, b, c, d, e; double a, b, c, d, e;
a = 1; a = 1;
b = 2.0; b = 2.0;
@ -40,10 +40,10 @@ double greater_equal = 3;
double less_equal = 5; double less_equal = 5;
double greater = 5; double greater = 5;
int long
test_copare () test_copare ()
{ {
int fail = 0; long fail = 0;
fail |= !(less < greater); fail |= !(less < greater);
fail |= (less > greater); fail |= (less > greater);
@ -75,10 +75,10 @@ test_copare ()
return fail; return fail;
} }
int long
test_ops () test_ops ()
{ {
int fail = 0; long fail = 0;
double a = 6.25, b = 2.375; double a = 6.25, b = 2.375;
double c; double c;
@ -98,7 +98,7 @@ test_ops ()
int int
main () main ()
{ {
int fail = 0; long fail = 0;
fail |= test_format (); fail |= test_format ();
fail |= test_constant (); fail |= test_constant ();
fail |= test_ops (); fail |= test_ops ();