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 \ | +| SYS | sys \ | | 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 @@ -49,11 +59,12 @@ cargo run -- --f - [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 { 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", _ => "???",