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",
|
"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() {
|
||||||
|
|
|
@ -55,9 +55,14 @@ constmod!(pub opcode(u8) {
|
||||||
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)]
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue