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