aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkdx <kikoodx@paranoici.org>2023-04-13 14:22:25 +0200
committerkdx <kikoodx@paranoici.org>2023-04-13 14:22:25 +0200
commit54e5a3fc57b9cfdaf4650486971834fd111b209b (patch)
treecc37767868c0b0cb2525abbe27e719cc362094bf
parent7af20dd1b14134f355e89f64f7e269c137f6f592 (diff)
downloadorga-54e5a3fc57b9cfdaf4650486971834fd111b209b.tar.gz
easy clap
-rw-r--r--samples/helloworld.orgaasm2
-rw-r--r--src/orgaasm.c4
-rw-r--r--src/orgaemu.c109
3 files changed, 101 insertions, 14 deletions
diff --git a/samples/helloworld.orgaasm b/samples/helloworld.orgaasm
index 9401e8f..d968543 100644
--- a/samples/helloworld.orgaasm
+++ b/samples/helloworld.orgaasm
@@ -10,4 +10,4 @@ RET
RET
( "hello world" )
-@hellostr 0068 0065 006c 006c 006f 0020 0077 006f 0072 006c 0064 0000
+@hellostr 0068 0065 006c 006c 006f 0020 0077 006f 0072 006c 0064 000a 0000
diff --git a/src/orgaasm.c b/src/orgaasm.c
index d48ad94..cafab0e 100644
--- a/src/orgaasm.c
+++ b/src/orgaasm.c
@@ -58,7 +58,9 @@ skip_comments(void)
static void
write_short(uint_least16_t v)
{
- if (verbose) printf("write: %04x\n", v);
+ static unsigned int write_n = 0;
+ if (verbose) printf("write %04x: %04x\n", write_n, v);
+ write_n += 1;
if (fputc(v & 0x00ff, outfile) == EOF ||
fputc(v / 0x0100, outfile) == EOF) {
fprintf(stderr, "fputc failed\n");
diff --git a/src/orgaemu.c b/src/orgaemu.c
index be53a22..b824415 100644
--- a/src/orgaemu.c
+++ b/src/orgaemu.c
@@ -5,8 +5,20 @@
#define MEM_SIZE 0xffff
-static uint16_t *stack = NULL;
-static size_t stack_ptr = 0;
+static uint16_t *mem = NULL, *stack = NULL, *rstack = NULL;
+static size_t stack_ptr = 0, rstack_ptr = 0;
+
+static int
+fail(void)
+{
+ if (mem != NULL)
+ free(mem);
+ if (stack != NULL)
+ free(stack);
+ if (rstack != NULL)
+ free(rstack);
+ return 1;
+}
static uint16_t
get_short(const unsigned char *s)
@@ -21,7 +33,7 @@ push(uint16_t v)
stack_ptr += 1;
if (stack_ptr >= MEM_SIZE) {
fprintf(stderr, "stack overflow\n");
- return;
+ exit(fail());
}
}
@@ -30,16 +42,38 @@ pop(void)
{
if (stack_ptr == 0) {
fprintf(stderr, "stack underflow\n");
- return 0;
+ exit(fail());
}
stack_ptr -= 1;
return stack[stack_ptr];
}
+
+static void
+push_rs(uint16_t v)
+{
+ rstack[rstack_ptr] = v;
+ rstack_ptr += 1;
+ if (rstack_ptr >= MEM_SIZE) {
+ fprintf(stderr, "return stack overflow\n");
+ exit(fail());
+ }
+}
+static uint16_t
+pop_rs(void)
+{
+ if (rstack_ptr == 0) {
+ fprintf(stderr, "return stack underflow\n");
+ exit(fail());
+ }
+ rstack_ptr -= 1;
+ return rstack[rstack_ptr];
+}
+
static void
exec_data(uint16_t *mem)
{
- for (long pc = 0; pc < MEM_SIZE; pc++) {
+ for (long pc = 0; pc < MEM_SIZE;) {
switch (mem[pc]) {
case OP_NOP:
break;
@@ -47,15 +81,63 @@ exec_data(uint16_t *mem)
push(mem[pc + 1]);
pc += 1;
break;
+ case OP_POP:
+ pop();
+ break;
+ case OP_NIP: {
+ const uint16_t a = pop();
+ pop();
+ push(a);
+ } break;
+ case OP_SWP: {
+ const uint16_t a = pop();
+ const uint16_t b = pop();
+ push(a);
+ push(b);
+ } break;
+ case OP_DUP: {
+ const uint16_t a = pop();
+ push(a);
+ push(a);
+ } break;
+ case OP_ADD:
+ push(pop() + pop());
+ break;
case OP_WRT:
putchar(pop());
break;
+ case OP_JNZ:
+ if (pop() != 0) {
+ pc = mem[pc + 1];
+ continue;
+ }
+ pc += 1;
+ break;
+ case OP_JRT:
+ push_rs(pc);
+ pc = mem[pc + 1];
+ continue;
case OP_RET:
+ if (rstack_ptr > 0) {
+ pc = pop_rs() + 1;
+ break;
+ }
return;
+ case OP_LDA:
+ push(mem[pop()]);
+ break;
+ case OP_STA: {
+ const uint16_t a = pop();
+ const uint16_t b = pop();
+ mem[a] = b;
+ } break;
default:
fprintf(stderr, "unhandled opcode %04x\n", mem[pc]);
- return;
+ if (mem[pc] <= OP_SLP)
+ fprintf(stderr, "(%s)\n", ops[mem[pc]]);
+ exit(fail());
}
+ pc += 1;
}
}
@@ -79,7 +161,7 @@ main(int argc, char **argv)
if (data == NULL)
return 1;
- uint16_t *mem = calloc(MEM_SIZE, sizeof(uint16_t));
+ mem = calloc(MEM_SIZE, sizeof(uint16_t));
if (mem == NULL) {
perror("main:calloc");
free(data);
@@ -93,12 +175,15 @@ main(int argc, char **argv)
stack = calloc(MEM_SIZE, sizeof(uint16_t));
if (stack == NULL) {
perror("main:calloc");
- free(mem);
- return 1;
+ return fail();
+ }
+
+ rstack = calloc(MEM_SIZE, sizeof(uint16_t));
+ if (rstack == NULL) {
+ perror("main:calloc");
+ return fail();
}
exec_data(mem);
- free(mem);
- free(stack);
- return 0;
+ return fail(), 0;
}