#include #include #include #include #include #include #include #include #include #include "asm.h" #include "cpu.h" #include "log.h" #include "opc.h" bool is_debug = false; bool is_interactive = false; /* global program buffer */ uint8_t *P = NULL; static void usage(int rc) { fprintf(stderr, "Usage: risci [-dhi] \n"); exit(rc); } static void signal_handler(int sig) { switch (sig) { case SIGILL: /* SIGILL is raised by the cpu for an unknown instruction */ error("ERROR: illegal instruction."); if (!is_interactive) exit(-1); break; case SIGSEGV: /* SIGSEGV is raised for unaligned memory access */ error("ERROR: unaligned memory access."); if (!is_interactive) exit(-1); break; case SIGFPE: /* SIGFPE is raised by devision with zero */ error("ERROR: division by zero."); exit(-1); break; } } static void read_program(const char *program) { struct stat sb; if (lstat(program, &sb) == -1) pdie("cannot stat program"); if (sb.st_size % sizeof(uint32_t)) die("program does not align to op-code size of %u bytes", sizeof(uint32_t)); int pfd; if ((pfd = open(program, O_RDONLY)) == -1) pdie("could not open program"); P = malloc(sb.st_size + sizeof(uint32_t)); if (read(pfd, P, sb.st_size) != sb.st_size) die("premature end of program"); memset(P + sb.st_size, 0xFF, sizeof(uint32_t)); } static uint32_t next_instruction(void) { if (is_interactive) { /* read next instruction from stdin */ printf("%03d", PC/4); return compile(readline("> ")); } uint32_t tmp; memcpy(&tmp, &P[PC], sizeof(uint32_t)); return tmp; } int main(int argc, char *argv[]) { int ch; while ((ch = getopt(argc, argv, "dhi")) != -1) { switch (ch) { case 'd': is_debug = true; break; case 'h': usage(EXIT_SUCCESS); case 'i': is_interactive = true; break; case '?': default: usage(EXIT_FAILURE); } } argc -= optind; argv += optind; /* catch cpu signal traps */ signal(SIGILL, signal_handler); signal(SIGFPE, signal_handler); signal(SIGSEGV, signal_handler); /* load program from file if we're not in interactive mode */ if (!is_interactive) { if (argc < 1) usage(EXIT_FAILURE); read_program(argv[0]); } /* reset program counter to first instruction */ PC = 0; /* start instruction loop */ while (1) { execute(next_instruction()); PC += 4; } /* not reached, program is terminated by signal traps from the cpu */ }