mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 07:11:41 +00:00
[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:
parent
8a0246c910
commit
29a57b7128
6 changed files with 62 additions and 52 deletions
|
@ -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 = {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 ();
|
||||||
|
|
Loading…
Reference in a new issue