Krolyxon
Commit 133f6f7

Branches

Tags

Refs →

bench51133f6f7

add CALL, RET

Author
krolxon
Date
2026-01-08 19:02 +0530
Parent
3372e77
Commit
133f6f748dd8d687273d991a134fad1c455ef99c

+72 −4

6 files changed

  1. A examples/call.asm +7 −0
  2. M examples/div.asm +1 −1
  3. M src/assembler.rs +16 −2
  4. M src/cpu.rs +42 −0
  5. M src/instructions.rs +5 −0
  6. M src/main.rs +1 −1
A examples/call.asm View
@@ -0,0 +1,7 @@
1+mov a, 2
2+call square
3+hlt
4+
5+square:
6+ mul a, a
7+ ret
M examples/div.asm View
@@ -1,4 +1,4 @@
11 mov a, 10
2−mov b, 2
2+mov b, 10
33 div a, b
44 hlt
M src/assembler.rs View
@@ -25,8 +25,8 @@ fn is_reg(s: &str) -> bool {
2525
2626 fn instr_size(tokens: &[String]) -> u16 {
2727 match tokens[0].as_str() {
28− "mov" | "add" | "sub" | "jmp" | "jz" | "jnz" | "cmp" | "mul" | "div" => 3,
29− "hlt" => 1,
28+ "mov" | "add" | "sub" | "jmp" | "jz" | "jnz" | "cmp" | "mul" | "div" | "call" => 3,
29+ "hlt" | "ret" => 1,
3030 _ => panic!("Unknown instruction {}", tokens[0]),
3131 }
3232 }
@@ -172,6 +172,20 @@ pub fn assembler(source: &str) -> Vec<u8> {
172172 bytes.push(r2);
173173 }
174174
175+ "call" => {
176+ let addr = *symbols
177+ .get(&tokens[1])
178+ .expect("Unknown label");
179+
180+ bytes.push(Instruction::CALL as u8);
181+ bytes.push((addr & 0xFF) as u8); // low
182+ bytes.push((addr >> 8) as u8); // high
183+ }
184+
185+ "ret" => {
186+ bytes.push(Instruction::RET as u8);
187+ }
188+
175189 "hlt" => {
176190 bytes.push(Instruction::HLT as u8);
177191 }
M src/cpu.rs View
@@ -19,6 +19,22 @@ pub struct CPU {
1919 }
2020
2121 impl CPU {
22+ fn push16(&mut self, mem: &mut Memory, val: u16) {
23+ self.dec_sp();
24+ mem.write(self.sp, (val >> 8) as u8); // high
25+ self.dec_sp();
26+ mem.write(self.sp, (val & 0xFF) as u8); // low
27+ }
28+
29+ fn pop16(&mut self, mem: &mut Memory) -> u16 {
30+ let low = mem.read(self.sp) as u16;
31+ self.inc_sp();
32+ let high = mem.read(self.sp) as u16;
33+ self.inc_sp();
34+
35+ (high << 8) | low
36+ }
37+
2238 pub fn debug_instr(&self, mem: &Memory) {
2339 let opcode = mem.read(self.pc);
2440
@@ -53,6 +69,21 @@ impl CPU {
5369 x if x == Instruction::CMP_RR as u8 => self.cmp_rr(mem),
5470 x if x == Instruction::MUL as u8 => self.mul(mem),
5571 x if x == Instruction::DIV as u8 => self.div(mem),
72+ x if x == Instruction::CALL as u8 => {
73+ let low = mem.read(self.pc) as u16; self.inc_pc();
74+ let high = mem.read(self.pc) as u16; self.inc_pc();
75+ let addr = (high << 8) | low;
76+
77+ let return_addr = self.pc;
78+
79+ self.push16(mem, return_addr);
80+ self.pc = addr;
81+
82+ },
83+ x if x == Instruction::RET as u8 => {
84+ let addr = self.pop16(mem);
85+ self.pc = addr;
86+ },
5687 x if x == Instruction::HLT as u8 => self.halt(),
5788 _ => panic!("Unknown opcode {:02X}", opcode),
5889 }
@@ -62,6 +93,17 @@ impl CPU {
6293 self.pc += 1;
6394 }
6495
96+ pub fn inc_sp(&mut self) {
97+ // self.sp += 1;
98+ self.sp = self.sp.wrapping_add(1);
99+ }
100+
101+ pub fn dec_sp(&mut self) {
102+ // self.sp -= 1;
103+ self.sp = self.sp.wrapping_sub(1);
104+ }
105+
106+
65107 pub fn halt(&mut self) {
66108 self.halted = true;
67109 }
M src/instructions.rs View
@@ -14,6 +14,8 @@ pub enum Instruction {
1414 CMP_RR = 0x09,
1515 MUL = 0x0C,
1616 DIV = 0x0D,
17+ CALL = 0x0E,
18+ RET = 0x0F,
1719 HLT = 0xFF,
1820 }
1921
@@ -29,7 +31,10 @@ impl Instruction {
2931 0x07 | 0x09 => "CMP",
3032 0x0C => "MUL",
3133 0x0D => "DIV",
34+ 0x0E => "CALL",
35+ 0x0F => "RET",
3236 0xFF => "HLT",
37+
3338 _ => "???",
3439 }
3540 }
M src/main.rs View
@@ -21,7 +21,7 @@ struct Args {
2121 fn main() {
2222 let args = Args::parse();
2323
24− let mut cpu = CPU::default();
24+ let mut cpu = CPU {sp: 0xFFFE, ..Default::default( )};
2525 let mut mem = Memory::new();
2626
2727 let asm = std::fs::read_to_string(args.filename).unwrap();