add SYS instruction
This commit is contained in:
parent
4667df1425
commit
467ec78e89
17
README.md
17
README.md
|
|
@ -20,6 +20,7 @@
|
||||||
| MUL | mul r1, r2 |
|
| MUL | mul r1, r2 |
|
||||||
| DIV | div r1, r2 |
|
| DIV | div r1, r2 |
|
||||||
| CALL | call \<label\> |
|
| CALL | call \<label\> |
|
||||||
|
| SYS | sys \<syscall_no\> |
|
||||||
| HLT (Halt) | hlt |
|
| HLT (Halt) | hlt |
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -33,6 +34,7 @@
|
||||||
| PC | 16-bit | Program Counter |
|
| PC | 16-bit | Program Counter |
|
||||||
| SP | 16-bit | Stack pointer |
|
| SP | 16-bit | Stack pointer |
|
||||||
|
|
||||||
|
|
||||||
## Flags
|
## Flags
|
||||||
| Flag | Description |
|
| Flag | Description |
|
||||||
| ----- | ------------ |
|
| ----- | ------------ |
|
||||||
|
|
@ -40,6 +42,14 @@
|
||||||
| C | Carry/Borrow |
|
| C | Carry/Borrow |
|
||||||
|
|
||||||
|
|
||||||
|
## Syscalls
|
||||||
|
| Imm | Meaning |
|
||||||
|
| --- | ------- |
|
||||||
|
| 0 | Exit Program |
|
||||||
|
| 1 | Print register A as integer |
|
||||||
|
| 2 | Print register A as ASCII char |
|
||||||
|
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
```bash
|
```bash
|
||||||
cargo run -- --f <examples/filename.asc>
|
cargo run -- --f <examples/filename.asc>
|
||||||
|
|
@ -49,11 +59,12 @@ cargo run -- --f <examples/filename.asc>
|
||||||
- [x] Assembler
|
- [x] Assembler
|
||||||
- [x] Lexer/Tokenizer
|
- [x] Lexer/Tokenizer
|
||||||
- [x] Add label support (supporting JMP/JZ/JNZ)
|
- [x] Add label support (supporting JMP/JZ/JNZ)
|
||||||
- [ ] Add instructions
|
- [x] Add instructions
|
||||||
- [x] CMP
|
- [x] CMP
|
||||||
- [x] MUL
|
- [x] MUL
|
||||||
- [x] DIV
|
- [x] DIV
|
||||||
- [x] CALL
|
- [x] CALL
|
||||||
- [x] RET
|
- [x] RET
|
||||||
- [ ] Error handling
|
- [x] SYS
|
||||||
- [ ] Build Debugger
|
- [ ] Better Error handling
|
||||||
|
- [ ] TUI Debugger
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
mov a, 72 ; 'H'
|
||||||
|
sys 2
|
||||||
|
mov a, 105 ; 'i'
|
||||||
|
sys 2
|
||||||
|
mov a, 10 ; '\n'
|
||||||
|
sys 2
|
||||||
|
sys 0
|
||||||
|
|
@ -26,6 +26,7 @@ fn is_reg(s: &str) -> bool {
|
||||||
fn instr_size(tokens: &[String]) -> u16 {
|
fn instr_size(tokens: &[String]) -> u16 {
|
||||||
match tokens[0].as_str() {
|
match tokens[0].as_str() {
|
||||||
"mov" | "add" | "sub" | "jmp" | "jz" | "jnz" | "cmp" | "mul" | "div" | "call" => 3,
|
"mov" | "add" | "sub" | "jmp" | "jz" | "jnz" | "cmp" | "mul" | "div" | "call" => 3,
|
||||||
|
"sys" => 2,
|
||||||
"hlt" | "ret" => 1,
|
"hlt" | "ret" => 1,
|
||||||
_ => panic!("Unknown instruction {}", tokens[0]),
|
_ => panic!("Unknown instruction {}", tokens[0]),
|
||||||
}
|
}
|
||||||
|
|
@ -190,6 +191,12 @@ pub fn assembler(source: &str) -> Vec<u8> {
|
||||||
bytes.push(Instruction::HLT as 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),
|
_ => panic!("Line {}: unknown instruction", line_no + 1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
58
src/cpu.rs
58
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::CMP_RR as u8 => self.cmp_rr(mem),
|
||||||
x if x == Instruction::MUL as u8 => self.mul(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::DIV as u8 => self.div(mem),
|
||||||
x if x == Instruction::CALL as u8 => {
|
x if x == Instruction::CALL as u8 => self.call(mem),
|
||||||
let low = mem.read(self.pc) as u16; self.inc_pc();
|
x if x == Instruction::RET as u8 => self.ret(mem),
|
||||||
let high = mem.read(self.pc) as u16; self.inc_pc();
|
x if x == Instruction::SYS as u8 => self.syscall(mem),
|
||||||
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::HLT as u8 => self.halt(),
|
x if x == Instruction::HLT as u8 => self.halt(),
|
||||||
_ => panic!("Unknown opcode {:02X}", opcode),
|
_ => panic!("Unknown opcode {:02X}", opcode),
|
||||||
}
|
}
|
||||||
|
|
@ -94,12 +82,10 @@ impl CPU {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inc_sp(&mut self) {
|
pub fn inc_sp(&mut self) {
|
||||||
// self.sp += 1;
|
|
||||||
self.sp = self.sp.wrapping_add(1);
|
self.sp = self.sp.wrapping_add(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dec_sp(&mut self) {
|
pub fn dec_sp(&mut self) {
|
||||||
// self.sp -= 1;
|
|
||||||
self.sp = self.sp.wrapping_sub(1);
|
self.sp = self.sp.wrapping_sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -379,6 +365,44 @@ impl CPU {
|
||||||
// carry unchanged
|
// 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 {
|
fn get_reg(&self, r: u8) -> u8 {
|
||||||
match r {
|
match r {
|
||||||
0 => self.a,
|
0 => self.a,
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ pub enum Instruction {
|
||||||
DIV = 0x0D,
|
DIV = 0x0D,
|
||||||
CALL = 0x0E,
|
CALL = 0x0E,
|
||||||
RET = 0x0F,
|
RET = 0x0F,
|
||||||
|
SYS = 0x10,
|
||||||
HLT = 0xFF,
|
HLT = 0xFF,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,6 +34,7 @@ impl Instruction {
|
||||||
0x0D => "DIV",
|
0x0D => "DIV",
|
||||||
0x0E => "CALL",
|
0x0E => "CALL",
|
||||||
0x0F => "RET",
|
0x0F => "RET",
|
||||||
|
0x10 => "SYS",
|
||||||
0xFF => "HLT",
|
0xFF => "HLT",
|
||||||
|
|
||||||
_ => "???",
|
_ => "???",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue