added conditional jumps
This commit is contained in:
parent
417047806b
commit
48353db26f
|
@ -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() {
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue