added conditional jumps

This commit is contained in:
Erin 2023-06-09 01:55:09 +02:00 committed by ondra05
parent 417047806b
commit 48353db26f
5 changed files with 55 additions and 7 deletions

View file

@ -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<u8>) -> 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() {

View file

@ -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)]

View file

@ -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);
}

View file

@ -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;

View file

@ -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<core::cmp::Ordering> {
self.int().partial_cmp(&other.int())
}
}
impl Ord for Value {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.int().cmp(&other.int())
}
}