Added reporting of division by zero errors rather than crashing
This commit is contained in:
parent
6bf7e7f7a1
commit
064f7745d4
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
14
src/uxn.c
14
src/uxn.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue