completely redo bytecode format and decoder

This commit is contained in:
tali 2023-12-21 14:00:57 -05:00
parent 18cc66697e
commit 12a519cfd7
5 changed files with 293 additions and 297 deletions

View File

@ -12,94 +12,98 @@ module Bc = struct
output_string t.out (Buffer.contents t.buf); output_string t.out (Buffer.contents t.buf);
Buffer.clear t.buf Buffer.clear t.buf
let write_16 t x = let wr_u8 t xs =
assert (Int64.to_int x land 3 = 1); List.iter (Buffer.add_uint8 t.buf) xs
Buffer.add_int16_le t.buf (Int64.to_int x)
let write_32 t x = let wr_u16 t xs =
assert (Int64.to_int x land 3 = 2); List.iter (Buffer.add_uint16_le t.buf) xs
Buffer.add_int32_le t.buf (Int64.to_int32 x)
let write_48 _t x = let wr_i32 t xs =
assert (x land 3 = 3); List.iter (Buffer.add_int32_le t.buf)
failwith "..." (List.map Int32.of_int xs)
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)
type r = [`R of int] type r = [`R of int]
type v = [r | `K 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 let reg v =
| `R i -> (rep_uint i) |+ (_0 << 10) match v with
| `K i -> (rep_uint i) |+ (_1 << 10) | `R i -> assert (0 <= i && i <= 0xff); i
let rep_r : [< r] -> int64 = let cst i =
rep_v assert (0 <= i && i <= 0xff); i
let rep_l : l -> int64 = function let arg v b0 =
| `SubI (a, i) -> (rep_r a) |+ (rep_sint i << 10) |+ (_0 << 20) match v with
| `SubR (a, i) -> (rep_r a) |+ (rep_r i << 10) |+ (_1 << 20) | #r as v -> b0, reg v
| `K i -> (b0 lor 0x80), cst i
let write_v i t a = let ofs v =
assert (i >= 0 && i <= 32 && (i land 7 = 5)); assert ((-0x80) <= v && v <= 0x7f);
write_16 t (Int64.of_int i |+ (rep_v a << 5)) v land 0xff
let write_rv i t a b = let loc v b0 =
assert (i >= 0 && i <= 255 && (i land 7 = 2)); match v with
write_32 t (Int64.of_int i |+ (rep_r a << 8) |+ (rep_v b << 18)) | `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 = let wr_ins_v b0 t (a : v) =
write_32 t (Int64.of_int i |+ (rep_s24 o << 8)) 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 match a, b with
| (#r as a), (#v as b) -> write_rv i t a b | (#r as a), (#v as b) -> wr_ins_rv 0x01 0x00 t a b
| (#r as a), (#l as b) -> let _ = (a,b) in failwith "..." | (#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 = let jmp t d =
write_rv (i lor 8) t a b let b0 = 0xff in
let w0 = b0 lor (d lsl 8) in
wr_i32 t [w0]
let ret = write_v 0x05 let ret = wr_ins_v 0x00
let btr = write_v 0x0d let btr = wr_ins_v 0x04
let jmp = write_o 0x06 let bfl = wr_ins_v 0x14
let mov = write_opr 0x02 let con = wr_op 0x0
let con = write_opr 0x12 let not_= wr_op 0x1
let add = write_opr 0x22 let neg = wr_op 0x2
let sub = write_opr 0x32 let add = wr_op 0x3
let mul = write_opr 0x42 let sub = wr_op 0x4
let div = write_opr 0x52 let mul = wr_op 0x5
let mod_= write_opr 0x62 let div = wr_op 0x6
let neg_= write_opr 0x72 let mod_= wr_op 0x7
let not_= write_opr 0x82 let ceq = wr_op 0xa let beq = wr_cb 0xa
(* let ? = write_opr 0x92 *) let cne = wr_op 0xb let bne = wr_cb 0xb
let ceq = write_opr 0xa2 let clt = wr_op 0xc let blt = wr_cb 0xc
let beq = write_cbr 0xa2 let cge = wr_op 0xd let bge = wr_cb 0xd
let cne = write_opr 0xb2 let cgt = wr_op 0xe let bgt = wr_cb 0xe
let bne = write_cbr 0xb2 let cle = wr_op 0xf let ble = wr_cb 0xf
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
end end
let bc = Bc.make stdout let bc = Bc.make stdout
@ -111,10 +115,10 @@ let () =
Bc.bgt bc (`R 0) (`R 1); (* 4 *) Bc.bgt bc (`R 0) (`R 1); (* 4 *)
Bc.jmp bc (+9 (* L3 *)); (* 6 *) Bc.jmp bc (+9 (* L3 *)); (* 6 *)
Bc.jmp bc (+3 (* L2 *)); (* 8 *) Bc.jmp bc (+3 (* L2 *)); (* 8 *)
Bc.ret bc (`R 0); (* L1: 10 *) Bc.ret bc (`R 1); (* L1: 10 *)
Bc.mov bc (`R 0) (`K 2); (* L2: 11 *) Bc.add bc (`R 1) (`K 2); (* L2: 11 *)
Bc.jmp bc (-3 (* L1 *)); (* 13 *) 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 *) Bc.jmp bc (-7 (* L1 *)); (* 17 *)
end end

View File

@ -4,179 +4,178 @@ use super::opcodes::*;
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum DecodeError { pub enum DecodeError {
#[error("data truncated (len < {0})")] #[error("not enough data (len < {0})")]
DataTrunc(usize), Trunc(usize),
#[error("invalid len: {0}")]
Len(u8),
#[error("invalid instruction: {0:x}")] #[error("invalid instruction: {0:x}")]
Ins(u8), Ins(u8),
#[error("invalid operator: {0:x}")] #[error("invalid operation: {0:x}")]
Opr(u8), Opr(u8),
#[error("invalid operand: {0:x}")]
Arg(u32),
}
fn read_u8(bs: &[u8], i: usize) -> Result<u8, DecodeError> {
if bs.len() < i + 1 {
return Err(DecodeError::DataTrunc(i + 1));
}
Ok(bs[i])
}
fn read_u16(bs: &[u8], i: usize) -> Result<u32, DecodeError> {
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<u32, DecodeError> {
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<Opr, DecodeError> {
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<Reg, DecodeError> {
Ok(Reg(((w >> k) & 0x3ff) as u16))
}
fn decode_const(w: u32, k: u32) -> Result<ConstIdx, DecodeError> {
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<ArgV, DecodeError> {
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> { pub fn decode_one(bs: &[u8]) -> Result<(Ins, usize), DecodeError> {
let b0 = read_u8(bs, 0)?; let byte0 = byte(bs, 0)?;
let ins; let len = (byte0 & 1) as usize * 2 + 2;
match b0 & 0b111 { let ins = match byte0 & 0x3f {
0b010 => { 0x00 => {
let i; let a = arg(byte(bs, 1)?, byte0);
if b0 & 0b1000 != 0 { Ins::RET(a)
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);
} }
0x04 => {
0b011 => { let a = arg(byte(bs, 1)?, byte0);
#[allow(unreachable_code, unused_variables)] Ins::Br(InsBr::BTR(a))
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);
}
};
} }
0x14 => {
0b101 => { let a = arg(byte(bs, 1)?, byte0);
let i = match b0 & 0b11111 { Ins::Br(InsBr::BFL(a))
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);
} }
0x01 => {
0b110 => { let a = Reg(byte(bs, 2)?);
let i = match b0 { let b = arg(byte(bs, 3)?, byte0);
0x06 => InsO::JMP, Ins::MOV(InsMov::RV(a, b))
_ => return Err(DecodeError::Ins(b0)),
};
let w = read_u32(bs, 0)?;
let o = (w as i32) >> 8;
ins = Ins::O(i, o);
} }
0x03 => {
_ => return Err(DecodeError::Ins(b0)), let a = Reg(byte(bs, 1)?);
}; let b = loc(byte(bs, 2)?, byte(bs, 3)?, byte0);
Ins::MOV(InsMov::RL(a, b))
let len = match b0 & 0b11 { }
0 => return Err(DecodeError::Len(0)), 0x05 => {
x => (x * 2) as usize, 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)) Ok((ins, len))
} }
/// Iterator adapter for [`decode_one`]. #[inline]
#[derive(Clone)] fn byte(bs: &[u8], i: usize) -> Result<u8, DecodeError> {
pub struct Decode<'a>(&'a [u8]); bs.get(i).copied().ok_or(DecodeError::Trunc(i + 1))
/// Decode all instructions from bytecode data.
pub fn decode(bs: &[u8]) -> Decode<'_> {
Decode(bs)
} }
impl Decode<'_> { #[inline]
pub fn inner(&self) -> &[u8] { fn i32_le(bs: &[u8]) -> Result<i32, DecodeError> {
self.0 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<Opr, DecodeError> {
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<Cnd, DecodeError> {
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: AsRef<[u8]>>(T, usize);
/// Decode all instructions from bytecode data.
pub fn decode<T: AsRef<[u8]>>(bs: T) -> Decode<T> {
Decode(bs, 0)
}
impl<T: AsRef<[u8]>> Decode<T> {
pub fn into_inner(self) -> T {
self.0
}
pub fn position(&self) -> usize {
self.1
}
}
impl<T: AsRef<[u8]>> Iterator for Decode<T> {
type Item = Result<Ins, DecodeError>; type Item = Result<Ins, DecodeError>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let bs = self.0; let bs = self.0.as_ref();
if bs.is_empty() { let pos = &mut self.1;
if *pos >= bs.len() {
return None; return None;
} }
decode_one(&bs[*pos..])
Some(decode_one(bs).map(|(ins, len)| { .map(|(ins, len)| {
self.0 = &bs[len..]; *pos += len;
ins Some(ins)
})) })
.map_err(|err| match err {
DecodeError::Trunc(i) => DecodeError::Trunc(i + *pos),
_ => err,
})
.transpose()
} }
} }

View File

@ -1,5 +1,4 @@
pub mod decode;
pub mod opcodes; pub mod opcodes;
pub mod decode;
pub use decode::{decode, DecodeError}; pub use decode::{decode, DecodeError};
pub use opcodes::Ins;

View File

@ -7,16 +7,17 @@ use spicei::*;
enum Error { enum Error {
#[error(transparent)] #[error(transparent)]
Io(#[from] std::io::Error), Io(#[from] std::io::Error),
#[error(transparent)] #[error("decode error at position {1}")]
Decode(#[from] DecodeError), Decode(#[source] DecodeError, usize),
} }
fn entry() -> Result<(), Error> { fn entry() -> Result<(), Error> {
let mut bytes = vec![]; let mut bytes = vec![];
BufReader::new(std::io::stdin()).read_to_end(&mut bytes)?; BufReader::new(std::io::stdin()).read_to_end(&mut bytes)?;
for ins in decode(&bytes) { let mut decode = decode(&bytes);
let ins = ins?; while let Some(ins) = decode.next() {
let ins = ins.map_err(|err| Error::Decode(err, decode.position()))?;
println!("{ins}"); println!("{ins}");
} }
@ -31,7 +32,7 @@ fn main() {
let mut src = err.source(); let mut src = err.source();
while let Some(err) = src { while let Some(err) = src {
println!("- {err}"); println!("from: {err}");
src = err.source(); src = err.source();
} }
} }

View File

@ -2,7 +2,7 @@ use std::fmt;
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
#[repr(transparent)] #[repr(transparent)]
pub struct Reg(pub u16); pub struct Reg(pub u8);
impl fmt::Display for Reg { impl fmt::Display for Reg {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 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)] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
#[repr(transparent)] #[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 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "K{}", self.0) write!(f, "K{}", self.0)
} }
} }
#[derive(Copy, Clone, Eq, PartialEq, Debug)] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum ArgV { pub enum Arg {
R(Reg), 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 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match *self {
Self::R(r) => r.fmt(f), Self::R(r) => r.fmt(f),
Self::K(k) => k.fmt(f), Self::K(k) => k.fmt(f),
} }
} }
} }
#[derive(Copy, Clone, Eq, PartialEq, Debug)] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum ArgL { pub enum Loc {
SubI(Reg, i16), R(Reg, Reg),
SubR(Reg, Reg), O(Reg, i8),
} }
impl fmt::Display for ArgL { impl fmt::Display for Loc {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match *self {
Self::SubI(r, l) => write!(f, "{r}[{l}]"), Self::R(r, l) => write!(f, "{r}[{l}]"),
Self::SubR(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 { pub enum Ins {
V(InsV, ArgV), MOV(InsMov),
RV(InsRV, Reg, ArgV), LOC(InsLoc),
O(InsO, i32), CAL(InsCal),
RL(InsRL, Reg, ArgL), JMP(InsJmp),
LV(InsLV, ArgL, ArgV), Br(InsBr),
RRK(InsRRK, Reg, Reg, ConstIdx), RET(Arg),
} }
impl fmt::Display for Ins { impl fmt::Display for Ins {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { use Ins::*;
Self::O(InsO::JMP, o) => write!(f, "jmp {o:+}"), use InsBr::*;
Self::V(InsV::RET, v) => write!(f, "ret {v}"), use InsMov::*;
Self::V(InsV::BTR, v) => write!(f, "btr {v}"),
Self::RV(InsRV::Op(opr), r, v) => write!(f, "{opr} {r}, {v}"), match *self {
Self::RV(InsRV::Br(cmp), r, v) => write!(f, "b{cmp} {r}, {v}"), MOV(Op(opr, a, b)) => write!(f, "{opr} {a}, {b}"),
Self::RL(InsRL::Get(opr), r, l) => write!(f, "{opr} {r}, {l}"), MOV(RV(a, b)) => write!(f, "mov {a}, {b}"),
Self::RL(InsRL::CAL(n), r, l) => write!(f, "cal {r}, {l}({r},...{n})"), MOV(RL(a, b)) => write!(f, "mov {a}, {b}"),
Self::RL(InsRL::RETCAL(n), r, l) => write!(f, "ret cal {l}({r},...{n})"), MOV(LV(a, b)) => write!(f, "mov {a}, {b}"),
Self::LV(InsLV::Set(opr), l, v) => write!(f, "{opr} {l}, {v}"), LOC(InsLoc(a, b, k)) => write!(f, "loc {a}, {b}, {}", Arg::K(k)),
Self::RRK(InsRRK::LOC, r, v, k) => write!(f, "loc {r}, {v}, {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)] #[derive(Clone, Eq, PartialEq, Debug)]
pub enum InsV { pub enum InsMov {
RET, Op(Opr, Reg, Arg),
BTR, RV(Reg, Arg),
RL(Reg, Loc),
LV(Loc, Arg),
} }
#[derive(Copy, Clone, Eq, PartialEq, Debug)] #[derive(Clone, Eq, PartialEq, Debug)]
pub enum InsRV { pub enum InsBr {
Op(Opr), BTR(Arg),
Br(Cmp), BFL(Arg),
BCnd(Cnd, Reg, Arg),
} }
#[derive(Copy, Clone, Eq, PartialEq, Debug)] #[derive(Clone, Eq, PartialEq, Debug)]
pub enum InsO { pub struct InsLoc(pub Reg, pub Reg, pub Cst);
JMP,
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)] #[derive(Clone, Eq, PartialEq, Debug)]
pub enum InsRL { pub struct InsCal(pub Reg, pub Loc, pub u8);
Get(Opr),
CAL(u16),
RETCAL(u16),
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)] #[derive(Clone, Eq, PartialEq, Debug)]
pub enum InsLV { pub struct InsJmp(pub i32);
Set(Opr),
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum InsRRK {
LOC,
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum Opr { pub enum Opr {
MOV,
CON, CON,
NOT, NOT,
NEG, NEG,
@ -122,13 +116,12 @@ pub enum Opr {
MUL, MUL,
DIV, DIV,
MOD, MOD,
Cmp(Cmp), Cmp(Cnd),
} }
impl fmt::Display for Opr { impl fmt::Display for Opr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Self::MOV => write!(f, "mov"),
Self::CON => write!(f, "con"), Self::CON => write!(f, "con"),
Self::NOT => write!(f, "not"), Self::NOT => write!(f, "not"),
Self::NEG => write!(f, "neg"), Self::NEG => write!(f, "neg"),
@ -143,7 +136,7 @@ impl fmt::Display for Opr {
} }
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum Cmp { pub enum Cnd {
EQ, EQ,
NE, NE,
LT, LT,
@ -152,7 +145,7 @@ pub enum Cmp {
GE, GE,
} }
impl fmt::Display for Cmp { impl fmt::Display for Cnd {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Self::EQ => write!(f, "eq"), Self::EQ => write!(f, "eq"),