(uxnemu) Interrupt infinite loops with an error.
This commit is contained in:
parent
b9ff19d857
commit
0e7ebb69e6
|
@ -20,7 +20,8 @@ static const char *errors[] = {
|
||||||
"Working-stack overflow",
|
"Working-stack overflow",
|
||||||
"Return-stack overflow",
|
"Return-stack overflow",
|
||||||
"Working-stack division by zero",
|
"Working-stack division by zero",
|
||||||
"Return-stack division by zero"};
|
"Return-stack division by zero",
|
||||||
|
"Execution timeout"};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
system_print(Stack *s, char *name)
|
system_print(Stack *s, char *name)
|
||||||
|
|
10
src/uxn.c
10
src/uxn.c
|
@ -30,16 +30,25 @@ WITH REGARD TO THIS SOFTWARE.
|
||||||
#define DEVW8(x, y) { dev->dat[(x) & 0xf] = y; dev->deo(dev, (x) & 0x0f); }
|
#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 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 WARP(x) { if(bs) pc = (x); else pc += (Sint8)(x); }
|
||||||
|
#define LIMIT 0x40000 /* around 3 ms */
|
||||||
|
|
||||||
int
|
int
|
||||||
uxn_eval(Uxn *u, Uint16 pc)
|
uxn_eval(Uxn *u, Uint16 pc)
|
||||||
{
|
{
|
||||||
unsigned int a, b, c, j, k, bs, instr, errcode;
|
unsigned int a, b, c, j, k, bs, instr, errcode;
|
||||||
|
unsigned int limit = LIMIT;
|
||||||
Uint8 kptr, *sp;
|
Uint8 kptr, *sp;
|
||||||
Stack *src, *dst;
|
Stack *src, *dst;
|
||||||
Device *dev;
|
Device *dev;
|
||||||
if(!pc || u->dev[0].dat[0xf]) return 0;
|
if(!pc || u->dev[0].dat[0xf]) return 0;
|
||||||
while((instr = u->ram[pc++])) {
|
while((instr = u->ram[pc++])) {
|
||||||
|
if(!limit--) {
|
||||||
|
if(!uxn_interrupt()) {
|
||||||
|
errcode = 6;
|
||||||
|
goto timeout;
|
||||||
|
}
|
||||||
|
limit = LIMIT;
|
||||||
|
}
|
||||||
/* Return Mode */
|
/* Return Mode */
|
||||||
if(instr & 0x40) {
|
if(instr & 0x40) {
|
||||||
src = &u->rst; dst = &u->wst;
|
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 */
|
/* set 1 in errcode if it involved the return stack instead of the working stack */
|
||||||
/* (stack overflow & ( opcode was STH / JSR )) ^ Return Mode */
|
/* (stack overflow & ( opcode was STH / JSR )) ^ Return Mode */
|
||||||
errcode |= ((errcode >> 1 & ((instr & 0x1e) == 0x0e)) ^ instr >> 6) & 1;
|
errcode |= ((errcode >> 1 & ((instr & 0x1e) == 0x0e)) ^ instr >> 6) & 1;
|
||||||
|
timeout:
|
||||||
return uxn_halt(u, errcode, pc - 1);
|
return uxn_halt(u, errcode, pc - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ typedef struct Uxn {
|
||||||
|
|
||||||
int uxn_boot(Uxn *u, Uint8 *ram);
|
int uxn_boot(Uxn *u, Uint8 *ram);
|
||||||
int uxn_eval(Uxn *u, Uint16 pc);
|
int uxn_eval(Uxn *u, Uint16 pc);
|
||||||
|
int uxn_interrupt(void);
|
||||||
int uxn_halt(Uxn *u, Uint8 error, Uint16 addr);
|
int uxn_halt(Uxn *u, Uint8 error, Uint16 addr);
|
||||||
Device *uxn_port(Uxn *u, Uint8 id, Uint8 (*deifn)(Device *, Uint8), void (*deofn)(Device *, Uint8));
|
Device *uxn_port(Uxn *u, Uint8 id, Uint8 (*deifn)(Device *, Uint8), void (*deofn)(Device *, Uint8));
|
||||||
#endif /* UXN_UXN_H */
|
#endif /* UXN_UXN_H */
|
||||||
|
|
|
@ -101,6 +101,12 @@ load(Uxn *u, char *filepath)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
uxn_interrupt(void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
start(Uxn *u)
|
start(Uxn *u)
|
||||||
{
|
{
|
||||||
|
|
21
src/uxnemu.c
21
src/uxnemu.c
|
@ -32,6 +32,7 @@ WITH REGARD TO THIS SOFTWARE.
|
||||||
#define WIDTH 64 * 8
|
#define WIDTH 64 * 8
|
||||||
#define HEIGHT 40 * 8
|
#define HEIGHT 40 * 8
|
||||||
#define PAD 4
|
#define PAD 4
|
||||||
|
#define TIMEOUT_FRAMES 10
|
||||||
|
|
||||||
static SDL_Window *gWindow;
|
static SDL_Window *gWindow;
|
||||||
static SDL_Texture *gTexture;
|
static SDL_Texture *gTexture;
|
||||||
|
@ -43,7 +44,7 @@ static SDL_Rect gRect;
|
||||||
|
|
||||||
static Device *devscreen, *devmouse, *devctrl, *devaudio0, *devfile0;
|
static Device *devscreen, *devmouse, *devctrl, *devaudio0, *devfile0;
|
||||||
static Uint8 zoom = 1;
|
static Uint8 zoom = 1;
|
||||||
static Uint32 stdin_event, audio0_event, redraw_event;
|
static Uint32 stdin_event, audio0_event, redraw_event, interrupt_event;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
error(char *msg, const char *err)
|
error(char *msg, const char *err)
|
||||||
|
@ -89,12 +90,19 @@ stdin_handler(void *p)
|
||||||
static int
|
static int
|
||||||
redraw_handler(void *p)
|
redraw_handler(void *p)
|
||||||
{
|
{
|
||||||
SDL_Event event;
|
int dropped_frames = 0;
|
||||||
|
SDL_Event event, interrupt;
|
||||||
event.type = redraw_event;
|
event.type = redraw_event;
|
||||||
|
interrupt.type = interrupt_event;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
SDL_Delay(16);
|
SDL_Delay(16);
|
||||||
if(SDL_HasEvent(redraw_event) == SDL_FALSE)
|
if(SDL_HasEvent(redraw_event) == SDL_FALSE) {
|
||||||
SDL_PushEvent(&event);
|
SDL_PushEvent(&event);
|
||||||
|
dropped_frames = 0;
|
||||||
|
}
|
||||||
|
else if(++dropped_frames == TIMEOUT_FRAMES) {
|
||||||
|
SDL_PushEvent(&interrupt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
(void)p;
|
(void)p;
|
||||||
|
@ -169,6 +177,7 @@ init(void)
|
||||||
stdin_event = SDL_RegisterEvents(1);
|
stdin_event = SDL_RegisterEvents(1);
|
||||||
audio0_event = SDL_RegisterEvents(POLYPHONY);
|
audio0_event = SDL_RegisterEvents(POLYPHONY);
|
||||||
redraw_event = SDL_RegisterEvents(1);
|
redraw_event = SDL_RegisterEvents(1);
|
||||||
|
interrupt_event = SDL_RegisterEvents(1);
|
||||||
SDL_CreateThread(stdin_handler, "stdin", NULL);
|
SDL_CreateThread(stdin_handler, "stdin", NULL);
|
||||||
SDL_CreateThread(redraw_handler, "redraw", NULL);
|
SDL_CreateThread(redraw_handler, "redraw", NULL);
|
||||||
SDL_StartTextInput();
|
SDL_StartTextInput();
|
||||||
|
@ -467,6 +476,12 @@ run(Uxn *u)
|
||||||
return error("SDL_WaitEvent", SDL_GetError());
|
return error("SDL_WaitEvent", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
uxn_interrupt(void)
|
||||||
|
{
|
||||||
|
return SDL_PeepEvents(NULL, 1, SDL_GETEVENT, interrupt_event, interrupt_event) < 1;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue