aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkdx <kikoodx@paranoici.org>2023-04-13 13:54:19 +0200
committerkdx <kikoodx@paranoici.org>2023-04-13 13:54:19 +0200
commit7af20dd1b14134f355e89f64f7e269c137f6f592 (patch)
tree916c58aee0e6ed52b36e04857225ff5f8e52128b
parent5493bbbc07240d04abc51ea56d5017d200bc9eba (diff)
downloadorga-7af20dd1b14134f355e89f64f7e269c137f6f592.tar.gz
execute minimal bullshit
-rw-r--r--.gitignore1
-rw-r--r--compile_flags.txt3
-rw-r--r--samples/minimal.orgaasm13
-rw-r--r--src/drain.h29
-rw-r--r--src/ops.h69
-rw-r--r--src/orgaasm.c37
-rw-r--r--src/orgaemu.c98
7 files changed, 216 insertions, 34 deletions
diff --git a/.gitignore b/.gitignore
index dee9757..ba302ed 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
/orgaasm
/orgaemu
+/*.rom
diff --git a/compile_flags.txt b/compile_flags.txt
new file mode 100644
index 0000000..c376403
--- /dev/null
+++ b/compile_flags.txt
@@ -0,0 +1,3 @@
+-Wall
+-Wextra
+-std=c99
diff --git a/samples/minimal.orgaasm b/samples/minimal.orgaasm
new file mode 100644
index 0000000..5ae1d7b
--- /dev/null
+++ b/samples/minimal.orgaasm
@@ -0,0 +1,13 @@
+LIT 0068 WRT ( h )
+LIT 0065 WRT ( e )
+LIT 006c WRT ( l )
+LIT 006c WRT ( l )
+LIT 006f WRT ( o )
+LIT 0020 WRT ( )
+LIT 0077 WRT ( w )
+LIT 006f WRT ( o )
+LIT 0072 WRT ( r )
+LIT 006c WRT ( l )
+LIT 0064 WRT ( d )
+LIT 000a WRT ( \n )
+RET
diff --git a/src/drain.h b/src/drain.h
new file mode 100644
index 0000000..d0f1111
--- /dev/null
+++ b/src/drain.h
@@ -0,0 +1,29 @@
+#pragma once
+#include <stdio.h>
+#include <stdlib.h>
+
+static char *
+drain(FILE *fp, long *size)
+{
+ if (fseek(fp, 0, SEEK_END) < 0) {
+ perror("drain:SEEK_END");
+ return NULL;
+ }
+ *size = ftell(fp);
+ if (fseek(fp, 0, SEEK_SET) < 0) {
+ perror("drain:SEEK_SET");
+ return NULL;
+ }
+ char *const s = malloc(*size + 1);
+ if (s == NULL) {
+ perror("drain:malloc");
+ return NULL;
+ }
+ if ((long)fread(s, 1, *size, fp) != *size) {
+ perror("drain:fread");
+ free(s);
+ return NULL;
+ }
+ s[*size] = '\0';
+ return s;
+}
diff --git a/src/ops.h b/src/ops.h
new file mode 100644
index 0000000..2ad2285
--- /dev/null
+++ b/src/ops.h
@@ -0,0 +1,69 @@
+#pragma once
+
+enum {
+ OP_NOP,
+ OP_LIT,
+ OP_POP,
+ OP_NIP,
+ OP_SWP,
+ OP_ROT,
+ OP_DUP,
+ OP_OVR,
+ OP_EQU,
+ OP_NEQ,
+ OP_GTH,
+ OP_LTH,
+ OP_JEZ,
+ OP_JNZ,
+ OP_JMP,
+ OP_JRT,
+ OP_RET,
+ OP_LDA,
+ OP_STA,
+ OP_RED,
+ OP_WRT,
+ OP_ADD,
+ OP_SUB,
+ OP_MUL,
+ OP_DIV,
+ OP_AND,
+ OP_ORA,
+ OP_XOR,
+ OP_LSF,
+ OP_RSF,
+ OP_SLP,
+};
+
+static const char ops[][4] = {
+ [OP_NOP] = "NOP",
+ [OP_LIT] = "LIT",
+ [OP_POP] = "POP",
+ [OP_NIP] = "NIP",
+ [OP_SWP] = "SWP",
+ [OP_ROT] = "ROT",
+ [OP_DUP] = "DUP",
+ [OP_OVR] = "OVR",
+ [OP_EQU] = "EQU",
+ [OP_NEQ] = "NEQ",
+ [OP_GTH] = "GTH",
+ [OP_LTH] = "LTH",
+ [OP_JEZ] = "JEZ",
+ [OP_JNZ] = "JNZ",
+ [OP_JMP] = "JMP",
+ [OP_JRT] = "JRT",
+ [OP_RET] = "RET",
+ [OP_LDA] = "LDA",
+ [OP_STA] = "STA",
+ [OP_RED] = "RED",
+ [OP_WRT] = "WRT",
+ [OP_ADD] = "ADD",
+ [OP_SUB] = "SUB",
+ [OP_MUL] = "MUL",
+ [OP_DIV] = "DIV",
+ [OP_AND] = "AND",
+ [OP_ORA] = "ORA",
+ [OP_XOR] = "XOR",
+ [OP_LSF] = "LSF",
+ [OP_RSF] = "RSF",
+ [OP_SLP] = "SLP",
+};
diff --git a/src/orgaasm.c b/src/orgaasm.c
index 8e1aa3f..d48ad94 100644
--- a/src/orgaasm.c
+++ b/src/orgaasm.c
@@ -1,3 +1,5 @@
+#include "ops.h"
+#include "drain.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -10,12 +12,6 @@ struct Label {
Label *next;
};
-static const char ops[][4] = {
- "NOP", "LIT", "POP", "NIP", "SWP", "ROT", "DUP", "OVR", "EQU", "NEQ",
- "GTH", "LTH", "JEZ", "JNZ", "JMP", "JRT", "RET", "LDA", "STA", "RED",
- "WRT", "ADD", "SUB", "MUL", "DIV", "AND", "ORA", "XOR", "LSF", "RSF",
- "SLP"
-};
static const int hextable[256] = {
['0'] = 0x0, ['1'] = 0x1, ['2'] = 0x2, ['3'] = 0x3, ['4'] = 0x4,
['5'] = 0x5, ['6'] = 0x6, ['7'] = 0x7, ['8'] = 0x8, ['9'] = 0x9,
@@ -194,32 +190,6 @@ second_pass(char *s)
}
}
-static char *
-drain(FILE *fp)
-{
- if (fseek(fp, 0, SEEK_END) < 0) {
- perror("drain:SEEK_END");
- return NULL;
- }
- const long size = ftell(fp);
- if (fseek(fp, 0, SEEK_SET) < 0) {
- perror("drain:SEEK_SET");
- return NULL;
- }
- char *const data = malloc(size + 1);
- if (data == NULL) {
- perror("drain:malloc");
- return NULL;
- }
- if ((long)fread(data, 1, size, fp) != size) {
- perror("drain:fread");
- free(data);
- return NULL;
- }
- data[size] = '\0';
- return data;
-}
-
int
main(int argc, char **argv)
{
@@ -235,7 +205,8 @@ main(int argc, char **argv)
perror(argv[1]);
return fail();
}
- data = drain(fp);
+ long size;
+ data = drain(fp, &size);
fclose(fp);
if (data == NULL)
return fail();
diff --git a/src/orgaemu.c b/src/orgaemu.c
index 00c30cf..be53a22 100644
--- a/src/orgaemu.c
+++ b/src/orgaemu.c
@@ -1,8 +1,104 @@
+#include "drain.h"
+#include "ops.h"
#include <stdio.h>
+#include <stdint.h>
+
+#define MEM_SIZE 0xffff
+
+static uint16_t *stack = NULL;
+static size_t stack_ptr = 0;
+
+static uint16_t
+get_short(const unsigned char *s)
+{
+ return s[0] | (s[1] * 0x0100);
+}
+
+static void
+push(uint16_t v)
+{
+ stack[stack_ptr] = v;
+ stack_ptr += 1;
+ if (stack_ptr >= MEM_SIZE) {
+ fprintf(stderr, "stack overflow\n");
+ return;
+ }
+}
+
+static uint16_t
+pop(void)
+{
+ if (stack_ptr == 0) {
+ fprintf(stderr, "stack underflow\n");
+ return 0;
+ }
+ stack_ptr -= 1;
+ return stack[stack_ptr];
+}
+
+static void
+exec_data(uint16_t *mem)
+{
+ for (long pc = 0; pc < MEM_SIZE; pc++) {
+ switch (mem[pc]) {
+ case OP_NOP:
+ break;
+ case OP_LIT:
+ push(mem[pc + 1]);
+ pc += 1;
+ break;
+ case OP_WRT:
+ putchar(pop());
+ break;
+ case OP_RET:
+ return;
+ default:
+ fprintf(stderr, "unhandled opcode %04x\n", mem[pc]);
+ return;
+ }
+ }
+}
int
main(int argc, char **argv)
{
- (void)argc, (void)argv;
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s <rom>\n", argv[0]);
+ return 1;
+ }
+
+ FILE *file = fopen(argv[1], "rb");
+ if (file == NULL) {
+ perror(argv[1]);
+ return 1;
+ }
+
+ long size;
+ unsigned char *const data = (unsigned char*)drain(file, &size);
+ fclose(file);
+ if (data == NULL)
+ return 1;
+
+ uint16_t *mem = calloc(MEM_SIZE, sizeof(uint16_t));
+ if (mem == NULL) {
+ perror("main:calloc");
+ free(data);
+ return 1;
+ }
+
+ for (long i = 0; i < size; i += 2)
+ mem[i / 2] = get_short(data + i);
+ free(data);
+
+ stack = calloc(MEM_SIZE, sizeof(uint16_t));
+ if (stack == NULL) {
+ perror("main:calloc");
+ free(mem);
+ return 1;
+ }
+
+ exec_data(mem);
+ free(mem);
+ free(stack);
return 0;
}