diff --git a/hbasm/src/lib.rs b/hbasm/src/lib.rs index 63dd76ff..7bd12af4 100644 --- a/hbasm/src/lib.rs +++ b/hbasm/src/lib.rs @@ -46,7 +46,8 @@ tokendef![ "nop", "add", "sub", "mul", "rem", "and", "or", "xor", "sl", "sr", "srs", "not", "addf", "subf", "mulf", "divf", "addi", "muli", "remi", "andi", "ori", "xori", "sli", "sri", "srsi", "addfi", "mulfi", "cp", "li", "lb", - "ld", "lq", "lo", "sb", "sd", "sq", "so", "jmp", "jmpcond", "ret", "ecall", + "ld", "lq", "lo", "sb", "sd", "sq", "so", "jmp", "jeq", "jne", "jlt", "jgt", + "jltu", "jgtu", "ret", "ecall", ]; #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -103,7 +104,7 @@ pub fn assembly(code: &str, buf: &mut Vec) -> Result<(), Error> { ADD..=SRS | ADDF..=DIVF => self.rrr(), NOT | CP => self.rr(), LI | JMP => self.ri(), - ADDI..=MULFI | LB..=SO => self.rri(), + ADDI..=MULFI | LB..=SO | JEQ..=JGTU => self.rri(), _ => unreachable!(), }?; match self.next() { diff --git a/hbbytecode/src/lib.rs b/hbbytecode/src/lib.rs index 06c24e6d..6e434ff2 100644 --- a/hbbytecode/src/lib.rs +++ b/hbbytecode/src/lib.rs @@ -54,10 +54,15 @@ constmod!(pub opcode(u8) { SQ = 36, // RRI; Store quadlet SO = 37, // RRI; Store octlet - JMP = 38, // RI; Unconditional jump [#0 + imm #1] - JMPCOND = 39, // ?; Conditional jump - RET = 40, // N; Return - ECALL = 42, // N; Issue system call + JMP = 38, // RI; Unconditional jump [#0 + imm #1] + JEQ = 39, // RRI; if #0 = #1 → jump imm #2 + JNE = 40, // RRI; if #0 ≠ #1 → jump imm #2 + JLT = 41, // RRI; if #0 < #1 → jump imm #2 + JGT = 52, // RRI; if #0 > #1 → jump imm #2 + JLTU = 53, // RRI; if #0 < #1 → jump imm #2 (unsigned) + JGTU = 54, // RRI; if #0 > #1 → jump imm #2 (unsigned) + RET = 55, // N; Return + ECALL = 56, // N; Issue system call }); #[repr(packed)] diff --git a/hbvm/src/validate.rs b/hbvm/src/validate.rs index 6866eb38..1907b2c6 100644 --- a/hbvm/src/validate.rs +++ b/hbvm/src/validate.rs @@ -62,7 +62,7 @@ pub fn validate(mut program: &[u8]) -> Result<(), Error> { rest } // RRI - [ADDI..=MULFI | LB..=SO, _, _, _, _, _, _, _, _, _, _, rest @ ..] => { + [ADDI..=MULFI | LB..=SO | JEQ..=JGTU, _, _, _, _, _, _, _, _, _, _, rest @ ..] => { if let Some(n) = reg(&program[1..=2]) { bail!(InvalidRegister, start, program, n + 1); } diff --git a/hbvm/src/vm/mod.rs b/hbvm/src/vm/mod.rs index 1ad00077..bf47abb0 100644 --- a/hbvm/src/vm/mod.rs +++ b/hbvm/src/vm/mod.rs @@ -75,6 +75,17 @@ macro_rules! store { }}; } +macro_rules! cond_jump { + ($self:expr, $ty:ident, $expected:ident) => {{ + let ParamRRI(a0, a1, jt) = param!($self, ParamRRI); + if core::cmp::Ord::cmp(&$self.read_reg(a0), &$self.read_reg(a1)) + == core::cmp::Ordering::$expected + { + $self.pc = jt as usize; + } + }}; +} + pub struct Vm<'a> { pub registers: [Value; 60], pub memory: Memory, @@ -158,6 +169,17 @@ impl<'a> Vm<'a> { let ParamRI(reg, offset) = param!(self, ParamRI); self.pc = (self.read_reg(reg).int() + offset) as usize; } + JEQ => cond_jump!(self, int, Equal), + JNE => { + let ParamRRI(a0, a1, jt) = param!(self, ParamRRI); + if self.read_reg(a0) != self.read_reg(a1) { + self.pc = jt as usize; + } + } + JLT => cond_jump!(self, int, Less), + JGT => cond_jump!(self, int, Greater), + JLTU => cond_jump!(self, sint, Less), + JGTU => cond_jump!(self, sint, Greater), ECALL => { param!(self, ()); return HaltReason::Ecall; diff --git a/hbvm/src/vm/value.rs b/hbvm/src/vm/value.rs index 870439a4..e0cf69cd 100644 --- a/hbvm/src/vm/value.rs +++ b/hbvm/src/vm/value.rs @@ -37,3 +37,23 @@ impl Debug for Value { self.int().fmt(f) } } + +impl PartialEq for Value { + fn eq(&self, other: &Self) -> bool { + self.int().eq(&other.int()) + } +} + +impl Eq for Value {} + +impl PartialOrd for Value { + fn partial_cmp(&self, other: &Self) -> Option { + self.int().partial_cmp(&other.int()) + } +} + +impl Ord for Value { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.int().cmp(&other.int()) + } +}