From 12a519cfd7ee2cc407632886226b1ed9845b782b Mon Sep 17 00:00:00 2001 From: tali Date: Thu, 21 Dec 2023 14:00:57 -0500 Subject: [PATCH] completely redo bytecode format and decoder --- bin/bctest.ml | 156 +++++++++++----------- native/src/decode.rs | 295 +++++++++++++++++++++--------------------- native/src/lib.rs | 3 +- native/src/main.rs | 11 +- native/src/opcodes.rs | 125 +++++++++--------- 5 files changed, 293 insertions(+), 297 deletions(-) diff --git a/bin/bctest.ml b/bin/bctest.ml index fe8db5f..78c4f51 100644 --- a/bin/bctest.ml +++ b/bin/bctest.ml @@ -12,94 +12,98 @@ module Bc = struct output_string t.out (Buffer.contents t.buf); Buffer.clear t.buf - let write_16 t x = - assert (Int64.to_int x land 3 = 1); - Buffer.add_int16_le t.buf (Int64.to_int x) + let wr_u8 t xs = + List.iter (Buffer.add_uint8 t.buf) xs - let write_32 t x = - assert (Int64.to_int x land 3 = 2); - Buffer.add_int32_le t.buf (Int64.to_int32 x) + let wr_u16 t xs = + List.iter (Buffer.add_uint16_le t.buf) xs - let write_48 _t x = - assert (x land 3 = 3); - failwith "..." - - let ( << ) = Int64.shift_left - let ( |+ ) = Int64.logor - let _0 = Int64.zero - let _1 = Int64.one - - let rep_uint i = - assert (0 <= i && i < 0x400); - Int64.of_int i - - let rep_sint i = - assert (-0x200 <= i && i < 0x200); - Int64.of_int (i land 0x3ff) - - let rep_s24 i = - assert (-0x800000 <= i && i < 0x800000); - Int64.of_int (i land 0xffffff) + let wr_i32 t xs = + List.iter (Buffer.add_int32_le t.buf) + (List.map Int32.of_int xs) type r = [`R of int] type v = [r | `K of int] - type l = [`SubI of r * int | `SubR of r * r] + type i = [r | `O of int] + type l = [`L of r * i] - let rep_v : [< v] -> int64 = function - | `R i -> (rep_uint i) |+ (_0 << 10) - | `K i -> (rep_uint i) |+ (_1 << 10) + let reg v = + match v with + | `R i -> assert (0 <= i && i <= 0xff); i - let rep_r : [< r] -> int64 = - rep_v + let cst i = + assert (0 <= i && i <= 0xff); i - let rep_l : l -> int64 = function - | `SubI (a, i) -> (rep_r a) |+ (rep_sint i << 10) |+ (_0 << 20) - | `SubR (a, i) -> (rep_r a) |+ (rep_r i << 10) |+ (_1 << 20) + let arg v b0 = + match v with + | #r as v -> b0, reg v + | `K i -> (b0 lor 0x80), cst i - let write_v i t a = - assert (i >= 0 && i <= 32 && (i land 7 = 5)); - write_16 t (Int64.of_int i |+ (rep_v a << 5)) + let ofs v = + assert ((-0x80) <= v && v <= 0x7f); + v land 0xff - let write_rv i t a b = - assert (i >= 0 && i <= 255 && (i land 7 = 2)); - write_32 t (Int64.of_int i |+ (rep_r a << 8) |+ (rep_v b << 18)) + let loc v b0 = + match v with + | `L (r, (#r as i)) -> b0, reg r lor (reg i lsl 8) + | `L (r, `O i) -> (b0 lor 0x40), reg r lor (ofs i lsl 8) - let write_o i t o = - write_32 t (Int64.of_int i |+ (rep_s24 o << 8)) + let wr_ins_v b0 t (a : v) = + let b0, b1 = arg a b0 in + wr_u8 t [b0; b1] - let write_opr i t a b = + let wr_ins_rv b0 b1 t (a : r) (b : v) = + let b2 = reg a in + let b0, b3 = arg b b0 in + wr_u8 t [b0; b1; b2; b3] + + let wr_ins_rl b0 t (a : r) (b : l) = + let b1 = reg a in + let b0, s2 = loc b b0 in + wr_u8 t [b0; b1]; wr_u16 t [s2] + + let wr_ins_lv b0 t (b : l) (a : v) = + let b0, b1 = arg a b0 in + let b0, s2 = loc b b0 in + wr_u8 t [b0; b1]; wr_u16 t [s2] + + let wr_op o t a b = + assert (o >= 0x0 && o <= 0xf); + wr_ins_rv 0x07 o t a b + + let wr_cb c t a b = + assert (c >= 0xa && c <= 0xf); + wr_ins_rv 0x17 c t a b + + let mov t a b = match a, b with - | (#r as a), (#v as b) -> write_rv i t a b - | (#r as a), (#l as b) -> let _ = (a,b) in failwith "..." + | (#r as a), (#v as b) -> wr_ins_rv 0x01 0x00 t a b + | (#r as a), (#l as b) -> wr_ins_rl 0x03 t a b + | (#l as a), (#v as b) -> wr_ins_lv 0x05 t a b + | #l, #l -> failwith "'mov L, L' mode unsupported" - let write_cbr i t a b = - write_rv (i lor 8) t a b + let jmp t d = + let b0 = 0xff in + let w0 = b0 lor (d lsl 8) in + wr_i32 t [w0] - let ret = write_v 0x05 - let btr = write_v 0x0d - let jmp = write_o 0x06 - let mov = write_opr 0x02 - let con = write_opr 0x12 - let add = write_opr 0x22 - let sub = write_opr 0x32 - let mul = write_opr 0x42 - let div = write_opr 0x52 - let mod_= write_opr 0x62 - let neg_= write_opr 0x72 - let not_= write_opr 0x82 - (* let ? = write_opr 0x92 *) - let ceq = write_opr 0xa2 - let beq = write_cbr 0xa2 - let cne = write_opr 0xb2 - let bne = write_cbr 0xb2 - let clt = write_opr 0xc2 - let blt = write_cbr 0xc2 - let cge = write_opr 0xd2 - let bge = write_cbr 0xd2 - let cgt = write_opr 0xe2 - let bgt = write_cbr 0xe2 - let cle = write_opr 0xf2 - let ble = write_cbr 0xf2 + let ret = wr_ins_v 0x00 + let btr = wr_ins_v 0x04 + let bfl = wr_ins_v 0x14 + let con = wr_op 0x0 + let not_= wr_op 0x1 + let neg = wr_op 0x2 + let add = wr_op 0x3 + let sub = wr_op 0x4 + let mul = wr_op 0x5 + let div = wr_op 0x6 + let mod_= wr_op 0x7 + let ceq = wr_op 0xa let beq = wr_cb 0xa + let cne = wr_op 0xb let bne = wr_cb 0xb + let clt = wr_op 0xc let blt = wr_cb 0xc + let cge = wr_op 0xd let bge = wr_cb 0xd + let cgt = wr_op 0xe let bgt = wr_cb 0xe + let cle = wr_op 0xf let ble = wr_cb 0xf end let bc = Bc.make stdout @@ -111,10 +115,10 @@ let () = Bc.bgt bc (`R 0) (`R 1); (* 4 *) Bc.jmp bc (+9 (* L3 *)); (* 6 *) Bc.jmp bc (+3 (* L2 *)); (* 8 *) - Bc.ret bc (`R 0); (* L1: 10 *) - Bc.mov bc (`R 0) (`K 2); (* L2: 11 *) + Bc.ret bc (`R 1); (* L1: 10 *) + Bc.add bc (`R 1) (`K 2); (* L2: 11 *) Bc.jmp bc (-3 (* L1 *)); (* 13 *) - Bc.mov bc (`R 0) (`K 3); (* L3: 15 *) + Bc.mul bc (`R 1) (`R 1); (* L3: 15 *) Bc.jmp bc (-7 (* L1 *)); (* 17 *) end diff --git a/native/src/decode.rs b/native/src/decode.rs index b95e021..250a12d 100644 --- a/native/src/decode.rs +++ b/native/src/decode.rs @@ -4,179 +4,178 @@ use super::opcodes::*; #[derive(Debug, Error)] pub enum DecodeError { - #[error("data truncated (len < {0})")] - DataTrunc(usize), - #[error("invalid len: {0}")] - Len(u8), + #[error("not enough data (len < {0})")] + Trunc(usize), #[error("invalid instruction: {0:x}")] Ins(u8), - #[error("invalid operator: {0:x}")] + #[error("invalid operation: {0:x}")] Opr(u8), - #[error("invalid operand: {0:x}")] - Arg(u32), -} - -fn read_u8(bs: &[u8], i: usize) -> Result { - if bs.len() < i + 1 { - return Err(DecodeError::DataTrunc(i + 1)); - } - Ok(bs[i]) -} - -fn read_u16(bs: &[u8], i: usize) -> Result { - if bs.len() < i + 2 { - return Err(DecodeError::DataTrunc(i + 2)); - } - Ok(u16::from_le_bytes(bs[i..i + 2].try_into().unwrap()) as u32) -} - -fn read_u32(bs: &[u8], i: usize) -> Result { - if bs.len() < i + 4 { - return Err(DecodeError::DataTrunc(i + 4)); - } - Ok(u32::from_le_bytes(bs[i..i + 4].try_into().unwrap())) -} - -fn decode_opr(b: u8) -> Result { - match b { - 0x02 => Ok(Opr::MOV), - 0x12 => Ok(Opr::CON), - 0x22 => Ok(Opr::ADD), - 0x32 => Ok(Opr::SUB), - 0x42 => Ok(Opr::MUL), - 0x52 => Ok(Opr::DIV), - 0x62 => Ok(Opr::MOD), - 0x72 => Ok(Opr::NEG), - 0x82 => Ok(Opr::NOT), - 0xa2 => Ok(Opr::Cmp(Cmp::EQ)), - 0xb2 => Ok(Opr::Cmp(Cmp::NE)), - 0xc2 => Ok(Opr::Cmp(Cmp::LT)), - 0xd2 => Ok(Opr::Cmp(Cmp::GE)), - 0xe2 => Ok(Opr::Cmp(Cmp::GT)), - 0xf2 => Ok(Opr::Cmp(Cmp::LE)), - _ => Err(DecodeError::Opr(b)), - } -} - -fn decode_reg(w: u32, k: u32) -> Result { - Ok(Reg(((w >> k) & 0x3ff) as u16)) -} - -fn decode_const(w: u32, k: u32) -> Result { - if w & (0x400 << k) == 0 { - return Err(DecodeError::Arg(w)); - } - Ok(ConstIdx(((w >> k) & 0x3ff) as u16)) -} - -fn decode_argv(w: u32, k: u32) -> Result { - if w & (0x400 << k) != 0 { - decode_const(w, k).map(ArgV::K) - } else { - decode_reg(w, k).map(ArgV::R) - } } +/// Decode a single instruction from the bytecode, returning the instruction and its size +/// (in bytes). pub fn decode_one(bs: &[u8]) -> Result<(Ins, usize), DecodeError> { - let b0 = read_u8(bs, 0)?; + let byte0 = byte(bs, 0)?; - let ins; - match b0 & 0b111 { - 0b010 => { - let i; - if b0 & 0b1000 != 0 { - match decode_opr(b0 & !0b1000)? { - Opr::Cmp(cmp) => { - i = InsRV::Br(cmp); - } - _ => return Err(DecodeError::Opr(b0)), - } - } else { - i = InsRV::Op(decode_opr(b0)?); - }; - - let w = read_u32(bs, 0)?; - let a = decode_reg(w, 8)?; - let b = decode_argv(w, 18)?; - ins = Ins::RV(i, a, b); + let len = (byte0 & 1) as usize * 2 + 2; + let ins = match byte0 & 0x3f { + 0x00 => { + let a = arg(byte(bs, 1)?, byte0); + Ins::RET(a) } - - 0b011 => { - #[allow(unreachable_code, unused_variables)] - match b0 { - 0x3 => { - let (i, a, b) = todo!("LV"); - ins = Ins::LV(i, a, b); - } - - _ => { - let (i, a, b) = todo!("RL"); - ins = Ins::RL(i, a, b); - } - }; + 0x04 => { + let a = arg(byte(bs, 1)?, byte0); + Ins::Br(InsBr::BTR(a)) } - - 0b101 => { - let i = match b0 & 0b11111 { - 0x05 => InsV::RET, - 0x0d => InsV::BTR, - _ => return Err(DecodeError::Ins(b0)), - }; - - let w = read_u16(bs, 0)?; - let a = decode_argv(w as u32, 8)?; - ins = Ins::V(i, a); + 0x14 => { + let a = arg(byte(bs, 1)?, byte0); + Ins::Br(InsBr::BFL(a)) } - - 0b110 => { - let i = match b0 { - 0x06 => InsO::JMP, - _ => return Err(DecodeError::Ins(b0)), - }; - - let w = read_u32(bs, 0)?; - let o = (w as i32) >> 8; - ins = Ins::O(i, o); + 0x01 => { + let a = Reg(byte(bs, 2)?); + let b = arg(byte(bs, 3)?, byte0); + Ins::MOV(InsMov::RV(a, b)) } - - _ => return Err(DecodeError::Ins(b0)), - }; - - let len = match b0 & 0b11 { - 0 => return Err(DecodeError::Len(0)), - x => (x * 2) as usize, + 0x03 => { + let a = Reg(byte(bs, 1)?); + let b = loc(byte(bs, 2)?, byte(bs, 3)?, byte0); + Ins::MOV(InsMov::RL(a, b)) + } + 0x05 => { + let a = arg(byte(bs, 1)?, byte0); + let b = loc(byte(bs, 2)?, byte(bs, 3)?, byte0); + Ins::MOV(InsMov::LV(b, a)) + } + 0x07 => { + let opr = opr(byte(bs, 1)?)?; + let a = Reg(byte(bs, 2)?); + let b = arg(byte(bs, 3)?, byte0); + Ins::MOV(InsMov::Op(opr, a, b)) + } + 0x17 => { + let cnd = cnd(byte(bs, 1)?)?; + let a = Reg(byte(bs, 2)?); + let b = arg(byte(bs, 3)?, byte0); + Ins::Br(InsBr::BCnd(cnd, a, b)) + } + 0x89 => { + let a = Reg(byte(bs, 1)?); + let b = Reg(byte(bs, 2)?); + let c = Cst(byte(bs, 3)?); + Ins::LOC(InsLoc(a, b, c)) + } + 0x3f => { + let d = i32_le(bs)? >> 8; + Ins::JMP(InsJmp(d)) + } + _ if (byte0 & 0xf == 0xd) => { + let a = Reg(byte(bs, 1)?); + let b = loc(byte(bs, 2)?, byte(bs, 3)?, 0x0d); + let n = byte0 >> 4; + Ins::CAL(InsCal(a, b, n)) + } + _ => return Err(DecodeError::Ins(byte0)), }; Ok((ins, len)) } -/// Iterator adapter for [`decode_one`]. -#[derive(Clone)] -pub struct Decode<'a>(&'a [u8]); - -/// Decode all instructions from bytecode data. -pub fn decode(bs: &[u8]) -> Decode<'_> { - Decode(bs) +#[inline] +fn byte(bs: &[u8], i: usize) -> Result { + bs.get(i).copied().ok_or(DecodeError::Trunc(i + 1)) } -impl Decode<'_> { - pub fn inner(&self) -> &[u8] { - self.0 +#[inline] +fn i32_le(bs: &[u8]) -> Result { + let slice = bs.get(..4).ok_or(DecodeError::Trunc(4))?; + Ok(i32::from_le_bytes(slice.try_into().unwrap())) +} + +fn arg(b: u8, byte0: u8) -> Arg { + if byte0 & 0x80 == 0 { + Arg::R(Reg(b)) + } else { + Arg::K(Cst(b)) } } -impl Iterator for Decode<'_> { +fn ofs(b: u8) -> i8 { + b as i8 +} + +fn loc(b: u8, c: u8, byte0: u8) -> Loc { + if byte0 & 0x40 == 0 { + Loc::R(Reg(b), Reg(c)) + } else { + Loc::O(Reg(b), ofs(c)) + } +} + +fn opr(b: u8) -> Result { + match b { + 0x0 => Ok(Opr::CON), + 0x1 => Ok(Opr::NOT), + 0x2 => Ok(Opr::NEG), + 0x3 => Ok(Opr::ADD), + 0x4 => Ok(Opr::SUB), + 0x5 => Ok(Opr::MUL), + 0x6 => Ok(Opr::DIV), + 0x7 => Ok(Opr::MOD), + // 0x8 + // 0x9 + _ => cnd(b).map(Opr::Cmp), + } +} + +fn cnd(b: u8) -> Result { + match b { + 0xa => Ok(Cnd::EQ), + 0xb => Ok(Cnd::NE), + 0xc => Ok(Cnd::LT), + 0xd => Ok(Cnd::GE), + 0xe => Ok(Cnd::GT), + 0xf => Ok(Cnd::LE), + _ => Err(DecodeError::Opr(b)), + } +} + +/// Iterator adapter for [`decode_one`]. +#[derive(Clone)] +pub struct Decode>(T, usize); + +/// Decode all instructions from bytecode data. +pub fn decode>(bs: T) -> Decode { + Decode(bs, 0) +} + +impl> Decode { + pub fn into_inner(self) -> T { + self.0 + } + + pub fn position(&self) -> usize { + self.1 + } +} + +impl> Iterator for Decode { type Item = Result; fn next(&mut self) -> Option { - let bs = self.0; - if bs.is_empty() { + let bs = self.0.as_ref(); + let pos = &mut self.1; + if *pos >= bs.len() { return None; } - - Some(decode_one(bs).map(|(ins, len)| { - self.0 = &bs[len..]; - ins - })) + decode_one(&bs[*pos..]) + .map(|(ins, len)| { + *pos += len; + Some(ins) + }) + .map_err(|err| match err { + DecodeError::Trunc(i) => DecodeError::Trunc(i + *pos), + _ => err, + }) + .transpose() } } diff --git a/native/src/lib.rs b/native/src/lib.rs index d343d02..8c6f081 100644 --- a/native/src/lib.rs +++ b/native/src/lib.rs @@ -1,5 +1,4 @@ -pub mod decode; pub mod opcodes; +pub mod decode; pub use decode::{decode, DecodeError}; -pub use opcodes::Ins; diff --git a/native/src/main.rs b/native/src/main.rs index 9a31b18..29e5d38 100644 --- a/native/src/main.rs +++ b/native/src/main.rs @@ -7,16 +7,17 @@ use spicei::*; enum Error { #[error(transparent)] Io(#[from] std::io::Error), - #[error(transparent)] - Decode(#[from] DecodeError), + #[error("decode error at position {1}")] + Decode(#[source] DecodeError, usize), } fn entry() -> Result<(), Error> { let mut bytes = vec![]; BufReader::new(std::io::stdin()).read_to_end(&mut bytes)?; - for ins in decode(&bytes) { - let ins = ins?; + let mut decode = decode(&bytes); + while let Some(ins) = decode.next() { + let ins = ins.map_err(|err| Error::Decode(err, decode.position()))?; println!("{ins}"); } @@ -31,7 +32,7 @@ fn main() { let mut src = err.source(); while let Some(err) = src { - println!("- {err}"); + println!("from: {err}"); src = err.source(); } } diff --git a/native/src/opcodes.rs b/native/src/opcodes.rs index 1851c80..d27ef68 100644 --- a/native/src/opcodes.rs +++ b/native/src/opcodes.rs @@ -2,7 +2,7 @@ use std::fmt; #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] #[repr(transparent)] -pub struct Reg(pub u16); +pub struct Reg(pub u8); impl fmt::Display for Reg { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -12,108 +12,102 @@ impl fmt::Display for Reg { #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] #[repr(transparent)] -pub struct ConstIdx(pub u16); +pub struct Cst(pub u8); -impl fmt::Display for ConstIdx { +impl fmt::Display for Cst { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "K{}", self.0) } } -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum ArgV { +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] +pub enum Arg { R(Reg), - K(ConstIdx), + K(Cst), } -impl fmt::Display for ArgV { +impl fmt::Display for Arg { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { + match *self { Self::R(r) => r.fmt(f), Self::K(k) => k.fmt(f), } } } -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum ArgL { - SubI(Reg, i16), - SubR(Reg, Reg), +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] +pub enum Loc { + R(Reg, Reg), + O(Reg, i8), } -impl fmt::Display for ArgL { +impl fmt::Display for Loc { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::SubI(r, l) => write!(f, "{r}[{l}]"), - Self::SubR(r, l) => write!(f, "{r}[{l}]"), + match *self { + Self::R(r, l) => write!(f, "{r}[{l}]"), + Self::O(r, l) => write!(f, "{r}[{l}]"), } } } -#[derive(Copy, Clone, Eq, PartialEq, Debug)] +#[derive(Clone, Eq, PartialEq, Debug)] pub enum Ins { - V(InsV, ArgV), - RV(InsRV, Reg, ArgV), - O(InsO, i32), - RL(InsRL, Reg, ArgL), - LV(InsLV, ArgL, ArgV), - RRK(InsRRK, Reg, Reg, ConstIdx), + MOV(InsMov), + LOC(InsLoc), + CAL(InsCal), + JMP(InsJmp), + Br(InsBr), + RET(Arg), } impl fmt::Display for Ins { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::O(InsO::JMP, o) => write!(f, "jmp {o:+}"), - Self::V(InsV::RET, v) => write!(f, "ret {v}"), - Self::V(InsV::BTR, v) => write!(f, "btr {v}"), - Self::RV(InsRV::Op(opr), r, v) => write!(f, "{opr} {r}, {v}"), - Self::RV(InsRV::Br(cmp), r, v) => write!(f, "b{cmp} {r}, {v}"), - Self::RL(InsRL::Get(opr), r, l) => write!(f, "{opr} {r}, {l}"), - Self::RL(InsRL::CAL(n), r, l) => write!(f, "cal {r}, {l}({r},...{n})"), - Self::RL(InsRL::RETCAL(n), r, l) => write!(f, "ret cal {l}({r},...{n})"), - Self::LV(InsLV::Set(opr), l, v) => write!(f, "{opr} {l}, {v}"), - Self::RRK(InsRRK::LOC, r, v, k) => write!(f, "loc {r}, {v}, {k}"), + use Ins::*; + use InsBr::*; + use InsMov::*; + + match *self { + MOV(Op(opr, a, b)) => write!(f, "{opr} {a}, {b}"), + MOV(RV(a, b)) => write!(f, "mov {a}, {b}"), + MOV(RL(a, b)) => write!(f, "mov {a}, {b}"), + MOV(LV(a, b)) => write!(f, "mov {a}, {b}"), + LOC(InsLoc(a, b, k)) => write!(f, "loc {a}, {b}, {}", Arg::K(k)), + CAL(InsCal(a, b, n)) => write!(f, "cal {a}, {b}({a},...{n})"), + JMP(InsJmp(d)) => write!(f, "jmp {d:+}"), + RET(v) => write!(f, "ret {v}"), + Br(BTR(v)) => write!(f, "btr {v}"), + Br(BFL(v)) => write!(f, "btr {v}"), + Br(BCnd(cnd, a, b)) => write!(f, "b{cnd} {a}, {b}"), } } } -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum InsV { - RET, - BTR, +#[derive(Clone, Eq, PartialEq, Debug)] +pub enum InsMov { + Op(Opr, Reg, Arg), + RV(Reg, Arg), + RL(Reg, Loc), + LV(Loc, Arg), } -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum InsRV { - Op(Opr), - Br(Cmp), +#[derive(Clone, Eq, PartialEq, Debug)] +pub enum InsBr { + BTR(Arg), + BFL(Arg), + BCnd(Cnd, Reg, Arg), } -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum InsO { - JMP, -} +#[derive(Clone, Eq, PartialEq, Debug)] +pub struct InsLoc(pub Reg, pub Reg, pub Cst); -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum InsRL { - Get(Opr), - CAL(u16), - RETCAL(u16), -} +#[derive(Clone, Eq, PartialEq, Debug)] +pub struct InsCal(pub Reg, pub Loc, pub u8); -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum InsLV { - Set(Opr), -} - -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum InsRRK { - LOC, -} +#[derive(Clone, Eq, PartialEq, Debug)] +pub struct InsJmp(pub i32); #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] pub enum Opr { - MOV, CON, NOT, NEG, @@ -122,13 +116,12 @@ pub enum Opr { MUL, DIV, MOD, - Cmp(Cmp), + Cmp(Cnd), } impl fmt::Display for Opr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::MOV => write!(f, "mov"), Self::CON => write!(f, "con"), Self::NOT => write!(f, "not"), Self::NEG => write!(f, "neg"), @@ -143,7 +136,7 @@ impl fmt::Display for Opr { } #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] -pub enum Cmp { +pub enum Cnd { EQ, NE, LT, @@ -152,7 +145,7 @@ pub enum Cmp { GE, } -impl fmt::Display for Cmp { +impl fmt::Display for Cnd { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::EQ => write!(f, "eq"),