(uxnemu) Interrupt infinite loops with an error.

This commit is contained in:
Andrew Alderwick 2022-03-27 13:53:25 +01:00
parent b9ff19d857
commit 0e7ebb69e6
5 changed files with 37 additions and 4 deletions

View File

@ -20,7 +20,8 @@ static const char *errors[] = {
"Working-stack overflow",
"Return-stack overflow",
"Working-stack division by zero",
"Return-stack division by zero"};
"Return-stack division by zero",
"Execution timeout"};
static void
system_print(Stack *s, char *name)

View File

@ -30,16 +30,25 @@ WITH REGARD TO THIS SOFTWARE.
#define DEVW8(x, y) { dev->dat[(x) & 0xf] = y; dev->deo(dev, (x) & 0x0f); }
#define DEVW(d, x, y) { dev = (d); if(bs) { DEVW8((x), (y) >> 8); DEVW8((x) + 1, (y)); } else { DEVW8((x), (y)) } }
#define WARP(x) { if(bs) pc = (x); else pc += (Sint8)(x); }
#define LIMIT 0x40000 /* around 3 ms */
int
uxn_eval(Uxn *u, Uint16 pc)
{
unsigned int a, b, c, j, k, bs, instr, errcode;
unsigned int limit = LIMIT;
Uint8 kptr, *sp;
Stack *src, *dst;
Device *dev;
if(!pc || u->dev[0].dat[0xf]) return 0;
while((instr = u->ram[pc++])) {
if(!limit--) {
if(!uxn_interrupt()) {
errcode = 6;
goto timeout;
}
limit = LIMIT;
}
/* Return Mode */
if(instr & 0x40) {
src = &u->rst; dst = &u->wst;
@ -101,6 +110,7 @@ err:
/* set 1 in errcode if it involved the return stack instead of the working stack */
/* (stack overflow & ( opcode was STH / JSR )) ^ Return Mode */
errcode |= ((errcode >> 1 & ((instr & 0x1e) == 0x0e)) ^ instr >> 6) & 1;
timeout:
return uxn_halt(u, errcode, pc - 1);
}

View File

@ -47,6 +47,7 @@ typedef struct Uxn {
int uxn_boot(Uxn *u, Uint8 *ram);
int uxn_eval(Uxn *u, Uint16 pc);
int uxn_interrupt(void);
int uxn_halt(Uxn *u, Uint8 error, Uint16 addr);
Device *uxn_port(Uxn *u, Uint8 id, Uint8 (*deifn)(Device *, Uint8), void (*deofn)(Device *, Uint8));
#endif /* UXN_UXN_H */

View File

@ -101,6 +101,12 @@ load(Uxn *u, char *filepath)
return 1;
}
int
uxn_interrupt(void)
{
return 1;
}
static int
start(Uxn *u)
{

View File

@ -32,6 +32,7 @@ WITH REGARD TO THIS SOFTWARE.
#define WIDTH 64 * 8
#define HEIGHT 40 * 8
#define PAD 4
#define TIMEOUT_FRAMES 10
static SDL_Window *gWindow;
static SDL_Texture *gTexture;
@ -43,7 +44,7 @@ static SDL_Rect gRect;
static Device *devscreen, *devmouse, *devctrl, *devaudio0, *devfile0;
static Uint8 zoom = 1;
static Uint32 stdin_event, audio0_event, redraw_event;
static Uint32 stdin_event, audio0_event, redraw_event, interrupt_event;
static int
error(char *msg, const char *err)
@ -89,12 +90,19 @@ stdin_handler(void *p)
static int
redraw_handler(void *p)
{
SDL_Event event;
int dropped_frames = 0;
SDL_Event event, interrupt;
event.type = redraw_event;
interrupt.type = interrupt_event;
for(;;) {
SDL_Delay(16);
if(SDL_HasEvent(redraw_event) == SDL_FALSE)
if(SDL_HasEvent(redraw_event) == SDL_FALSE) {
SDL_PushEvent(&event);
dropped_frames = 0;
}
else if(++dropped_frames == TIMEOUT_FRAMES) {
SDL_PushEvent(&interrupt);
}
}
return 0;
(void)p;
@ -169,6 +177,7 @@ init(void)
stdin_event = SDL_RegisterEvents(1);
audio0_event = SDL_RegisterEvents(POLYPHONY);
redraw_event = SDL_RegisterEvents(1);
interrupt_event = SDL_RegisterEvents(1);
SDL_CreateThread(stdin_handler, "stdin", NULL);
SDL_CreateThread(redraw_handler, "redraw", NULL);
SDL_StartTextInput();
@ -467,6 +476,12 @@ run(Uxn *u)
return error("SDL_WaitEvent", SDL_GetError());
}
int
uxn_interrupt(void)
{
return SDL_PeepEvents(NULL, 1, SDL_GETEVENT, interrupt_event, interrupt_event) < 1;
}
int
main(int argc, char **argv)
{