Added reporting of division by zero errors rather than crashing

This commit is contained in:
Andrew Alderwick 2021-06-08 22:58:02 +01:00
parent 6bf7e7f7a1
commit 064f7745d4
4 changed files with 127 additions and 28 deletions

View File

@ -72,9 +72,15 @@ pop_push = function(k, n, s)
return nil
end
end
local indented_block
indented_block = function(s)
s = s:gsub('^%{ *', '{\n'):gsub('\n', '\n\t'):gsub('\t%} *$', '}\n')
s = s:gsub('\n[^\n]+%.error = [^\n]+', '%0\n#ifndef NO_STACK_CHECKS\n\tgoto error;\n#endif')
return s
end
local process
process = function(body)
local out_body = body:gsub('^%{ *', ''):gsub(' *%}$', ''):gsub('; ', ';\n'):gsub('(%a+)(%d+)(%b())', pop_push)
local out_body = body:gsub('^%{ *', ''):gsub(' *%}$', ''):gsub('; ', ';\n'):gsub('%b{} *', indented_block):gsub('(%a+)(%d+)(%b())', pop_push)
local in_ifdef = false
local _list_0 = {
'src',
@ -132,6 +138,8 @@ for l in assert(io.lines('src/uxn.c')) do
if replacements[name] then
body = replacements[name]
end
body = body:gsub('u%-%>src%-%>', 'src.')
body = body:gsub('u%-%>dst%-%>', 'dst.')
body = body:gsub('u%-%>src', 'src')
body = body:gsub('u%-%>dst', 'dst')
top = {
@ -278,6 +286,7 @@ See etc/mkuxn-fast.moon for instructions.
*/
]])
wanted = true
while true do
local _continue_0 = false
repeat
@ -287,9 +296,19 @@ See etc/mkuxn-fast.moon for instructions.
break
end
if l == '/* Stack */' then
wanted = false
end
if l:match('errors%[%]') then
_with_0:write('\n#ifndef NO_STACK_CHECKS\n')
wanted = true
end
if wanted then
_with_0:write(('%s\n'):format(l))
end
if l == '}' then
_with_0:write('#endif\n\n')
break
end
_with_0:write(('%s\n'):format(l))
_continue_0 = true
until true
if not _continue_0 then
@ -338,12 +357,10 @@ evaluxn(Uxn *u, Uint16 vec)
return 1;
#ifndef NO_STACK_CHECKS
error:
printf("Halted: %s-stack %sflow#%04x, at 0x%04x\n",
u->wst.error ? "Working" : "Return",
((u->wst.error | u->rst.error) & 2) ? "over" : "under",
instr,
u->ram.ptr);
return 0;
if(u->wst.error)
return haltuxn(u, u->wst.error, "Working-stack", instr);
else
return haltuxn(u, u->rst.error, "Return-stack", instr);
#endif
}

View File

