add CALL, RET
This commit is contained in:
parent
3372e774e9
commit
133f6f748d
|
|
@ -0,0 +1,7 @@
|
|||
mov a, 2
|
||||
call square
|
||||
hlt
|
||||
|
||||
square:
|
||||
mul a, a
|
||||
ret
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
mov a, 10
|
||||
mov b, 2
|
||||
mov b, 10
|
||||
div a, b
|
||||
hlt
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ 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" => 3,
|
||||
"hlt" => 1,
|
||||
"mov" | "add" | "sub" | "jmp" | "jz" | "jnz" | "cmp" | "mul" | "div" | "call" => 3,
|
||||
"hlt" | "ret" => 1,
|
||||
_ => panic!("Unknown instruction {}", tokens[0]),
|
||||
}
|
||||
}
|
||||
|
|
@ -172,6 +172,20 @@ pub fn assembler(source: &str) -> Vec<u8> {
|
|||
bytes.push(r2);
|
||||
}
|
||||
|
||||
"call" => {
|
||||
let addr = *symbols
|
||||
.get(&tokens[1])
|
||||
.expect("Unknown label");
|
||||
|
||||
bytes.push(Instruction::CALL as u8);
|
||||
bytes.push((addr & 0xFF) as u8); // low
|
||||
bytes.push((addr >> 8) as u8); // high
|
||||
}
|
||||
|
||||
"ret" => {
|
||||
bytes.push(Instruction::RET as u8);
|
||||
}
|
||||
|
||||
"hlt" => {
|
||||
bytes.push(Instruction::HLT as u8);
|
||||
}
|
||||
|
|
|
|||
42
src/cpu.rs
42
src/cpu.rs
|
|
@ -19,6 +19,22 @@ pub struct CPU {
|
|||
}
|
||||
|
||||
impl CPU {
|
||||
fn push16(&mut self, mem: &mut Memory, val: u16) {
|
||||
self.dec_sp();
|
||||
mem.write(self.sp, (val >> 8) as u8); // high
|
||||
self.dec_sp();
|
||||
mem.write(self.sp, (val & 0xFF) as u8); // low
|
||||
}
|
||||
|
||||
fn pop16(&mut self, mem: &mut Memory) -> u16 {
|
||||
let low = mem.read(self.sp) as u16;
|
||||
self.inc_sp();
|
||||
let high = mem.read(self.sp) as u16;
|
||||
self.inc_sp();
|
||||
|
||||
(high << 8) | low
|
||||
}
|
||||
|
||||
pub fn debug_instr(&self, mem: &Memory) {
|
||||
let opcode = mem.read(self.pc);
|
||||
|
||||
|
|
@ -53,6 +69,21 @@ 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::HLT as u8 => self.halt(),
|
||||
_ => panic!("Unknown opcode {:02X}", opcode),
|
||||
}
|
||||
|
|
@ -62,6 +93,17 @@ impl CPU {
|
|||
self.pc += 1;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
pub fn halt(&mut self) {
|
||||
self.halted = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ pub enum Instruction {
|
|||
CMP_RR = 0x09,
|
||||
MUL = 0x0C,
|
||||
DIV = 0x0D,
|
||||
CALL = 0x0E,
|
||||
RET = 0x0F,
|
||||
HLT = 0xFF,
|
||||
}
|
||||
|
||||
|
|
@ -29,7 +31,10 @@ impl Instruction {
|
|||
0x07 | 0x09 => "CMP",
|
||||
0x0C => "MUL",
|
||||
0x0D => "DIV",
|
||||
0x0E => "CALL",
|
||||
0x0F => "RET",
|
||||
0xFF => "HLT",
|
||||
|
||||
_ => "???",
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ struct Args {
|
|||
fn main() {
|
||||
let args = Args::parse();
|
||||
|
||||
let mut cpu = CPU::default();
|
||||
let mut cpu = CPU {sp: 0xFFFE, ..Default::default( )};
|
||||
let mut mem = Memory::new();
|
||||
|
||||
let asm = std::fs::read_to_string(args.filename).unwrap();
|
||||
|
|
|
|||
Loading…
Reference in New Issue