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", "nop", "add", "sub", "mul", "rem", "and", "or", "xor", "sl", "sr", "srs",
"not", "addf", "subf", "mulf", "divf", "addi", "muli", "remi", "andi", "not", "addf", "subf", "mulf", "divf", "addi", "muli", "remi", "andi",
"ori", "xori", "sli", "sri", "srsi", "addfi", "mulfi", "cp", "li", "lb", "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)] #[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(), ADD..=SRS | ADDF..=DIVF => self.rrr(),
NOT | CP => self.rr(), NOT | CP => self.rr(),
LI | JMP => self.ri(), LI | JMP => self.ri(),
ADDI..=MULFI | LB..=SO => self.rri(), ADDI..=MULFI | LB..=SO | JEQ..=JGTU => self.rri(),
_ => unreachable!(), _ => unreachable!(),
}?; }?;
match self.next() { match self.next() {

View file

@ -54,10 +54,15 @@ constmod!(pub opcode(u8) {
SQ = 36, // RRI; Store quadlet SQ = 36, // RRI; Store quadlet
SO = 37, // RRI; Store octlet SO = 37, // RRI; Store octlet
JMP = 38, // RI; Unconditional jump [#0 + imm #1] JMP = 38, // RI; Unconditional jump [#0 + imm #1]
JMPCOND = 39, // ?; Conditional jump JEQ = 39, // RRI; if #0 = #1 → jump imm #2
RET = 40, // N; Return JNE = 40, // RRI; if #0 ≠ #1 → jump imm #2
ECALL = 42, // N; Issue system call 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)] #[repr(packed)]

View file

@ -62,7 +62,7 @@ pub fn validate(mut program: &[u8]) -> Result<(), Error> {
rest rest
} }
// RRI // RRI
[ADDI..=MULFI | LB..=SO, _, _, _, _, _, _, _, _, _, _, rest @ ..] => { [ADDI..=MULFI | LB..=SO | JEQ..=JGTU, _, _, _, _, _, _, _, _, _, _, rest @ ..] => {
if let Some(n) = reg(&program[1..=2]) { if let Some(n) = reg(&program[1..=2]) {
bail!(InvalidRegister, start, program, n + 1); 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 struct Vm<'a> {
pub registers: [Value; 60], pub registers: [Value; 60],
pub memory: Memory, pub memory: Memory,
@ -158,6 +169,17 @@ impl<'a> Vm<'a> {
let ParamRI(reg, offset) = param!(self, ParamRI); let ParamRI(reg, offset) = param!(self, ParamRI);
self.pc = (self.read_reg(reg).int() + offset) as usize; 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 => { ECALL => {
param!(self, ()); param!(self, ());
return HaltReason::Ecall; return HaltReason::Ecall;

View file

@ -37,3 +37,23 @@ impl Debug for Value {
self.int().fmt(f) 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())
}
}