blob: 8c4e30f0955c02d557cbe38ccadb5a7c9b4566bb (
plain) (
tree)
|
|
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <readline/readline.h>
#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] <program>\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 */
}
|