| ... | ... |
@@ -72,9 +72,15 @@ pop_push = function(k, n, s) |
| 72 | 72 |
return nil |
| 73 | 73 |
end |
| 74 | 74 |
end |
| 75 |
+local indented_block |
|
| 76 |
+indented_block = function(s) |
|
| 77 |
+ s = s:gsub('^%{ *', '{\n'):gsub('\n', '\n\t'):gsub('\t%} *$', '}\n')
|
|
| 78 |
+ s = s:gsub('\n[^\n]+%.error = [^\n]+', '%0\n#ifndef NO_STACK_CHECKS\n\tgoto error;\n#endif')
|
|
| 79 |
+ return s |
|
| 80 |
+end |
|
| 75 | 81 |
local process |
| 76 | 82 |
process = function(body) |
| 77 |
- local out_body = body:gsub('^%{ *', ''):gsub(' *%}$', ''):gsub('; ', ';\n'):gsub('(%a+)(%d+)(%b())', pop_push)
|
|
| 83 |
+ local out_body = body:gsub('^%{ *', ''):gsub(' *%}$', ''):gsub('; ', ';\n'):gsub('%b{} *', indented_block):gsub('(%a+)(%d+)(%b())', pop_push)
|
|
| 78 | 84 |
local in_ifdef = false |
| 79 | 85 |
local _list_0 = {
|
| 80 | 86 |
'src', |
| ... | ... |
@@ -132,6 +138,8 @@ for l in assert(io.lines('src/uxn.c')) do
|
| 132 | 138 |
if replacements[name] then |
| 133 | 139 |
body = replacements[name] |
| 134 | 140 |
end |
| 141 |
+ body = body:gsub('u%-%>src%-%>', 'src.')
|
|
| 142 |
+ body = body:gsub('u%-%>dst%-%>', 'dst.')
|
|
| 135 | 143 |
body = body:gsub('u%-%>src', 'src')
|
| 136 | 144 |
body = body:gsub('u%-%>dst', 'dst')
|
| 137 | 145 |
top = {
|
| ... | ... |
@@ -278,6 +286,7 @@ See etc/mkuxn-fast.moon for instructions. |
| 278 | 286 |
|
| 279 | 287 |
*/ |
| 280 | 288 |
]]) |
| 289 |
+ wanted = true |
|
| 281 | 290 |
while true do |
| 282 | 291 |
local _continue_0 = false |
| 283 | 292 |
repeat |
| ... | ... |
@@ -287,9 +296,19 @@ See etc/mkuxn-fast.moon for instructions. |
| 287 | 296 |
break |
| 288 | 297 |
end |
| 289 | 298 |
if l == '/* Stack */' then |
| 299 |
+ wanted = false |
|
| 300 |
+ end |
|
| 301 |
+ if l:match('errors%[%]') then
|
|
| 302 |
+ _with_0:write('\n#ifndef NO_STACK_CHECKS\n')
|
|
| 303 |
+ wanted = true |
|
| 304 |
+ end |
|
| 305 |
+ if wanted then |
|
| 306 |
+ _with_0:write(('%s\n'):format(l))
|
|
| 307 |
+ end |
|
| 308 |
+ if l == '}' then |
|
| 309 |
+ _with_0:write('#endif\n\n')
|
|
| 290 | 310 |
break |
| 291 | 311 |
end |
| 292 |
- _with_0:write(('%s\n'):format(l))
|
|
| 293 | 312 |
_continue_0 = true |
| 294 | 313 |
until true |
| 295 | 314 |
if not _continue_0 then |
| ... | ... |
@@ -338,12 +357,10 @@ evaluxn(Uxn *u, Uint16 vec) |
| 338 | 357 |
return 1; |
| 339 | 358 |
#ifndef NO_STACK_CHECKS |
| 340 | 359 |
error: |
| 341 |
- printf("Halted: %s-stack %sflow#%04x, at 0x%04x\n",
|
|
| 342 |
- u->wst.error ? "Working" : "Return", |
|
| 343 |
- ((u->wst.error | u->rst.error) & 2) ? "over" : "under", |
|
| 344 |
- instr, |
|
| 345 |
- u->ram.ptr); |
|
| 346 |
- return 0; |
|
| 360 |
+ if(u->wst.error) |
|
| 361 |
+ return haltuxn(u, u->wst.error, "Working-stack", instr); |
|
| 362 |
+ else |
|
| 363 |
+ return haltuxn(u, u->rst.error, "Return-stack", instr); |
|
| 347 | 364 |
#endif |
| 348 | 365 |
} |
| 349 | 366 |
|
| ... | ... |
@@ -77,8 +77,13 @@ pop_push = (k, n, s) -> |
| 77 | 77 |
else |
| 78 | 78 |
nil |
| 79 | 79 |
|
| 80 |
+indented_block = (s) -> |
|
| 81 |
+ s = s\gsub('^%{ *', '{\n')\gsub('\n', '\n\t')\gsub('\t%} *$', '}\n')
|
|
| 82 |
+ s = s\gsub('\n[^\n]+%.error = [^\n]+', '%0\n#ifndef NO_STACK_CHECKS\n\tgoto error;\n#endif')
|
|
| 83 |
+ s |
|
| 84 |
+ |
|
| 80 | 85 |
process = (body) -> |
| 81 |
- out_body = body\gsub('^%{ *', '')\gsub(' *%}$', '')\gsub('; ', ';\n')\gsub '(%a+)(%d+)(%b())', pop_push
|
|
| 86 |
+ out_body = body\gsub('^%{ *', '')\gsub(' *%}$', '')\gsub('; ', ';\n')\gsub('%b{} *', indented_block)\gsub '(%a+)(%d+)(%b())', pop_push
|
|
| 82 | 87 |
in_ifdef = false |
| 83 | 88 |
for k in *{'src', 'dst'}
|
| 84 | 89 |
if bottom[k] != 0 |
| ... | ... |
@@ -115,6 +120,8 @@ for l in assert io.lines 'src/uxn.c' |
| 115 | 120 |
continue |
| 116 | 121 |
if replacements[name] |
| 117 | 122 |
body = replacements[name] |
| 123 |
+ body = body\gsub 'u%-%>src%-%>', 'src.' |
|
| 124 |
+ body = body\gsub 'u%-%>dst%-%>', 'dst.' |
|
| 118 | 125 |
body = body\gsub 'u%-%>src', 'src' |
| 119 | 126 |
body = body\gsub 'u%-%>dst', 'dst' |
| 120 | 127 |
top = { src: 0, dst: 0 }
|
| ... | ... |
@@ -200,13 +207,21 @@ See etc/mkuxn-fast.moon for instructions. |
| 200 | 207 |
|
| 201 | 208 |
*/ |
| 202 | 209 |
]] |
| 210 |
+ wanted = true |
|
| 203 | 211 |
while true |
| 204 | 212 |
l = f\read '*l' |
| 205 | 213 |
if l\match' push' or l\match'[ *]pop' |
| 206 | 214 |
continue |
| 207 | 215 |
if l == '/* Stack */' |
| 216 |
+ wanted = false |
|
| 217 |
+ if l\match 'errors%[%]' |
|
| 218 |
+ \write '\n#ifndef NO_STACK_CHECKS\n' |
|
| 219 |
+ wanted = true |
|
| 220 |
+ if wanted |
|
| 221 |
+ \write '%s\n'\format l |
|
| 222 |
+ if l == '}' |
|
| 223 |
+ \write '#endif\n\n' |
|
| 208 | 224 |
break |
| 209 |
- \write '%s\n'\format l |
|
| 210 | 225 |
\write [[ |
| 211 | 226 |
/* clang-format on */ |
| 212 | 227 |
|
| ... | ... |
@@ -238,12 +253,10 @@ evaluxn(Uxn *u, Uint16 vec) |
| 238 | 253 |
return 1; |
| 239 | 254 |
#ifndef NO_STACK_CHECKS |
| 240 | 255 |
error: |
| 241 |
- printf("Halted: %s-stack %sflow#%04x, at 0x%04x\n",
|
|
| 242 |
- u->wst.error ? "Working" : "Return", |
|
| 243 |
- ((u->wst.error | u->rst.error) & 2) ? "over" : "under", |
|
| 244 |
- instr, |
|
| 245 |
- u->ram.ptr); |
|
| 246 |
- return 0; |
|
| 256 |
+ if(u->wst.error) |
|
| 257 |
+ return haltuxn(u, u->wst.error, "Working-stack", instr); |
|
| 258 |
+ else |
|
| 259 |
+ return haltuxn(u, u->rst.error, "Return-stack", instr); |
|
| 247 | 260 |
#endif |
| 248 | 261 |
} |
| 249 | 262 |
|
| ... | ... |
@@ -34,6 +34,19 @@ void mempoke16(Uint8 *m, Uint16 a, Uint16 b) { mempoke8(m, a, b >> 8); mempoke
|
| 34 | 34 |
Uint16 mempeek16(Uint8 *m, Uint16 a) { return (mempeek8(m, a) << 8) + mempeek8(m, a + 1); }
|
| 35 | 35 |
void devpoke16(Device *d, Uint8 a, Uint16 b) { devpoke8(d, a, b >> 8); devpoke8(d, a + 1, b); }
|
| 36 | 36 |
Uint16 devpeek16(Device *d, Uint16 a) { return (devpeek8(d, a) << 8) + devpeek8(d, a + 1); }
|
| 37 |
+ |
|
| 38 |
+#ifndef NO_STACK_CHECKS |
|
| 39 |
+static const char *errors[] = {"underflow", "overflow", "division by zero"};
|
|
| 40 |
+ |
|
| 41 |
+int |
|
| 42 |
+haltuxn(Uxn *u, Uint8 error, char *name, int id) |
|
| 43 |
+{
|
|
| 44 |
+ printf("Halted: %s %s#%04x, at 0x%04x\n", name, errors[error - 1], id, u->ram.ptr);
|
|
| 45 |
+ u->ram.ptr = 0; |
|
| 46 |
+ return 0; |
|
| 47 |
+} |
|
| 48 |
+#endif |
|
| 49 |
+ |
|
| 37 | 50 |
/* clang-format on */ |
| 38 | 51 |
|
| 39 | 52 |
#pragma mark - Core |
| ... | ... |
@@ -453,6 +466,13 @@ evaluxn(Uxn *u, Uint16 vec) |
| 453 | 466 |
__asm__("evaluxn_1b_DIV:");
|
| 454 | 467 |
{
|
| 455 | 468 |
Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; |
| 469 |
+ if(a == 0) {
|
|
| 470 |
+ u->wst.error = 3; |
|
| 471 |
+#ifndef NO_STACK_CHECKS |
|
| 472 |
+ goto error; |
|
| 473 |
+#endif |
|
| 474 |
+ a = 1; |
|
| 475 |
+ } |
|
| 456 | 476 |
u->wst.dat[u->wst.ptr - 2] = b / a; |
| 457 | 477 |
#ifndef NO_STACK_CHECKS |
| 458 | 478 |
if(__builtin_expect(u->wst.ptr < 2, 0)) {
|
| ... | ... |
@@ -926,6 +946,13 @@ evaluxn(Uxn *u, Uint16 vec) |
| 926 | 946 |
__asm__("evaluxn_3b_DIV2:");
|
| 927 | 947 |
{
|
| 928 | 948 |
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)); |
| 949 |
+ if(a == 0) {
|
|
| 950 |
+ u->wst.error = 3; |
|
| 951 |
+#ifndef NO_STACK_CHECKS |
|
| 952 |
+ goto error; |
|
| 953 |
+#endif |
|
| 954 |
+ a = 1; |
|
| 955 |
+ } |
|
| 929 | 956 |
u->wst.dat[u->wst.ptr - 4] = (b / a) >> 8; |
| 930 | 957 |
u->wst.dat[u->wst.ptr - 3] = (b / a) & 0xff; |
| 931 | 958 |
#ifndef NO_STACK_CHECKS |
| ... | ... |
@@ -1376,6 +1403,13 @@ evaluxn(Uxn *u, Uint16 vec) |
| 1376 | 1403 |
__asm__("evaluxn_5b_DIVr:");
|
| 1377 | 1404 |
{
|
| 1378 | 1405 |
Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; |
| 1406 |
+ if(a == 0) {
|
|
| 1407 |
+ u->rst.error = 3; |
|
| 1408 |
+#ifndef NO_STACK_CHECKS |
|
| 1409 |
+ goto error; |
|
| 1410 |
+#endif |
|
| 1411 |
+ a = 1; |
|
| 1412 |
+ } |
|
| 1379 | 1413 |
u->rst.dat[u->rst.ptr - 2] = b / a; |
| 1380 | 1414 |
#ifndef NO_STACK_CHECKS |
| 1381 | 1415 |
if(__builtin_expect(u->rst.ptr < 2, 0)) {
|
| ... | ... |
@@ -1849,6 +1883,13 @@ evaluxn(Uxn *u, Uint16 vec) |
| 1849 | 1883 |
__asm__("evaluxn_7b_DIV2r:");
|
| 1850 | 1884 |
{
|
| 1851 | 1885 |
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)); |
| 1886 |
+ if(a == 0) {
|
|
| 1887 |
+ u->rst.error = 3; |
|
| 1888 |
+#ifndef NO_STACK_CHECKS |
|
| 1889 |
+ goto error; |
|
| 1890 |
+#endif |
|
| 1891 |
+ a = 1; |
|
| 1892 |
+ } |
|
| 1852 | 1893 |
u->rst.dat[u->rst.ptr - 4] = (b / a) >> 8; |
| 1853 | 1894 |
u->rst.dat[u->rst.ptr - 3] = (b / a) & 0xff; |
| 1854 | 1895 |
#ifndef NO_STACK_CHECKS |
| ... | ... |
@@ -2332,6 +2373,13 @@ evaluxn(Uxn *u, Uint16 vec) |
| 2332 | 2373 |
__asm__("evaluxn_9b_DIVk:");
|
| 2333 | 2374 |
{
|
| 2334 | 2375 |
Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; |
| 2376 |
+ if(a == 0) {
|
|
| 2377 |
+ u->wst.error = 3; |
|
| 2378 |
+#ifndef NO_STACK_CHECKS |
|
| 2379 |
+ goto error; |
|
| 2380 |
+#endif |
|
| 2381 |
+ a = 1; |
|
| 2382 |
+ } |
|
| 2335 | 2383 |
u->wst.dat[u->wst.ptr] = b / a; |
| 2336 | 2384 |
#ifndef NO_STACK_CHECKS |
| 2337 | 2385 |
if(__builtin_expect(u->wst.ptr < 2, 0)) {
|
| ... | ... |
@@ -2846,6 +2894,13 @@ evaluxn(Uxn *u, Uint16 vec) |
| 2846 | 2894 |
__asm__("evaluxn_bb_DIV2k:");
|
| 2847 | 2895 |
{
|
| 2848 | 2896 |
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)); |
| 2897 |
+ if(a == 0) {
|
|
| 2898 |
+ u->wst.error = 3; |
|
| 2899 |
+#ifndef NO_STACK_CHECKS |
|
| 2900 |
+ goto error; |
|
| 2901 |
+#endif |
|
| 2902 |
+ a = 1; |
|
| 2903 |
+ } |
|
| 2849 | 2904 |
u->wst.dat[u->wst.ptr] = (b / a) >> 8; |
| 2850 | 2905 |
u->wst.dat[u->wst.ptr + 1] = (b / a) & 0xff; |
| 2851 | 2906 |
#ifndef NO_STACK_CHECKS |
| ... | ... |
@@ -3349,6 +3404,13 @@ evaluxn(Uxn *u, Uint16 vec) |
| 3349 | 3404 |
__asm__("evaluxn_db_DIVkr:");
|
| 3350 | 3405 |
{
|
| 3351 | 3406 |
Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; |
| 3407 |
+ if(a == 0) {
|
|
| 3408 |
+ u->rst.error = 3; |
|
| 3409 |
+#ifndef NO_STACK_CHECKS |
|
| 3410 |
+ goto error; |
|
| 3411 |
+#endif |
|
| 3412 |
+ a = 1; |
|
| 3413 |
+ } |
|
| 3352 | 3414 |
u->rst.dat[u->rst.ptr] = b / a; |
| 3353 | 3415 |
#ifndef NO_STACK_CHECKS |
| 3354 | 3416 |
if(__builtin_expect(u->rst.ptr < 2, 0)) {
|
| ... | ... |
@@ -3863,6 +3925,13 @@ evaluxn(Uxn *u, Uint16 vec) |
| 3863 | 3925 |
__asm__("evaluxn_fb_DIV2kr:");
|
| 3864 | 3926 |
{
|
| 3865 | 3927 |
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)); |
| 3928 |
+ if(a == 0) {
|
|
| 3929 |
+ u->rst.error = 3; |
|
| 3930 |
+#ifndef NO_STACK_CHECKS |
|
| 3931 |
+ goto error; |
|
| 3932 |
+#endif |
|
| 3933 |
+ a = 1; |
|
| 3934 |
+ } |
|
| 3866 | 3935 |
u->rst.dat[u->rst.ptr] = (b / a) >> 8; |
| 3867 | 3936 |
u->rst.dat[u->rst.ptr + 1] = (b / a) & 0xff; |
| 3868 | 3937 |
#ifndef NO_STACK_CHECKS |
| ... | ... |
@@ -3961,12 +4030,10 @@ evaluxn(Uxn *u, Uint16 vec) |
| 3961 | 4030 |
return 1; |
| 3962 | 4031 |
#ifndef NO_STACK_CHECKS |
| 3963 | 4032 |
error: |
| 3964 |
- printf("Halted: %s-stack %sflow#%04x, at 0x%04x\n",
|
|
| 3965 |
- u->wst.error ? "Working" : "Return", |
|
| 3966 |
- ((u->wst.error | u->rst.error) & 2) ? "over" : "under", |
|
| 3967 |
- instr, |
|
| 3968 |
- u->ram.ptr); |
|
| 3969 |
- return 0; |
|
| 4033 |
+ if(u->wst.error) |
|
| 4034 |
+ return haltuxn(u, u->wst.error, "Working-stack", instr); |
|
| 4035 |
+ else |
|
| 4036 |
+ return haltuxn(u, u->rst.error, "Return-stack", instr); |
|
| 3970 | 4037 |
#endif |
| 3971 | 4038 |
} |
| 3972 | 4039 |
|
| ... | ... |
@@ -61,7 +61,7 @@ void op_deo(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); devpoke8(&u->dev
|
| 61 | 61 |
void op_add(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b + a); }
|
| 62 | 62 |
void op_sub(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b - a); }
|
| 63 | 63 |
void op_mul(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b * a); }
|
| 64 |
-void op_div(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b / a); }
|
|
| 64 |
+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); }
|
|
| 65 | 65 |
void op_and(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b & a); }
|
| 66 | 66 |
void op_ora(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b | a); }
|
| 67 | 67 |
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
|
| 95 | 95 |
void op_add16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b + a); }
|
| 96 | 96 |
void op_sub16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b - a); }
|
| 97 | 97 |
void op_mul16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b * a); }
|
| 98 |
-void op_div16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b / a); }
|
|
| 98 |
+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); }
|
|
| 99 | 99 |
void op_and16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b & a); }
|
| 100 | 100 |
void op_ora16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b | a); }
|
| 101 | 101 |
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) = {
|
| 117 | 117 |
|
| 118 | 118 |
#pragma mark - Core |
| 119 | 119 |
|
| 120 |
+static const char *errors[] = {"underflow", "overflow", "division by zero"};
|
|
| 121 |
+ |
|
| 120 | 122 |
int |
| 121 |
-haltuxn(Uxn *u, char *name, int id) |
|
| 123 |
+haltuxn(Uxn *u, Uint8 error, char *name, int id) |
|
| 122 | 124 |
{
|
| 123 |
- printf("Halted: %s#%04x, at 0x%04x\n", name, id, u->ram.ptr);
|
|
| 125 |
+ printf("Halted: %s %s#%04x, at 0x%04x\n", name, errors[error - 1], id, u->ram.ptr);
|
|
| 124 | 126 |
u->ram.ptr = 0; |
| 125 | 127 |
return 0; |
| 126 | 128 |
} |
| ... | ... |
@@ -145,9 +147,9 @@ stepuxn(Uxn *u, Uint8 instr) |
| 145 | 147 |
{
|
| 146 | 148 |
opcuxn(u, instr); |
| 147 | 149 |
if(u->wst.error) |
| 148 |
- return haltuxn(u, u->wst.error == 1 ? "Working-stack underflow" : "Working-stack overflow", instr); |
|
| 150 |
+ return haltuxn(u, u->wst.error, "Working-stack", instr); |
|
| 149 | 151 |
if(u->rst.error) |
| 150 |
- return haltuxn(u, u->rst.error == 1 ? "Return-stack underflow" : "Return-stack overflow", instr); |
|
| 152 |
+ return haltuxn(u, u->rst.error, "Return-stack", instr); |
|
| 151 | 153 |
return 1; |
| 152 | 154 |
} |
| 153 | 155 |
|