@ -77,8 +77,13 @@ pop_push = (k, n, s) ->
else
nil
indented_block = (s) ->
s = s\gsub('^%{ *', '{\n')\gsub('\n', '\n\t')\gsub('\t%} *$', '}\n')
s = s\gsub('\n[^\n]+%.error = [^\n]+', '%0\n#ifndef NO_STACK_CHECKS\n\tgoto error;\n#endif')
s
process = (body) ->
out_body = body\gsub('^%{ *', '')\gsub(' *%}$', '')\gsub('; ', ';\n')\gsub '(%a+)(%d+)(%b())', pop_push
out_body = body\gsub('^%{ *', '')\gsub(' *%}$', '')\gsub('; ', ';\n')\gsub('%b{} *', indented_block)\gsub '(%a+)(%d+)(%b())', pop_push
in_ifdef = false
for k in *{'src', 'dst'}
if bottom[k] != 0
@ -115,6 +120,8 @@ for l in assert io.lines 'src/uxn.c'
continue
if replacements[name]
body = replacements[name]
body = body\gsub 'u%-%>src%-%>', 'src.'
body = body\gsub 'u%-%>dst%-%>', 'dst.'
body = body\gsub 'u%-%>src', 'src'
body = body\gsub 'u%-%>dst', 'dst'
top = { src: 0, dst: 0 }
@ -200,13 +207,21 @@ See etc/mkuxn-fast.moon for instructions.
*/
]]
wanted = true
while true
l = f\read '*l'
if l\match' push' or l\match'[ *]pop'
continue
if l == '/* Stack */'
wanted = false
if l\match 'errors%[%]'
\write '\n#ifndef NO_STACK_CHECKS\n'
wanted = true
if wanted
\write '%s\n'\format l
if l == '}'
\write '#endif\n\n'
break
\write '%s\n'\format l
\write [[
/* clang-format on */
@ -238,12 +253,10 @@ evaluxn(Uxn *u, Uint16 vec)
return 1;
#ifndef NO_STACK_CHECKS
error:
printf("Halted: %s-stack %sflow#%04x, at 0x%04x\n",
u->wst.error ? "Working" : "Return",
((u->wst.error | u->rst.error) & 2) ? "over" : "under",
instr,
u->ram.ptr);
return 0;
if(u->wst.error)
return haltuxn(u, u->wst.error, "Working-stack", instr);
else
return haltuxn(u, u->rst.error, "Return-stack", instr);
#endif
}

View File

@ -34,6 +34,19 @@ void mempoke16(Uint8 *m, Uint16 a, Uint16 b) { mempoke8(m, a, b >> 8); mempoke
Uint16 mempeek16(Uint8 *m, Uint16 a) { return (mempeek8(m, a) << 8) + mempeek8(m, a + 1); }
void devpoke16(Device *d, Uint8 a, Uint16 b) { devpoke8(d, a, b >> 8); devpoke8(d, a + 1, b); }
Uint16 devpeek16(Device *d, Uint16 a) { return (devpeek8(d, a) << 8) + devpeek8(d, a + 1); }
#ifndef NO_STACK_CHECKS
static const char *errors[] = {"underflow", "overflow", "division by zero"};
int
haltuxn(Uxn *u, Uint8 error, char *name, int id)
{
printf("Halted: %s %s#%04x, at 0x%04x\n", name, errors[error - 1], id, u->ram.ptr);
u->ram.ptr = 0;
return 0;
}
#endif
/* clang-format on */
#pragma mark - Core
@ -453,6 +466,13 @@ evaluxn(Uxn *u, Uint16 vec)
__asm__("evaluxn_1b_DIV:");
{
Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
if(a == 0) {
u->wst.error = 3;
#ifndef NO_STACK_CHECKS
goto error;
#endif
a = 1;
}
u->wst.dat[u->wst.ptr - 2] = b / a;
#ifndef NO_STACK_CHECKS
if(__builtin_expect(u->wst.ptr < 2, 0)) {
@ -926,6 +946,13 @@ evaluxn(Uxn *u, Uint16 vec)
__asm__("evaluxn_3b_DIV2:");
{
Uint16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
if(a == 0) {
u->wst.error = 3;
#ifndef NO_STACK_CHECKS
goto error;
#endif
a = 1;
}
u->wst.dat[u->wst.ptr - 4] = (b / a) >> 8;
u->wst.dat[u->wst.ptr - 3] = (b / a) & 0xff;
#ifndef NO_STACK_CHECKS
@ -1376,6 +1403,13 @@ evaluxn(Uxn *u, Uint16 vec)
__asm__("evaluxn_5b_DIVr:");
{
Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
if(a == 0) {
u->rst.error = 3;
#ifndef NO_STACK_CHECKS
goto error;
#endif
a = 1;
}
u->rst.dat[u->rst.ptr - 2] = b / a;
#ifndef NO_STACK_CHECKS
if(__builtin_expect(u->rst.ptr < 2, 0)) {
@ -1849,6 +1883,13 @@ evaluxn(Uxn *u, Uint16 vec)
__asm__("evaluxn_7b_DIV2r:");
{
Uint16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
if(a == 0) {
u->rst.error = 3;
#ifndef NO_STACK_CHECKS
goto error;
#endif
a = 1;
}
u->rst.dat[u->rst.ptr - 4] = (b / a) >> 8;
u->rst.dat[u->rst.ptr - 3] = (b / a) & 0xff;
#ifndef NO_STACK_CHECKS
@ -2332,6 +2373,13 @@ evaluxn(Uxn *u, Uint16 vec)
__asm__("evaluxn_9b_DIVk:");
{
Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
if(a == 0) {
u->wst.error = 3;
#ifndef NO_STACK_CHECKS
goto error;
#endif
a = 1;
}
u->wst.dat[u->wst.ptr] = b / a;
#ifndef NO_STACK_CHECKS
if(__builtin_expect(u->wst.ptr < 2, 0)) {
@ -2846,6 +2894,13 @@ evaluxn(Uxn *u, Uint16 vec)
__asm__("evaluxn_bb_DIV2k:");
{
Uint16 a = (u->wst.dat[u->wst.ptr - 1] | (u->wst.dat[u->wst.ptr - 2] << 8)), b = (u->wst.dat[u->wst.ptr - 3] | (u->wst.dat[u->wst.ptr - 4] << 8));
if(a == 0) {
u->wst.error = 3;
#ifndef NO_STACK_CHECKS
goto error;
#endif
a = 1;
}
u->wst.dat[u->wst.ptr] = (b / a) >> 8;
u->wst.dat[u->wst.ptr + 1] = (b / a) & 0xff;
#ifndef NO_STACK_CHECKS
@ -3349,6 +3404,13 @@ evaluxn(Uxn *u, Uint16 vec)
__asm__("evaluxn_db_DIVkr:");
{
Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
if(a == 0) {
u->rst.error = 3;
#ifndef NO_STACK_CHECKS
goto error;
#endif
a = 1;
}
u->rst.dat[u->rst.ptr] = b / a;
#ifndef NO_STACK_CHECKS
if(__builtin_expect(u->rst.ptr < 2, 0)) {
@ -3863,6 +3925,13 @@ evaluxn(Uxn *u, Uint16 vec)
__asm__("evaluxn_fb_DIV2kr:");
{
Uint16 a = (u->rst.dat[u->rst.ptr - 1] | (u->rst.dat[u->rst.ptr - 2] << 8)), b = (u->rst.dat[u->rst.ptr - 3] | (u->rst.dat[u->rst.ptr - 4] << 8));
if(a == 0) {
u->rst.error = 3;
#ifndef NO_STACK_CHECKS
goto error;
#endif
a = 1;
}
u->rst.dat[u->rst.ptr] = (b / a) >> 8;
u->rst.dat[u->rst.ptr + 1] = (b / a) & 0xff;
#ifndef NO_STACK_CHECKS
@ -3961,12 +4030,10 @@ evaluxn(Uxn *u, Uint16 vec)
return 1;
#ifndef NO_STACK_CHECKS
error:
printf("Halted: %s-stack %sflow#%04x, at 0x%04x\n",
u->wst.error ? "Working" : "Return",
((u->wst.error | u->rst.error) & 2) ? "over" : "under",
instr,
u->ram.ptr);
return 0;
if(u->wst.error)
return haltuxn(u, u->wst.error, "Working-stack", instr);
else
return haltuxn(u, u->rst.error, "Return-stack", instr);
#endif
}

View File

@ -61,7 +61,7 @@ void op_deo(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); devpoke8(&u->dev
void op_add(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b + a); }
void op_sub(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b - a); }
void op_mul(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b * a); }
void op_div(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b / a); }
void op_div(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); if(a == 0) { u->src->error = 3; a = 1; } push8(u->src, b / a); }
void op_and(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b & a); }
void op_ora(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b | a); }
void op_eor(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b ^ a); }
@ -95,7 +95,7 @@ void op_deo16(Uxn *u) { Uint8 a = pop8(u->src); Uint16 b = pop16(u->src); devpok
void op_add16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b + a); }
void op_sub16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b - a); }
void op_mul16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b * a); }
void op_div16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b / a); }
void op_div16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); if(a == 0) { u->src->error = 3; a = 1; } push16(u->src, b / a); }
void op_and16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b & a); }
void op_ora16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b | a); }
void op_eor16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b ^ a); }
@ -117,10 +117,12 @@ void (*ops[])(Uxn *u) = {
#pragma mark - Core
static const char *errors[] = {"underflow", "overflow", "division by zero"};
int
haltuxn(Uxn *u, char *name, int id)
haltuxn(Uxn *u, Uint8 error, char *name, int id)
{
printf("Halted: %s#%04x, at 0x%04x\n", name, id, u->ram.ptr);
printf("Halted: %s %s#%04x, at 0x%04x\n", name, errors[error - 1], id, u->ram.ptr);
u->ram.ptr = 0;
return 0;
}
@ -145,9 +147,9 @@ stepuxn(Uxn *u, Uint8 instr)
{
opcuxn(u, instr);
if(u->wst.error)
return haltuxn(u, u->wst.error == 1 ? "Working-stack underflow" : "Working-stack overflow", instr);
return haltuxn(u, u->wst.error, "Working-stack", instr);
if(u->rst.error)
return haltuxn(u, u->rst.error == 1 ? "Return-stack underflow" : "Return-stack overflow", instr);
return haltuxn(u, u->rst.error, "Return-stack", instr);
return 1;
}