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
|
return nil
|
||||||
end
|
end
|
||||||
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
|
local process
|
||||||
process = function(body)
|
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 in_ifdef = false
|
||||||
local _list_0 = {
|
local _list_0 = {
|
||||||
'src',
|
'src',
|
||||||
|
@ -132,6 +138,8 @@ for l in assert(io.lines('src/uxn.c')) do
|
||||||
if replacements[name] then
|
if replacements[name] then
|
||||||
body = replacements[name]
|
body = replacements[name]
|
||||||
end
|
end
|
||||||
|
body = body:gsub('u%-%>src%-%>', 'src.')
|
||||||
|
body = body:gsub('u%-%>dst%-%>', 'dst.')
|
||||||
body = body:gsub('u%-%>src', 'src')
|
body = body:gsub('u%-%>src', 'src')
|
||||||
body = body:gsub('u%-%>dst', 'dst')
|
body = body:gsub('u%-%>dst', 'dst')
|
||||||
top = {
|
top = {
|
||||||
|
@ -278,6 +286,7 @@ See etc/mkuxn-fast.moon for instructions.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
]])
|
]])
|
||||||
|
wanted = true
|
||||||
while true do
|
while true do
|
||||||
local _continue_0 = false
|
local _continue_0 = false
|
||||||
repeat
|
repeat
|
||||||
|
@ -287,9 +296,19 @@ See etc/mkuxn-fast.moon for instructions.
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
if l == '/* Stack */' then
|
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
|
break
|
||||||
end
|
end
|
||||||
_with_0:write(('%s\n'):format(l))
|
|
||||||
_continue_0 = true
|
_continue_0 = true
|
||||||
until true
|
until true
|
||||||
if not _continue_0 then
|
if not _continue_0 then
|
||||||
|
@ -338,12 +357,10 @@ evaluxn(Uxn *u, Uint16 vec)
|
||||||
return 1;
|
return 1;
|
||||||
#ifndef NO_STACK_CHECKS
|
#ifndef NO_STACK_CHECKS
|
||||||
error:
|
error:
|
||||||
printf("Halted: %s-stack %sflow#%04x, at 0x%04x\n",
|
if(u->wst.error)
|
||||||
u->wst.error ? "Working" : "Return",
|
return haltuxn(u, u->wst.error, "Working-stack", instr);
|
||||||
((u->wst.error | u->rst.error) & 2) ? "over" : "under",
|
else
|
||||||
instr,
|
return haltuxn(u, u->rst.error, "Return-stack", instr);
|
||||||
u->ram.ptr);
|
|
||||||
return 0;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,8 +77,13 @@ pop_push = (k, n, s) ->
|
||||||
else
|
else
|
||||||
nil
|
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) ->
|
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
|
in_ifdef = false
|
||||||
for k in *{'src', 'dst'}
|
for k in *{'src', 'dst'}
|
||||||
if bottom[k] != 0
|
if bottom[k] != 0
|
||||||
|
@ -115,6 +120,8 @@ for l in assert io.lines 'src/uxn.c'
|
||||||
continue
|
continue
|
||||||
if replacements[name]
|
if replacements[name]
|
||||||
body = 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%-%>src', 'src'
|
||||||
body = body\gsub 'u%-%>dst', 'dst'
|
body = body\gsub 'u%-%>dst', 'dst'
|
||||||
top = { src: 0, dst: 0 }
|
top = { src: 0, dst: 0 }
|
||||||
|
@ -200,13 +207,21 @@ See etc/mkuxn-fast.moon for instructions.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
]]
|
]]
|
||||||
|
wanted = true
|
||||||
while true
|
while true
|
||||||
l = f\read '*l'
|
l = f\read '*l'
|
||||||
if l\match' push' or l\match'[ *]pop'
|
if l\match' push' or l\match'[ *]pop'
|
||||||
continue
|
continue
|
||||||
if l == '/* Stack */'
|
if l == '/* Stack */'
|
||||||
break
|
wanted = false
|
||||||
|
if l\match 'errors%[%]'
|
||||||
|
\write '\n#ifndef NO_STACK_CHECKS\n'
|
||||||
|
wanted = true
|
||||||
|
if wanted
|
||||||
\write '%s\n'\format l
|
\write '%s\n'\format l
|
||||||
|
if l == '}'
|
||||||
|
\write '#endif\n\n'
|
||||||
|
break
|
||||||
\write [[
|
\write [[
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
|
@ -238,12 +253,10 @@ evaluxn(Uxn *u, Uint16 vec)
|
||||||
return 1;
|
return 1;
|
||||||
#ifndef NO_STACK_CHECKS
|
#ifndef NO_STACK_CHECKS
|
||||||
error:
|
error:
|
||||||
printf("Halted: %s-stack %sflow#%04x, at 0x%04x\n",
|
if(u->wst.error)
|
||||||
u->wst.error ? "Working" : "Return",
|
return haltuxn(u, u->wst.error, "Working-stack", instr);
|
||||||
((u->wst.error | u->rst.error) & 2) ? "over" : "under",
|
else
|
||||||
instr,
|
return haltuxn(u, u->rst.error, "Return-stack", instr);
|
||||||
u->ram.ptr);
|
|
||||||
return 0;
|
|
||||||
#endif
|
#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); }
|
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); }
|
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); }
|
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 */
|
/* clang-format on */
|
||||||
|
|
||||||
#pragma mark - Core
|
#pragma mark - Core
|
||||||
|
@ -453,6 +466,13 @@ evaluxn(Uxn *u, Uint16 vec)
|
||||||
__asm__("evaluxn_1b_DIV:");
|
__asm__("evaluxn_1b_DIV:");
|
||||||
{
|
{
|
||||||
Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
|
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;
|
u->wst.dat[u->wst.ptr - 2] = b / a;
|
||||||
#ifndef NO_STACK_CHECKS
|
#ifndef NO_STACK_CHECKS
|
||||||
if(__builtin_expect(u->wst.ptr < 2, 0)) {
|
if(__builtin_expect(u->wst.ptr < 2, 0)) {
|
||||||
|
@ -926,6 +946,13 @@ evaluxn(Uxn *u, Uint16 vec)
|
||||||
__asm__("evaluxn_3b_DIV2:");
|
__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));
|
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 - 4] = (b / a) >> 8;
|
||||||
u->wst.dat[u->wst.ptr - 3] = (b / a) & 0xff;
|
u->wst.dat[u->wst.ptr - 3] = (b / a) & 0xff;
|
||||||
#ifndef NO_STACK_CHECKS
|
#ifndef NO_STACK_CHECKS
|
||||||
|
@ -1376,6 +1403,13 @@ evaluxn(Uxn *u, Uint16 vec)
|
||||||
__asm__("evaluxn_5b_DIVr:");
|
__asm__("evaluxn_5b_DIVr:");
|
||||||
{
|
{
|
||||||
Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
|
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;
|
u->rst.dat[u->rst.ptr - 2] = b / a;
|
||||||
#ifndef NO_STACK_CHECKS
|
#ifndef NO_STACK_CHECKS
|
||||||
if(__builtin_expect(u->rst.ptr < 2, 0)) {
|
if(__builtin_expect(u->rst.ptr < 2, 0)) {
|
||||||
|
@ -1849,6 +1883,13 @@ evaluxn(Uxn *u, Uint16 vec)
|
||||||
__asm__("evaluxn_7b_DIV2r:");
|
__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));
|
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 - 4] = (b / a) >> 8;
|
||||||
u->rst.dat[u->rst.ptr - 3] = (b / a) & 0xff;
|
u->rst.dat[u->rst.ptr - 3] = (b / a) & 0xff;
|
||||||
#ifndef NO_STACK_CHECKS
|
#ifndef NO_STACK_CHECKS
|
||||||
|
@ -2332,6 +2373,13 @@ evaluxn(Uxn *u, Uint16 vec)
|
||||||
__asm__("evaluxn_9b_DIVk:");
|
__asm__("evaluxn_9b_DIVk:");
|
||||||
{
|
{
|
||||||
Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
|
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;
|
u->wst.dat[u->wst.ptr] = b / a;
|
||||||
#ifndef NO_STACK_CHECKS
|
#ifndef NO_STACK_CHECKS
|
||||||
if(__builtin_expect(u->wst.ptr < 2, 0)) {
|
if(__builtin_expect(u->wst.ptr < 2, 0)) {
|
||||||
|
@ -2846,6 +2894,13 @@ evaluxn(Uxn *u, Uint16 vec)
|
||||||
__asm__("evaluxn_bb_DIV2k:");
|
__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));
|
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] = (b / a) >> 8;
|
||||||
u->wst.dat[u->wst.ptr + 1] = (b / a) & 0xff;
|
u->wst.dat[u->wst.ptr + 1] = (b / a) & 0xff;
|
||||||
#ifndef NO_STACK_CHECKS
|
#ifndef NO_STACK_CHECKS
|
||||||
|
@ -3349,6 +3404,13 @@ evaluxn(Uxn *u, Uint16 vec)
|
||||||
__asm__("evaluxn_db_DIVkr:");
|
__asm__("evaluxn_db_DIVkr:");
|
||||||
{
|
{
|
||||||
Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
|
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;
|
u->rst.dat[u->rst.ptr] = b / a;
|
||||||
#ifndef NO_STACK_CHECKS
|
#ifndef NO_STACK_CHECKS
|
||||||
if(__builtin_expect(u->rst.ptr < 2, 0)) {
|
if(__builtin_expect(u->rst.ptr < 2, 0)) {
|
||||||
|
@ -3863,6 +3925,13 @@ evaluxn(Uxn *u, Uint16 vec)
|
||||||
__asm__("evaluxn_fb_DIV2kr:");
|
__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));
|
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] = (b / a) >> 8;
|
||||||
u->rst.dat[u->rst.ptr + 1] = (b / a) & 0xff;
|
u->rst.dat[u->rst.ptr + 1] = (b / a) & 0xff;
|
||||||
#ifndef NO_STACK_CHECKS
|
#ifndef NO_STACK_CHECKS
|
||||||
|
@ -3961,12 +4030,10 @@ evaluxn(Uxn *u, Uint16 vec)
|
||||||
return 1;
|
return 1;
|
||||||
#ifndef NO_STACK_CHECKS
|
#ifndef NO_STACK_CHECKS
|
||||||
error:
|
error:
|
||||||
printf("Halted: %s-stack %sflow#%04x, at 0x%04x\n",
|
if(u->wst.error)
|
||||||
u->wst.error ? "Working" : "Return",
|
return haltuxn(u, u->wst.error, "Working-stack", instr);
|
||||||
((u->wst.error | u->rst.error) & 2) ? "over" : "under",
|
else
|
||||||
instr,
|
return haltuxn(u, u->rst.error, "Return-stack", instr);
|
||||||
u->ram.ptr);
|
|
||||||
return 0;
|
|
||||||
#endif
|
#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_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_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_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_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_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); }
|
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_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_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_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_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_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); }
|
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
|
#pragma mark - Core
|
||||||
|
|
||||||
|
static const char *errors[] = {"underflow", "overflow", "division by zero"};
|
||||||
|
|
||||||
int
|
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;
|
u->ram.ptr = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -145,9 +147,9 @@ stepuxn(Uxn *u, Uint8 instr)
|
||||||
{
|
{
|
||||||
opcuxn(u, instr);
|
opcuxn(u, instr);
|
||||||
if(u->wst.error)
|
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)
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue