aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md17
-rw-r--r--examples/syscall.asm7
-rw-r--r--src/assembler.rs7
-rw-r--r--src/cpu.rs58
-rw-r--r--src/instructions.rs2
5 files changed, 71 insertions, 20 deletions
diff --git a/README.md b/README.md
index 717351e..af5513c 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,7 @@
| MUL | mul r1, r2 |
| DIV | div r1, r2 |
| CALL | call \<label\> |
+| SYS | sys \<syscall_no\> |
| HLT (Halt) | hlt |
@@ -33,6 +34,7 @@
| PC | 16-bit | Program Counter |
| SP | 16-bit | Stack pointer |
+
## Flags
| Flag | Description |
| ----- | ------------ |
@@ -40,6 +42,14 @@
| C | Carry/Borrow |
+## Syscalls
+| Imm | Meaning |
+| --- | ------- |
+| 0 | Exit Program |
+| 1 | Print register A as integer |
+| 2 | Print register A as ASCII char |
+
+
# Usage
```bash
cargo run -- --f <examples/filename.asc>
@@ -49,11 +59,12 @@ cargo run -- --f <examples/filename.asc>
- [x] Assembler
- [x] Lexer/Tokenizer
- [x] Add label support (supporting JMP/JZ/JNZ)
-- [ ] Add instructions
+- [x] Add instructions
- [x] CMP
- [x] MUL
- [x] DIV
- [x] CALL
- [x] RET
-- [ ] Error handling
-- [ ] Build Debugger
+ - [x] SYS
+- [ ] Better Error handling
+- [ ] TUI Debugger
diff --git a/examples/syscall.asm b/examples/syscall.asm
new file mode 100644
index 0000000..bddefbd
--- /dev/null
+++ b/examples/syscall.asm
@@ -0,0 +1,7 @@
+mov a, 72 ; 'H'
+sys 2
+mov a, 105 ; 'i'
+sys 2
+mov a, 10 ; '\n'
+sys 2
+sys 0
diff --git a/src/assembler.rs b/src/assembler.rs
index 73dec00..784337b 100644
--- a/src/assembler.rs
+++ b/src/assembler.rs
@@ -26,6 +26,7 @@ fn is_reg(s: &str) -> bool {
fn instr_size(tokens: &[String]) -> u16 {
match tokens[0].as_str() {
"mov" | "add" | "sub" | "jmp" | "jz" | "jnz" | "cmp" | "mul" | "div" | "call" => 3,
+ "sys" => 2,
"hlt" | "ret" => 1,
_ => panic!("Unknown instruction {}", tokens[0]),
}
@@ -190,6 +191,12 @@ pub fn assembler(source: &str) -> Vec<u8> {
bytes.push(Instruction::HLT as u8);
}
+ "sys" => {
+ let imm = tokens[1].parse().unwrap();
+ bytes.push(Instruction::SYS as u8);
+ bytes.push(imm);
+ }
+
_ => panic!("Line {}: unknown instruction", line_no + 1),
}
}
diff --git a/src/cpu.rs b/src/cpu.rs
index 1393e95..4fad73e 100644
--- a/src/cpu.rs
+++ b/src/cpu.rs
@@ -69,21 +69,9 @@ impl CPU {
x if x == Instruction::CMP_RR as u8 => self.cmp_rr(mem),
x if x == Instruction::MUL as u8 => self.mul(mem),
x if x == Instruction::DIV as u8 => self.div(mem),
- x if x == Instruction::CALL as u8 => {
- let low = mem.read(self.pc) as u16; self.inc_pc();
- let high = mem.read(self.pc) as u16; self.inc_pc();
- let addr = (high << 8) | low;
-
- let return_addr = self.pc;
-
- self.push16(mem, return_addr);
- self.pc = addr;
-
- },
- x if x == Instruction::RET as u8 => {
- let addr = self.pop16(mem);
- self.pc = addr;
- },
+ x if x == Instruction::CALL as u8 => self.call(mem),
+ x if x == Instruction::RET as u8 => self.ret(mem),
+ x if x == Instruction::SYS as u8 => self.syscall(mem),
x if x == Instruction::HLT as u8 => self.halt(),
_ => panic!("Unknown opcode {:02X}", opcode),
}
@@ -94,12 +82,10 @@ impl CPU {
}
pub fn inc_sp(&mut self) {
- // self.sp += 1;
self.sp = self.sp.wrapping_add(1);
}
pub fn dec_sp(&mut self) {
- // self.sp -= 1;
self.sp = self.sp.wrapping_sub(1);
}
@@ -379,6 +365,44 @@ impl CPU {
// carry unchanged
}
+ pub fn call(&mut self, mem: &mut Memory ) {
+ let low = mem.read(self.pc) as u16; self.inc_pc();
+ let high = mem.read(self.pc) as u16; self.inc_pc();
+ let addr = (high << 8) | low;
+
+ let return_addr = self.pc;
+
+ self.push16(mem, return_addr);
+ self.pc = addr;
+
+ }
+
+ pub fn ret(&mut self, mem: &mut Memory) {
+ let addr = self.pop16(mem);
+ self.pc = addr;
+ }
+
+
+ pub fn syscall(&mut self, mem: &Memory) {
+ let num = mem.read(self.pc);
+ self.pc = self.pc.wrapping_add(1);
+ match num {
+ 0 => {
+ // exit
+ self.halted = true;
+ }
+ 1 => {
+ // print A as number
+ println!("{}", self.a);
+ }
+ 2 => {
+ // print A as ASCII char
+ print!("{}", self.a as char);
+ }
+ _ => panic!("Unknown syscall {}", num),
+ }
+ }
+
fn get_reg(&self, r: u8) -> u8 {
match r {
0 => self.a,
diff --git a/src/instructions.rs b/src/instructions.rs
index 620b0ad..a0d086f 100644
--- a/src/instructions.rs
+++ b/src/instructions.rs
@@ -16,6 +16,7 @@ pub enum Instruction {
DIV = 0x0D,
CALL = 0x0E,
RET = 0x0F,
+ SYS = 0x10,
HLT = 0xFF,
}
@@ -33,6 +34,7 @@ impl Instruction {
0x0D => "DIV",
0x0E => "CALL",
0x0F => "RET",
+ 0x10 => "SYS",
0xFF => "HLT",
_ => "???",