Krolyxon
Commit 467ec78

Branches

Tags

Refs →

bench51467ec78

add SYS instruction

Author
krolxon
Date
2026-01-08 19:21 +0530
Parent
4667df1
Commit
467ec78e894c8184144bfac039dc7d780abbd050

+71 −20

5 files changed

  1. M README.md +14 −3
  2. A examples/syscall.asm +7 −0
  3. M src/assembler.rs +7 −0
  4. M src/cpu.rs +41 −17
  5. M src/instructions.rs +2 −0
M README.md View
@@ -20,6 +20,7 @@
2020 | MUL | mul r1, r2 |
2121 | DIV | div r1, r2 |
2222 | CALL | call \<label\> |
23+| SYS | sys \<syscall_no\> |
2324 | HLT (Halt) | hlt |
2425
2526
@@ -33,6 +34,7 @@
3334 | PC | 16-bit | Program Counter |
3435 | SP | 16-bit | Stack pointer |
3536
37+
3638 ## Flags
3739 | Flag | Description |
3840 | ----- | ------------ |
@@ -40,6 +42,14 @@
4042 | C | Carry/Borrow |
4143
4244
45+## Syscalls
46+| Imm | Meaning |
47+| --- | ------- |
48+| 0 | Exit Program |
49+| 1 | Print register A as integer |
50+| 2 | Print register A as ASCII char |
51+
52+
4353 # Usage
4454 ```bash
4555 cargo run -- --f <examples/filename.asc>
@@ -49,11 +59,12 @@ cargo run -- --f <examples/filename.asc>
4959 - [x] Assembler
5060 - [x] Lexer/Tokenizer
5161 - [x] Add label support (supporting JMP/JZ/JNZ)
52−- [ ] Add instructions
62+- [x] Add instructions
5363 - [x] CMP
5464 - [x] MUL
5565 - [x] DIV
5666 - [x] CALL
5767 - [x] RET
58−- [ ] Error handling
59−- [ ] Build Debugger
68+ - [x] SYS
69+- [ ] Better Error handling
70+- [ ] TUI Debugger
A examples/syscall.asm View
@@ -0,0 +1,7 @@
1+mov a, 72 ; 'H'
2+sys 2
3+mov a, 105 ; 'i'
4+sys 2
5+mov a, 10 ; '\n'
6+sys 2
7+sys 0
M src/assembler.rs View
@@ -26,6 +26,7 @@ fn is_reg(s: &str) -> bool {
2626 fn instr_size(tokens: &[String]) -> u16 {
2727 match tokens[0].as_str() {
2828 "mov" | "add" | "sub" | "jmp" | "jz" | "jnz" | "cmp" | "mul" | "div" | "call" => 3,
29+ "sys" => 2,
2930 "hlt" | "ret" => 1,
3031 _ => panic!("Unknown instruction {}", tokens[0]),
3132 }
@@ -190,6 +191,12 @@ pub fn assembler(source: &str) -> Vec<u8> {
190191 bytes.push(Instruction::HLT as u8);
191192 }
192193
194+ "sys" => {
195+ let imm = tokens[1].parse().unwrap();
196+ bytes.push(Instruction::SYS as u8);
197+ bytes.push(imm);
198+ }
199+
193200 _ => panic!("Line {}: unknown instruction", line_no + 1),
194201 }
195202 }
M src/cpu.rs View
@@ -69,21 +69,9 @@ impl CPU {
6969 x if x == Instruction::CMP_RR as u8 => self.cmp_rr(mem),
7070 x if x == Instruction::MUL as u8 => self.mul(mem),
7171 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− },
72+ x if x == Instruction::CALL as u8 => self.call(mem),
73+ x if x == Instruction::RET as u8 => self.ret(mem),
74+ x if x == Instruction::SYS as u8 => self.syscall(mem),
8775 x if x == Instruction::HLT as u8 => self.halt(),
8876 _ => panic!("Unknown opcode {:02X}", opcode),
8977 }
@@ -94,12 +82,10 @@ impl CPU {
9482 }
9583
9684 pub fn inc_sp(&mut self) {
97− // self.sp += 1;
9885 self.sp = self.sp.wrapping_add(1);
9986 }
10087
10188 pub fn dec_sp(&mut self) {
102− // self.sp -= 1;
10389 self.sp = self.sp.wrapping_sub(1);
10490 }
10591
@@ -379,6 +365,44 @@ impl CPU {
379365 // carry unchanged
380366 }
381367
368+ pub fn call(&mut self, mem: &mut Memory ) {
369+ let low = mem.read(self.pc) as u16; self.inc_pc();
370+ let high = mem.read(self.pc) as u16; self.inc_pc();
371+ let addr = (high << 8) | low;
372+
373+ let return_addr = self.pc;
374+
375+ self.push16(mem, return_addr);
376+ self.pc = addr;
377+
378+ }
379+
380+ pub fn ret(&mut self, mem: &mut Memory) {
381+ let addr = self.pop16(mem);
382+ self.pc = addr;
383+ }
384+
385+
386+ pub fn syscall(&mut self, mem: &Memory) {
387+ let num = mem.read(self.pc);
388+ self.pc = self.pc.wrapping_add(1);
389+ match num {
390+ 0 => {
391+ // exit
392+ self.halted = true;
393+ }
394+ 1 => {
395+ // print A as number
396+ println!("{}", self.a);
397+ }
398+ 2 => {
399+ // print A as ASCII char
400+ print!("{}", self.a as char);
401+ }
402+ _ => panic!("Unknown syscall {}", num),
403+ }
404+ }
405+
382406 fn get_reg(&self, r: u8) -> u8 {
383407 match r {
384408 0 => self.a,
M src/instructions.rs View
@@ -16,6 +16,7 @@ pub enum Instruction {
1616 DIV = 0x0D,
1717 CALL = 0x0E,
1818 RET = 0x0F,
19+ SYS = 0x10,
1920 HLT = 0xFF,
2021 }
2122
@@ -33,6 +34,7 @@ impl Instruction {
3334 0x0D => "DIV",
3435 0x0E => "CALL",
3536 0x0F => "RET",
37+ 0x10 => "SYS",
3638 0xFF => "HLT",
3739
3840 _ => "???",