summaryrefslogtreecommitdiffstats
path: root/src/emu/risci.c
diff options
context:
space:
mode:
authorBenedikt Böhm <bb@xnull.de>2009-05-18 20:53:42 +0200
committerBenedikt Böhm <bb@xnull.de>2009-05-18 20:53:42 +0200
commit49f510d2d60129526832bfcd9c0f4049962bc80e (patch)
tree2828b773c75bdbc4014a3421c8046778a1a2b11b /src/emu/risci.c
parent144258f0196b69cbdd2f29bd501276942efc3182 (diff)
downloadswppy-49f510d2d60129526832bfcd9c0f4049962bc80e.tar.gz
swppy-49f510d2d60129526832bfcd9c0f4049962bc80e.tar.xz
swppy-49f510d2d60129526832bfcd9c0f4049962bc80e.zip
move stuff around and create initial source structure
Diffstat (limited to 'src/emu/risci.c')
-rw-r--r--src/emu/risci.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/src/emu/risci.c b/src/emu/risci.c
new file mode 100644
index 0000000..8c4e30f
--- /dev/null
+++ b/src/emu/risci.c
@@ -0,0 +1,134 @@
+#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 */
+}