aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md5
-rw-r--r--examples/cmp.asm4
-rw-r--r--examples/mov.asm5
-rw-r--r--examples/subtraction.asm4
-rw-r--r--src/assembler.rs50
-rw-r--r--src/cpu.rs72
-rw-r--r--src/instructions.rs8
7 files changed, 125 insertions, 23 deletions
diff --git a/README.md b/README.md
index 2290da0..18a02e8 100644
--- a/README.md
+++ b/README.md
@@ -10,12 +10,13 @@
| Instruction | Syntax |
| ----------- | ------------ |
-| MOV | mov reg, imm |
+| MOV | mov reg, imm OR mov reg, reg |
| ADD | add r1, r2 |
| SUB | sub r1, r2 |
| JMP | jmp addr |
| JZ | jz addr |
| JNZ | jnz addr |
+| CMP | cmp reg, imm OR cmp reg, reg |
| HLT (Halt) | hlt |
@@ -46,7 +47,7 @@ cargo run -- --f <examples/filename.asc>
- [x] Lexer/Tokenizer
- [x] Add label support (supporting JMP/JZ/JNZ)
- [ ] Add instructions
- - [ ] CMP
+ - [x] CMP
- [ ] CALL
- [ ] RET
- [ ] Error handling
diff --git a/examples/cmp.asm b/examples/cmp.asm
new file mode 100644
index 0000000..f35ccf4
--- /dev/null
+++ b/examples/cmp.asm
@@ -0,0 +1,4 @@
+mov a, 10
+mov b, 10
+cmp a, b
+hlt
diff --git a/examples/mov.asm b/examples/mov.asm
new file mode 100644
index 0000000..4aa3c04
--- /dev/null
+++ b/examples/mov.asm
@@ -0,0 +1,5 @@
+mov a, 10
+mov b, a
+cmp a, b
+cmp a, 10
+hlt
diff --git a/examples/subtraction.asm b/examples/subtraction.asm
deleted file mode 100644
index cfc9db5..0000000
--- a/examples/subtraction.asm
+++ /dev/null
@@ -1,4 +0,0 @@
-mov a, 15
-mov b, 15
-sub a, b
-hlt
diff --git a/src/assembler.rs b/src/assembler.rs
index 3eeec64..c4751c1 100644
--- a/src/assembler.rs
+++ b/src/assembler.rs
@@ -18,16 +18,21 @@ fn parse_reg(s: &str) -> u8 {
}
}
-fn instr_size(tokens: &[String]) -> u16 {
+fn is_reg(s: &str) -> bool {
+ match s {
+ "a" | "b" | "c" | "d" => true,
+ _ => false,
+ }
+}
+
+fn instr_size(tokens: &[String]) -> u16 {
match tokens[0].as_str() {
- "mov" | "add" | "sub" | "jmp" | "jz" | "jnz" => 3,
+ "mov" | "add" | "sub" | "jmp" | "jz" | "jnz" | "cmp" => 3,
"hlt" => 1,
- _ => panic!("Unknown instruction {}", tokens[0])
-
+ _ => panic!("Unknown instruction {}", tokens[0]),
}
}
-
fn first_pass(source: &str) -> HashMap<String, u16> {
let mut symbols = HashMap::new();
let mut addr: u16 = 0;
@@ -72,11 +77,17 @@ pub fn assembler(source: &str) -> Vec<u8> {
"mov" => {
// mov reg, imm
let reg = parse_reg(&tokens[1]);
- let imm: u8 = tokens[2].parse().unwrap();
-
- bytes.push(Instruction::MOV as u8);
- bytes.push(reg);
- bytes.push(imm);
+ if is_reg(&tokens[2]) {
+ let r2 = parse_reg(&tokens[2]);
+ bytes.push(Instruction::MOV_RR as u8);
+ bytes.push(reg);
+ bytes.push(r2);
+ } else {
+ let imm: u8 = tokens[2].parse().unwrap();
+ bytes.push(Instruction::MOV_RI as u8);
+ bytes.push(reg);
+ bytes.push(imm);
+ }
}
"add" => {
@@ -91,8 +102,8 @@ pub fn assembler(source: &str) -> Vec<u8> {
"sub" => {
// sub a, b
- let r1 = parse_reg(&tokens[1]);
let r2 = parse_reg(&tokens[2]);
+ let r1 = parse_reg(&tokens[1]);
bytes.push(Instruction::SUB as u8);
bytes.push(r1);
@@ -104,7 +115,7 @@ pub fn assembler(source: &str) -> Vec<u8> {
"jmp" => Instruction::JMP,
"jz" => Instruction::JZ,
"jnz" => Instruction::JNZ,
- _ => unreachable!()
+ _ => unreachable!(),
};
let label = &tokens[1];
@@ -115,6 +126,21 @@ pub fn assembler(source: &str) -> Vec<u8> {
bytes.push((addr >> 8) as u8); // high
}
+ "cmp" => {
+ let r1 = parse_reg(&tokens[1]);
+ if tokens[2].chars().all(|c| c.is_ascii_digit()) {
+ let imm: u8 = tokens[2].parse().unwrap();
+ bytes.push(Instruction::CMP_RI as u8);
+ bytes.push(r1);
+ bytes.push(imm);
+ } else {
+ let r2 = parse_reg(&tokens[2]);
+ bytes.push(Instruction::CMP_RR as u8);
+ bytes.push(r1);
+ bytes.push(r2);
+ }
+ }
+
"hlt" => {
bytes.push(Instruction::HLT as u8);
}
diff --git a/src/cpu.rs b/src/cpu.rs
index df8b3a2..116d20d 100644
--- a/src/cpu.rs
+++ b/src/cpu.rs
@@ -19,7 +19,6 @@ pub struct CPU {
}
impl CPU {
-
pub fn debug_instr(&self, mem: &Memory) {
let opcode = mem.read(self.pc);
@@ -41,12 +40,15 @@ impl CPU {
self.inc_pc();
match opcode {
- x if x == Instruction::MOV as u8 => self.mov(mem),
+ x if x == Instruction::MOV_RI as u8 => self.mov_ri(mem),
+ x if x == Instruction::MOV_RR as u8 => self.mov_rr(mem),
x if x == Instruction::ADD as u8 => self.add(mem),
x if x == Instruction::SUB as u8 => self.sub(mem),
x if x == Instruction::JMP as u8 => self.jmp(mem),
x if x == Instruction::JZ as u8 => self.jz(mem),
x if x == Instruction::JNZ as u8 => self.jnz(mem),
+ x if x == Instruction::CMP_RI as u8 => self.cmp_ri(mem),
+ x if x == Instruction::CMP_RR as u8 => self.cmp_rr(mem),
x if x == Instruction::HLT as u8 => self.halt(),
_ => panic!("Unknown opcode {:02X}", opcode),
}
@@ -60,7 +62,7 @@ impl CPU {
self.halted = true;
}
- pub fn mov(&mut self, mem: &Memory) {
+ pub fn mov_ri(&mut self, mem: &Memory) {
let reg = mem.read(self.pc);
self.inc_pc();
let val = mem.read(self.pc);
@@ -77,6 +79,19 @@ impl CPU {
self.zero = val == 0;
}
+ pub fn mov_rr(&mut self, mem: &Memory) {
+ let dest = mem.read(self.pc);
+ self.inc_pc();
+ let src= mem.read(self.pc);
+ self.inc_pc();
+
+ let val = self.get_reg(src);
+ self.set_reg(dest, val);
+
+ self.zero = val == 0;
+ }
+
+
pub fn add(&mut self, mem: &Memory) {
let dest = mem.read(self.pc);
self.pc += 1;
@@ -197,4 +212,55 @@ impl CPU {
self.pc = addrs;
}
}
+
+ pub fn cmp_rr(&mut self, mem: &Memory) {
+ let r1 = mem.read(self.pc);
+ self.inc_pc();
+ let r2 = mem.read(self.pc);
+ self.inc_pc();
+
+ let v1 = self.get_reg(r1);
+ let v2 = self.get_reg(r2);
+
+ let (result, borrow) = v1.overflowing_sub(v2);
+
+ self.zero = result == 0;
+ self.carry = borrow;
+ }
+
+ pub fn cmp_ri(&mut self, mem: &Memory) {
+ let r1 = mem.read(self.pc);
+ self.inc_pc();
+ let r2 = mem.read(self.pc);
+ self.inc_pc();
+
+ let v1 = self.get_reg(r1);
+
+ let (result, borrow) = v1.overflowing_sub(r2);
+
+ self.zero = result == 0;
+ self.carry = borrow;
+ }
+
+
+ fn get_reg(&self, r: u8) -> u8 {
+ match r {
+ 0 => self.a,
+ 1 => self.b,
+ 2 => self.c,
+ 3 => self.d,
+ _ => 0,
+ }
+ }
+
+ fn set_reg(&mut self, dest: u8, val: u8) {
+ match dest {
+ 0 => self.a = val,
+ 1 => self.b = val,
+ 2 => self.c = val,
+ 3 => self.d = val,
+ _ => {},
+ }
+ }
+
}
diff --git a/src/instructions.rs b/src/instructions.rs
index ac88e94..77de7f4 100644
--- a/src/instructions.rs
+++ b/src/instructions.rs
@@ -1,23 +1,27 @@
#[repr(u8)]
pub enum Instruction {
- MOV = 0x01,
+ MOV_RI = 0x01,
+ MOV_RR = 0x08,
ADD = 0x02,
SUB = 0x03,
JMP = 0x04,
JZ = 0x05,
JNZ = 0x06,
+ CMP_RI = 0x07,
+ CMP_RR = 0x09,
HLT = 0xFF,
}
impl Instruction {
pub fn opcode_name(op: u8) -> &'static str{
match op {
- 0x01 => "MOV",
+ 0x01 | 0x08 => "MOV",
0x02 => "ADD",
0x03 => "SUB",
0x04 => "JMP",
0x05 => "JZ",
0x06 => "JNZ",
+ 0x07 | 0x09 => "CMP",
0xFF => "HLT",
_ => "???",
}