Don't require pr_boundscheck for quoth.

I don't know about other FTEqcc compiled progs, but quoth doesn't try to do
anything clever (all its denormals are either vars of the wrong type, or
-0.0).
This commit is contained in:
Bill Currie 2010-11-20 14:12:40 +09:00
parent 9d6fd32206
commit 3309f483b6
2 changed files with 35 additions and 20 deletions

View file

@ -539,6 +539,8 @@ PR_DumpState (progs_t *pr)
PR_StackTrace (pr);
}
#define ISDENORM(x) ((x) && !((x) & 0x7f800000))
static const char *
value_string (progs_t *pr, etype_t type, pr_type_t *val)
{
@ -611,7 +613,10 @@ value_string (progs_t *pr, etype_t type, pr_type_t *val)
case ev_void:
return "void";
case ev_float:
dsprintf (line, "%g", val->float_var);
if (ISDENORM (val->integer_var) && val->uinteger_var != 0x80000000)
dsprintf (line, "<%08x>", val->integer_var);
else
dsprintf (line, "%g", val->float_var);
break;
case ev_vector:
dsprintf (line, "'%g %g %g'",

View file

@ -1204,9 +1204,10 @@ check_branch (progs_t *pr, dstatement_t *st, opcode_t *op, short offset)
static inline void
check_global (progs_t *pr, dstatement_t *st, opcode_t *op, etype_t type,
unsigned short operand)
unsigned short operand, int check_denorm)
{
const char *msg;
ddef_t *def;
switch (type) {
case ev_short:
@ -1223,11 +1224,19 @@ check_global (progs_t *pr, dstatement_t *st, opcode_t *op, etype_t type,
msg = "out of bounds global index";
goto error;
}
if (type == ev_float)
if (ISDENORM (G_INT (pr, operand))
&& !pr->denorm_found) {
if (type != ev_float || !check_denorm)
break;
if (!ISDENORM (G_INT (pr, operand))
|| G_UINT(pr, operand) == 0x80000000)
break;
if ((def = PR_GlobalAtOfs (pr, operand))
&& (def->type & ~DEF_SAVEGLOBAL) != ev_float) {
// FTEqcc uses store.f parameters of most types :/
break;
}
if (!pr->denorm_found) {
pr->denorm_found = 1;
if (pr_boundscheck-> int_val) {
if (pr_boundscheck->int_val) {
Sys_Printf ("DENORMAL floats detected, these progs might "
"not work. Good luck.\n");
return;
@ -1305,7 +1314,7 @@ PR_Check_Opcodes (progs_t *pr)
switch (st->op) {
case OP_IF:
case OP_IFNOT:
check_global (pr, st, op, op->type_a, st->a);
check_global (pr, st, op, op->type_a, st->a, 1);
check_branch (pr, st, op, st->b);
break;
case OP_GOTO:
@ -1313,12 +1322,12 @@ PR_Check_Opcodes (progs_t *pr)
break;
case OP_DONE:
case OP_RETURN:
check_global (pr, st, op, ev_integer, st->a);
check_global (pr, st, op, ev_void, st->b);
check_global (pr, st, op, ev_void, st->c);
check_global (pr, st, op, ev_integer, st->a, 1);
check_global (pr, st, op, ev_void, st->b, 0);
check_global (pr, st, op, ev_void, st->c, 0);
break;
case OP_RCALL1:
check_global (pr, st, op, ev_void, st->c);
check_global (pr, st, op, ev_void, st->c, 1);
case OP_RCALL2:
case OP_RCALL3:
case OP_RCALL4:
@ -1327,9 +1336,9 @@ PR_Check_Opcodes (progs_t *pr)
case OP_RCALL7:
case OP_RCALL8:
if (st->op > OP_RCALL1)
check_global (pr, st, op, ev_integer, st->c);
check_global (pr, st, op, ev_integer, st->b);
check_global (pr, st, op, ev_func, st->a);
check_global (pr, st, op, ev_integer, st->c, 1);
check_global (pr, st, op, ev_integer, st->b, 1);
check_global (pr, st, op, ev_func, st->a, 1);
break;
case OP_STATE:
case OP_STATE_F:
@ -1337,18 +1346,19 @@ PR_Check_Opcodes (progs_t *pr)
PR_Error (pr, "PR_Check_Opcodes: %s used with missing "
"fields or globals", op->opname);
}
check_global (pr, st, op, op->type_a, st->a);
check_global (pr, st, op, op->type_b, st->b);
check_global (pr, st, op, op->type_c, st->c);
check_global (pr, st, op, op->type_a, st->a, 1);
check_global (pr, st, op, op->type_b, st->b, 1);
check_global (pr, st, op, op->type_c, st->c, 1);
break;
case OP_MOVE:
check_global_size (pr, st, op, st->b, st->a);
check_global_size (pr, st, op, st->b, st->c);
break;
default:
check_global (pr, st, op, op->type_a, st->a);
check_global (pr, st, op, op->type_b, st->b);
check_global (pr, st, op, op->type_c, st->c);
check_global (pr, st, op, op->type_a, st->a, 1);
check_global (pr, st, op, op->type_b, st->b,
op->opcode != OP_STORE_F);
check_global (pr, st, op, op->type_c, st->c, 0);
break;
}
}