summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.b.r1a.kak.4uCRcR6
-rw-r--r--asm.ha19
-rw-r--r--bee.r11
-rw-r--r--disasm.ha8
-rw-r--r--main.ha15
-rw-r--r--r1-better.txt1
-rw-r--r--r1.ha150
-rw-r--r--u.r1a10
8 files changed, 167 insertions, 43 deletions
diff --git a/.b.r1a.kak.4uCRcR b/.b.r1a.kak.4uCRcR
deleted file mode 100644
index 57cc788..0000000
--- a/.b.r1a.kak.4uCRcR
+++ /dev/null
@@ -1,6 +0,0 @@
-i dup drp swp
-i psh pop psh
-j 1234
-: penis
-
-? 142345
diff --git a/asm.ha b/asm.ha
index 8bb3690..e4add61 100644
--- a/asm.ha
+++ b/asm.ha
@@ -12,8 +12,8 @@ type state = struct {
here: size,
};
-export fn run_asm() void = {
- let file = os::open("u.r1a")!;
+export fn run_asm(filename: str) void = {
+ let file = os::open(filename)!;
let scanner = bufio::newscanner(file, 4096);
let s = state { ... };
for (true) match (bufio::scan_line(&scanner)!) {
@@ -57,17 +57,18 @@ fn literal_instr(s: *state, tok: strings::tokenizer) void = {
fn arith_instr(s: *state, tok: strings::tokenizer) void = {
let instr = 0u16;
- for (let i=0z; i<3; i+=1) match (strings::next_token(&tok)) {
- case void => fmt::fatal("expected 3 opcodes");
- case let word: str => {
+ for (let i=0z; i<3; i+=1) {
instr <<= 5;
- let op = match (opcodefromstr(word)) {
- case invalid_opcode => fmt::fatalf("unknown opcode {}",word);
- case let o: uint => yield o;
+ let op = match (strings::next_token(&tok)) {
+ case void => yield 0; // nop
+ case let word: str => yield match (opcodefromstr(word)) {
+ case invalid_opcode => fmt::fatalf("unknown opcode {}",word);
+ case let o: uint => yield o;
};
+ };
+
instr |= (op:u16);
};
- };
set_mem(&s.mem, s.here, instr&0x7fff);
s.here += 2;
diff --git a/bee.r1 b/bee.r1
deleted file mode 100644
index 8b13789..0000000
--- a/bee.r1
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/disasm.ha b/disasm.ha
index 24df860..35727a0 100644
--- a/disasm.ha
+++ b/disasm.ha
@@ -2,8 +2,12 @@ use io;
use fmt;
fn pr_instr(instr: u16, pos: (void|u16)) (void|io::error) = {
- if (pos is u16)
- fmt::printf("{:04x}: ",pos as u16)!;
+ if (pos is u16) {
+ fmt::printf(" [{:04x}]:",pos as u16)!;
+ } else {
+ fmt::print(" ")!;
+ };
+
fmt::printf("{:04x} ",instr)?;
if (instr & 0x8000 == 0) {
pr_instr_arith(instr)?;
diff --git a/main.ha b/main.ha
new file mode 100644
index 0000000..9ca7633
--- /dev/null
+++ b/main.ha
@@ -0,0 +1,15 @@
+use os;
+use fmt;
+
+
+
+export fn main() void = {
+ if (len(os::args) < 2)
+ fmt::fatal("usage: {} <asm|disasm|run> FILENAME");
+ switch(os::args[1]) {
+ case "asm" => run_asm(os::args[2]);
+ case "disasm" => run_disasm(os::args[2]);
+ case "run" => run_run(os::args[2]);
+ case => fmt::fatal("what do you want me to do");
+ };
+};
diff --git a/r1-better.txt b/r1-better.txt
index ffc5426..6c56b13 100644
--- a/r1-better.txt
+++ b/r1-better.txt
@@ -62,6 +62,7 @@ sys op:
2 clear selected flags (c2-)
3 pop flags (f3-)
4 halt (4-)
+5 debug print (x5-)
%get-flags { zero sys }
%set-flags (f-) { one sys }
diff --git a/r1.ha b/r1.ha
index 5ad7c4d..1cd4aaf 100644
--- a/r1.ha
+++ b/r1.ha
@@ -21,6 +21,23 @@ fn pop(s: *stack) u16 = {
return s.d[s.p];
};
+fn peek(s: *stack) u16 = {
+ assert(s.p > 0, "stack underflow");
+ return s.d[s.p-1];
+};
+
+fn checkstack(s: *stack, depth: size) void = {
+ assert(s.p >= depth, "stack not deep enough");
+};
+
+fn readmem(mem: []u8, where: u16) u16 = {
+ if (where <= len(mem) - 2) {
+ return endian::begetu16(mem[where..]);
+ } else {
+ return 0;
+ };
+};
+
fn pr_stack(s: *stack) (void | io::error) = {
fmt::print(" stack:")?;
for (let i = 0z; i < s.p; i = i+1)
@@ -30,33 +47,128 @@ fn pr_stack(s: *stack) (void | io::error) = {
type cpu = struct {
pc: u16,
- ostack: stack,
+ dstack: stack,
rstack: stack,
+ mem: []u8,
+ stopped: bool,
+};
+
+
+fn do_instr(cpu: *cpu, instr: u16) void = {
+ if (instr & 0x8000 == 0) {
+ do_instr_arith(cpu,instr);
+ } else {
+ do_instr_jmp(cpu,instr);
+ };
};
+fn do_instr_arith(cpu: *cpu,instr: u16) void = {
+ let opa = (instr&(0x1f<<10)) >> 10;
+ let opb = (instr&(0x1f<< 5)) >> 5;
+ let opc = instr&(0x1f ) ;
+ do_opcode(cpu,opa);
+ do_opcode(cpu,opb);
+ do_opcode(cpu,opc);
+};
+
+fn do_instr_jmp(cpu: *cpu,instr: u16) void = {
+ let ty = (instr&0x6000)>>13;
+ let addr = (instr&0x1fff)<<1;
+ switch (ty) {
+ case 0 => // jmp
+ cpu.pc = addr;
+ case 1 => { // cjmp
+ let val = pop(&cpu.dstack);
+ if (val != 0) cpu.pc = addr;
+ };
+ case 2 => { // call
+ push(&cpu.rstack,cpu.pc);
+ cpu.pc = addr;
+ };
+ };
+};
-export fn run_disasm() void = {
- let rom = io::drain(os::open("bee.r1")!)!;
+fn do_opcode(cpu: *cpu,opc: u16) void = {
+ switch (opc) {
+ case opcode::nop => yield;
+ case opcode::psh => push(&cpu.rstack,pop(&cpu.dstack));
+ case opcode::pop => push(&cpu.dstack,pop(&cpu.rstack));
+ case opcode::dup => push(&cpu.dstack,peek(&cpu.dstack));
+ case opcode::swp => {
+ let a = pop(&cpu.dstack);
+ let b = pop(&cpu.dstack);
+ push(&cpu.dstack, a);
+ push(&cpu.dstack, b);
+ };
+ case opcode::ovr => {
+ checkstack(&cpu.dstack,2);
+ push(&cpu.dstack, cpu.dstack.d[cpu.dstack.p-2]);
+ };
+ case opcode::drp => pop(&cpu.dstack);
+ case opcode::one => push(&cpu.dstack,1);
+ case opcode::zro => push(&cpu.dstack,0);
+ case opcode::ret => cpu.pc = pop(&cpu.rstack);
+ case opcode::eql => {
+ let a = pop(&cpu.dstack);
+ let b = pop(&cpu.dstack);
+ push(&cpu.dstack, if (a==b) { yield 1; } else { yield 0; });
+ };
+ case opcode::sys => {
+ let callno = pop(&cpu.dstack);
+ switch (callno) {
+ case 4 => cpu.stopped=true;
+ case 5 => fmt::printfln("{:04x}",pop(&cpu.dstack))!;
+ case => fmt::fatalf("unknown syscall {:04x}",callno);
+ };
+ };
+ case opcode::lit => {
+ push(&cpu.dstack, readmem(cpu.mem, cpu.pc));
+ cpu.pc += 2;
+ };
+ case opcode::meh => fmt::printfln("{:04x}",pop(&cpu.dstack))!;
+ case opcode::add => {
+ let a = pop(&cpu.dstack);
+ let b = pop(&cpu.dstack);
+ push(&cpu.dstack, a+b);
+ };
+ case opcode::sub=> {
+ let a = pop(&cpu.dstack);
+ let b = pop(&cpu.dstack);
+ push(&cpu.dstack, a-b);
+ };
+
+
+ case => fmt::fatalf("unimplemented opcode {}",opcodestr(opc: opcode)!);
+ };
+};
+
+export fn run_run(filename: str) void = {
+ let rom = io::drain(os::open(filename)!)!;
defer free(rom);
assert(len(rom)&1 == 0, "rom length must be even");
+ let cpu = cpu { mem=rom, ... };
+ for (!cpu.stopped) {
+ let instr = readmem(cpu.mem, cpu.pc);
+ // pr_instr(instr, cpu.pc)!;
- let cpu = cpu { ... };
-
- for (true) {
- let instr = endian::begetu16(rom[cpu.pc..]);
- pr_instr(instr, cpu.pc)!;
cpu.pc += 2;
- // if (instr == 0)
- // break
- // else if (instr & 0x8000 == 0) {
- // push(&cpu.ostack, instr);
- // fmt::printfln(" push {:04x}",instr)!;
- // } else {
- // let v = pop(&cpu.ostack);
- // fmt::printfln(" pop {:04x}", v)!;
- // };
-
- // pr_stack(&cpu.ostack)!;
+ do_instr(&cpu, instr);
+ // pr_stack(&cpu.dstack)!;
+ };
+};
+
+
+export fn run_disasm(filename: str) void = {
+ let rom = io::drain(os::open("u.r1b")!)!;
+ defer free(rom);
+ assert(len(rom)&1 == 0, "rom length must be even");
+
+ let here = 0u16;
+
+ for (here < len(rom)) {
+ let instr = endian::begetu16(rom[here..]);
+ pr_instr(instr, here)!;
+ here += 2;
};
};
diff --git a/u.r1a b/u.r1a
index ddc65b8..fb4285b 100644
--- a/u.r1a
+++ b/u.r1a
@@ -1,6 +1,4 @@
-# print 2+2
-i nop lit nop
-i dup add meh
-l 1234
-i dup pop pop
-call 2016
+i lit dup add
+l 2
+i meh lit sys
+l 4