From 4beb17894113e422518820cba9f38b237f7e11c0 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Tue, 5 Nov 2024 00:00:11 +0100 Subject: [PATCH] bytecode: test cover and debug --- src/core/microcode/base.rs | 2 +- src/isa/alu/bytecode.rs | 165 ++++++++++++++++++++++++++++++++++--- src/isa/arch.rs | 6 +- src/isa/masm.rs | 125 ++++++++++++++-------------- src/library/marshaller.rs | 32 ++++--- 5 files changed, 242 insertions(+), 88 deletions(-) diff --git a/src/core/microcode/base.rs b/src/core/microcode/base.rs index f2d125e..a9b5e13 100644 --- a/src/core/microcode/base.rs +++ b/src/core/microcode/base.rs @@ -129,7 +129,7 @@ impl RegA { pub fn to_u8(&self) -> u8 { let a = self.a().to_u3().to_u8(); let idx = self.idx().to_u5().to_u8(); - a << 5 + idx + (a << 5) + idx } } diff --git a/src/isa/alu/bytecode.rs b/src/isa/alu/bytecode.rs index 8189eaa..2f7abc7 100644 --- a/src/isa/alu/bytecode.rs +++ b/src/isa/alu/bytecode.rs @@ -109,7 +109,7 @@ impl CtrlInstr { const FAIL: u8 = 3; const RSET: u8 = 4; const JMP: u8 = 5; - const JIFNE: u8 = 6; + const JINE: u8 = 6; const JIFAIL: u8 = 7; const SH: u8 = 8; const SHNE: u8 = 9; @@ -132,7 +132,7 @@ impl Bytecode for CtrlInstr { CtrlInstr::FailCk => Self::FAIL, CtrlInstr::RsetCk => Self::RSET, CtrlInstr::Jmp { .. } => Self::JMP, - CtrlInstr::JiNe { .. } => Self::JIFNE, + CtrlInstr::JiNe { .. } => Self::JINE, CtrlInstr::JiFail { .. } => Self::JIFAIL, CtrlInstr::Sh { .. } => Self::SH, CtrlInstr::ShNe { .. } => Self::SHNE, @@ -157,10 +157,10 @@ impl Bytecode for CtrlInstr { | CtrlInstr::Stop => {} CtrlInstr::Jmp { pos } | CtrlInstr::JiNe { pos } | CtrlInstr::JiFail { pos } | CtrlInstr::Fn { pos } => { - writer.write_fixed(pos.to_le_bytes())? + writer.write_word(pos)? } CtrlInstr::Sh { shift } | CtrlInstr::ShNe { shift } | CtrlInstr::ShFail { shift } => { - writer.write_fixed(shift.to_le_bytes())? + writer.write_byte(shift.to_le_bytes()[0])? } CtrlInstr::Call { site } | CtrlInstr::Exec { site } => { let site = Site::new(site.prog_id, site.offset); @@ -186,26 +186,26 @@ impl Bytecode for CtrlInstr { Self::STOP => Self::Stop, Self::JMP => CtrlInstr::Jmp { - pos: reader.read_fixed(u16::from_le_bytes)?, + pos: reader.read_word()?, }, - Self::JIFNE => CtrlInstr::JiNe { - pos: reader.read_fixed(u16::from_le_bytes)?, + Self::JINE => CtrlInstr::JiNe { + pos: reader.read_word()?, }, Self::JIFAIL => CtrlInstr::JiFail { - pos: reader.read_fixed(u16::from_le_bytes)?, + pos: reader.read_word()?, }, Self::FN => CtrlInstr::Fn { - pos: reader.read_fixed(u16::from_le_bytes)?, + pos: reader.read_word()?, }, Self::SH => CtrlInstr::Sh { - shift: reader.read_fixed(i8::from_le_bytes)?, + shift: i8::from_le_bytes([reader.read_byte()?]), }, Self::SHNE => CtrlInstr::ShNe { - shift: reader.read_fixed(i8::from_le_bytes)?, + shift: i8::from_le_bytes([reader.read_byte()?]), }, Self::SHFAIL => CtrlInstr::ShFail { - shift: reader.read_fixed(i8::from_le_bytes)?, + shift: i8::from_le_bytes([reader.read_byte()?]), }, Self::CALL => { @@ -343,3 +343,144 @@ impl Bytecode for RegInstr { }) } } + +#[cfg(test)] +mod test { + use core::str::FromStr; + + use amplify::confinement::SmallBlob; + + use super::*; + use crate::library::{LibId, LibsSeg, Marshaller}; + use crate::{_a_idx, a}; + + const LIB_ID: &str = "5iMb1eHJ-bN5BOe6-9RvBjYL-jF1ELjj-VV7c8Bm-WvFen1Q"; + + fn roundtrip(instr: impl Into>, bytecode: impl AsRef<[u8]>) -> SmallBlob { + let instr = instr.into(); + let mut libs = LibsSeg::new(); + libs.push(LibId::from_str(LIB_ID).unwrap()).unwrap(); + let mut marshaller = Marshaller::new(&libs); + instr.encode_instr(&mut marshaller).unwrap(); + let (code, data) = marshaller.finish(); + assert_eq!(code.as_slice(), bytecode.as_ref()); + let mut marshaller = Marshaller::with(code, data, &libs); + let decoded = Instr::::decode_instr(&mut marshaller).unwrap(); + assert_eq!(decoded, instr); + marshaller.into_code_data().1 + } + + #[test] + fn nop() { roundtrip(CtrlInstr::Nop, [CtrlInstr::::NOP]); } + #[test] + fn chk() { roundtrip(CtrlInstr::Chk, [CtrlInstr::::CHK]); } + #[test] + fn not_co() { roundtrip(CtrlInstr::NotCo, [CtrlInstr::::NOCO]); } + #[test] + fn fail_ck() { roundtrip(CtrlInstr::FailCk, [CtrlInstr::::FAIL]); } + #[test] + fn reset_ck() { roundtrip(CtrlInstr::RsetCk, [CtrlInstr::::RSET]); } + + #[test] + fn jmp() { roundtrip(CtrlInstr::Jmp { pos: 0x75AE }, [CtrlInstr::::JMP, 0xAE, 0x75]); } + #[test] + fn jine() { roundtrip(CtrlInstr::JiNe { pos: 0x75AE }, [CtrlInstr::::JINE, 0xAE, 0x75]); } + #[test] + fn jifail() { roundtrip(CtrlInstr::JiFail { pos: 0x75AE }, [CtrlInstr::::JIFAIL, 0xAE, 0x75]); } + + #[test] + fn sh() { roundtrip(CtrlInstr::Sh { shift: -0x5 }, [CtrlInstr::::SH, 255 - 5 + 1]); } + #[test] + fn shne() { roundtrip(CtrlInstr::ShNe { shift: -0x5 }, [CtrlInstr::::SHNE, 255 - 5 + 1]); } + #[test] + fn shfail() { roundtrip(CtrlInstr::ShFail { shift: -0x5 }, [CtrlInstr::::SHFAIL, 255 - 5 + 1]); } + + #[test] + fn exec() { + let lib_id = LibId::from_str(LIB_ID).unwrap(); + roundtrip( + CtrlInstr::Exec { + site: Site::new(lib_id, 0x69AB), + }, + [CtrlInstr::::EXEC, 0x00, 0xAB, 0x69], + ); + } + #[test] + fn func() { roundtrip(CtrlInstr::Fn { pos: 0x75AE }, [CtrlInstr::::FN, 0xAE, 0x75]); } + #[test] + fn call() { + let lib_id = LibId::from_str(LIB_ID).unwrap(); + roundtrip( + CtrlInstr::Call { + site: Site::new(lib_id, 0x69AB), + }, + [CtrlInstr::::CALL, 0x00, 0xAB, 0x69], + ); + } + + #[test] + fn ret() { roundtrip(CtrlInstr::Ret, [CtrlInstr::::RET]); } + #[test] + fn stop() { roundtrip(CtrlInstr::Stop, [CtrlInstr::::STOP]); } + + #[test] + fn clr() { roundtrip(RegInstr::Clr { dst: a![A128:A] }, [RegInstr::CLR, 0b1000_1010]); } + #[test] + fn test() { roundtrip(RegInstr::Test { src: a![A16:3] }, [RegInstr::TEST, 0b0010_0010]); } + + #[test] + fn put() { + let pos = 0xdeadcafebeefc0fe; + let data = roundtrip( + RegInstr::Put { + dst: a![A64.x], + val: MaybeU128::U128(pos), + }, + [RegInstr::PUT, 0b0111_1101, 0, 0], + ); + assert_eq!(data.as_slice(), &pos.to_le_bytes()); + } + #[test] + fn pif() { + let pos = 0xdeadcafebeefc0fe; + let data = roundtrip( + RegInstr::Pif { + dst: a![A64.x], + val: MaybeU128::U128(pos), + }, + [RegInstr::PIF, 0b0111_1101, 0, 0], + ); + assert_eq!(data.as_slice(), &pos.to_le_bytes()); + } + + #[test] + fn cpy() { + roundtrip( + RegInstr::Cpy { + dst: a![A32:7], + src: a![A32:E], + }, + [RegInstr::CPY, 0b0100_0110, 0b0100_1110], + ); + } + #[test] + fn swp() { + roundtrip( + RegInstr::Swp { + src_dst1: a![A32:7], + src_dst2: a![A32:E], + }, + [RegInstr::SWP, 0b0100_0110, 0b0100_1110], + ); + } + #[test] + fn eq() { + roundtrip( + RegInstr::Eq { + src1: a![A32:7], + src2: a![A32:E], + }, + [RegInstr::EQ, 0b0100_0110, 0b0100_1110], + ); + } +} diff --git a/src/isa/arch.rs b/src/isa/arch.rs index a1dc0e0..b674a0d 100644 --- a/src/isa/arch.rs +++ b/src/isa/arch.rs @@ -93,22 +93,26 @@ pub trait InstructionSet: Debug + Display { pub struct ReservedInstr(/** Reserved instruction op code value */ pub(super) u8); /// Complete AluVM ISA. -#[derive(Clone, PartialEq, Eq, Hash, Debug, Display)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, Display, From)] #[display(inner)] pub enum Instr = ReservedInstr> { /// Control flow instructions. + #[from] Ctrl(CtrlInstr), /// Register manipulation instructions. + #[from] Reg(RegInstr), #[cfg(feature = "GFA")] /// Arithmetic instructions for finite fields (Galois fields). + #[from] GFqA(FieldInstr), // #[cfg(feature = "str")] // Str(array::instr::StrInstr), /// Reserved instruction for future use in core `ALU` ISAs. + #[from] Reserved(ReservedInstr), /// Other ISA extensions, defined externally. diff --git a/src/isa/masm.rs b/src/isa/masm.rs index 7cdc110..4001406 100644 --- a/src/isa/masm.rs +++ b/src/isa/masm.rs @@ -53,7 +53,7 @@ macro_rules! aluasm { #[cfg(feature = "GFA")] use $crate::isa::FieldInstr; use $crate::regs::{IdxA, RegA, Reg, IdxAl, A, Idx32, Idx16}; - use $crate::{_a, _a_idx, paste}; + use $crate::{a, _a_idx, paste}; $crate::aluasm_isa! { ReservedInstr => $( $tt )+ } } }}; } @@ -237,191 +237,191 @@ macro_rules! instr { // Clear (clr $A:ident : $idx:literal) => { - Instr::Reg(RegInstr::Clr { dst: _a!($A : $idx) }) + Instr::Reg(RegInstr::Clr { dst: a!($A : $idx) }) }; (clr $A:ident : $idx:ident) => { - Instr::Reg(RegInstr::Clr { dst: _a!($A : $idx) }) + Instr::Reg(RegInstr::Clr { dst: a!($A : $idx) }) }; (clr $A:ident . $idx:ident) => { - Instr::Reg(RegInstr::Clr { dst: _a!($A . $idx) }) + Instr::Reg(RegInstr::Clr { dst: a!($A . $idx) }) }; // Test (test $A:ident : $idx:literal) => { - Instr::Reg(RegInstr::Test { dst: _a!($A : $idx) }) + Instr::Reg(RegInstr::Test { dst: a!($A : $idx) }) }; (test $A:ident : $idx:ident) => { - Instr::Reg(RegInstr::Test { dst: _a!($A : $idx) }) + Instr::Reg(RegInstr::Test { dst: a!($A : $idx) }) }; (test $A:ident . $idx:ident) => { - Instr::Reg(RegInstr::Test { dst: _a!($A . $idx) }) + Instr::Reg(RegInstr::Test { dst: a!($A . $idx) }) }; // Put (put $A:ident : $idx:literal, $val:literal) => { - Instr::Reg(RegInstr::Put { dst: _a!($A : $idx), val: $val }) + Instr::Reg(RegInstr::Put { dst: a!($A : $idx), val: $val }) }; (put $A:ident : $idx:ident, $val:literal) => { - Instr::Reg(RegInstr::Put { dst: _a!($A : $idx), val: $val }) + Instr::Reg(RegInstr::Put { dst: a!($A : $idx), val: $val }) }; (put $A:ident . $idx:ident, $val:literal) => { - Instr::Reg(RegInstr::Put { dst: _a!($A . $idx), val: $val }) + Instr::Reg(RegInstr::Put { dst: a!($A . $idx), val: $val }) }; (put $A:ident : $idx:literal, $val:literal #h) => { - Instr::Reg(RegInstr::Put { dst: _a!($A : $idx), val: from_hex!(u128, $val) }) + Instr::Reg(RegInstr::Put { dst: a!($A : $idx), val: from_hex!(u128, $val) }) }; (put $A:ident : $idx:ident, $val:literal #h) => { - Instr::Reg(RegInstr::Put { dst: _a!($A : $idx), val: from_hex!(u128, $val) }) + Instr::Reg(RegInstr::Put { dst: a!($A : $idx), val: from_hex!(u128, $val) }) }; (put $A:ident . $idx:ident, $val:literal #h) => { - Instr::Reg(RegInstr::Put { dst: _a!($A . $idx), val: from_hex!(u128, $val) }) + Instr::Reg(RegInstr::Put { dst: a!($A . $idx), val: from_hex!(u128, $val) }) }; // Put if (pif $A:ident : $idx:literal, $val:literal) => { - Instr::Reg(RegInstr::Pif { dst: _a!($A : $idx), val: $val.into() }) + Instr::Reg(RegInstr::Pif { dst: a!($A : $idx), val: $val.into() }) }; (pif $A:ident : $idx:ident, $val:literal) => { - Instr::Reg(RegInstr::Pif { dst: _a!($A : $idx), val: $val.into() }) + Instr::Reg(RegInstr::Pif { dst: a!($A : $idx), val: $val.into() }) }; (pif $A:ident . $idx:ident, $val:literal) => { - Instr::Reg(RegInstr::Pif { dst: _a!($A . $idx), val: $val.into() }) + Instr::Reg(RegInstr::Pif { dst: a!($A . $idx), val: $val.into() }) }; (pif $A:ident : $idx:literal, $val:literal #h) => { - Instr::Reg(RegInstr::Pif { dst: _a!($A : $idx), val: from_hex!(u128, $val).into() }) + Instr::Reg(RegInstr::Pif { dst: a!($A : $idx), val: from_hex!(u128, $val).into() }) }; (pif $A:ident : $idx:ident, $val:literal #h) => { - Instr::Reg(RegInstr::Pif { dst: _a!($A : $idx), val: from_hex!(u128, $val).into() }) + Instr::Reg(RegInstr::Pif { dst: a!($A : $idx), val: from_hex!(u128, $val).into() }) }; (pif $A:ident . $idx:ident, $val:literal #h) => { - Instr::Reg(RegInstr::Pif { dst: _a!($A . $idx), val: from_hex!(u128, $val).into() }) + Instr::Reg(RegInstr::Pif { dst: a!($A . $idx), val: from_hex!(u128, $val).into() }) }; // Copy (cpy $D:ident : $dst:literal, $S:ident : $src:literal) => { - Instr::Reg(RegInstr::Cpy { dst: _a!($D : $dst), src: _a!($S : $src) }) + Instr::Reg(RegInstr::Cpy { dst: a!($D : $dst), src: a!($S : $src) }) }; (cpy $D:ident : $dst:ident, $S:ident : $src:literal) => { - Instr::Reg(RegInstr::Cpy { dst: _a!($D : $dst), src: _a!($S : $src) }) + Instr::Reg(RegInstr::Cpy { dst: a!($D : $dst), src: a!($S : $src) }) }; (cpy $D:ident . $dst:ident, $S:ident : $src:literal) => { - Instr::Reg(RegInstr::Cpy { dst: _a!($D . $dst), src: _a!($S : $src) }) + Instr::Reg(RegInstr::Cpy { dst: a!($D . $dst), src: a!($S : $src) }) }; (cpy $D:ident : $dst:literal, $S:ident : $src:ident) => { - Instr::Reg(RegInstr::Cpy { dst: _a!($D : $dst), src: _a!($S : $src) }) + Instr::Reg(RegInstr::Cpy { dst: a!($D : $dst), src: a!($S : $src) }) }; (cpy $D:ident : $dst:ident, $S:ident : $src:ident) => { - Instr::Reg(RegInstr::Cpy { dst: _a!($D : $dst), src: _a!($S : $src) }) + Instr::Reg(RegInstr::Cpy { dst: a!($D : $dst), src: a!($S : $src) }) }; (cpy $D:ident . $dst:ident, $S:ident : $src:ident) => { - Instr::Reg(RegInstr::Cpy { dst: _a!($D . $dst), src: _a!($S : $src) }) + Instr::Reg(RegInstr::Cpy { dst: a!($D . $dst), src: a!($S : $src) }) }; (cpy $D:ident : $dst:literal, $S:ident . $src:ident) => { - Instr::Reg(RegInstr::Cpy { dst: _a!($D : $dst), src: _a!($S . $src) }) + Instr::Reg(RegInstr::Cpy { dst: a!($D : $dst), src: a!($S . $src) }) }; (cpy $D:ident : $dst:ident, $S:ident . $src:ident) => { - Instr::Reg(RegInstr::Cpy { dst: _a!($D : $dst), src: _a!($S . $src) }) + Instr::Reg(RegInstr::Cpy { dst: a!($D : $dst), src: a!($S . $src) }) }; (cpy $D:ident . $dst:ident, $S:ident . $src:ident) => { - Instr::Reg(RegInstr::Cpy { dst: _a!($D . $dst), src: _a!($S . $src) }) + Instr::Reg(RegInstr::Cpy { dst: a!($D . $dst), src: a!($S . $src) }) }; // Swap (swp $D:ident : $dst:literal, $S:ident : $src:literal) => { - Instr::Reg(RegInstr::Swp { src_dst1: _a!($D : $dst), src_dst2: _a!($S : $src) }) + Instr::Reg(RegInstr::Swp { src_dst1: a!($D : $dst), src_dst2: a!($S : $src) }) }; (swp $D:ident : $dst:ident, $S:ident : $src:literal) => { - Instr::Reg(RegInstr::Swp { src_dst1: _a!($D : $dst), src_dst2: _a!($S : $src) }) + Instr::Reg(RegInstr::Swp { src_dst1: a!($D : $dst), src_dst2: a!($S : $src) }) }; (swp $D:ident . $dst:ident, $S:ident : $src:literal) => { - Instr::Reg(RegInstr::Swp { src_dst1: _a!($D . $dst), src_dst2: _a!($S : $src) }) + Instr::Reg(RegInstr::Swp { src_dst1: a!($D . $dst), src_dst2: a!($S : $src) }) }; (swp $D:ident : $dst:literal, $S:ident : $src:ident) => { - Instr::Reg(RegInstr::Swp { src_dst1: _a!($D : $dst), src_dst2: _a!($S : $src) }) + Instr::Reg(RegInstr::Swp { src_dst1: a!($D : $dst), src_dst2: a!($S : $src) }) }; (swp $D:ident : $dst:ident, $S:ident : $src:ident) => { - Instr::Reg(RegInstr::Swp { src_dst1: _a!($D : $dst), src_dst2: _a!($S : $src) }) + Instr::Reg(RegInstr::Swp { src_dst1: a!($D : $dst), src_dst2: a!($S : $src) }) }; (swp $D:ident . $dst:ident, $S:ident : $src:ident) => { - Instr::Reg(RegInstr::Swp { src_dst1: _a!($D . $dst), src_dst2: _a!($S : $src) }) + Instr::Reg(RegInstr::Swp { src_dst1: a!($D . $dst), src_dst2: a!($S : $src) }) }; (swp $D:ident : $dst:literal, $S:ident . $src:ident) => { - Instr::Reg(RegInstr::Swp { src_dst1: _a!($D : $dst), src_dst2: _a!($S . $src) }) + Instr::Reg(RegInstr::Swp { src_dst1: a!($D : $dst), src_dst2: a!($S . $src) }) }; (swp $D:ident : $dst:ident, $S:ident . $src:ident) => { - Instr::Reg(RegInstr::Swp { src_dst1: _a!($D : $dst), src_dst2: _a!($S . $src) }) + Instr::Reg(RegInstr::Swp { src_dst1: a!($D : $dst), src_dst2: a!($S . $src) }) }; (swp $D:ident . $dst:ident, $S:ident . $src:ident) => { - Instr::Reg(RegInstr::Swp { src_dst1: _a!($D . $dst), src_dst2: _a!($S . $src) }) + Instr::Reg(RegInstr::Swp { src_dst1: a!($D . $dst), src_dst2: a!($S . $src) }) }; // Equals (eq $D:ident : $dst:literal, $S:ident : $src:literal) => { - Instr::Reg(RegInstr::Eq { src1: _a!($D : $dst), src2: _a!($S : $src) }) + Instr::Reg(RegInstr::Eq { src1: a!($D : $dst), src2: a!($S : $src) }) }; (eq $D:ident : $dst:ident, $S:ident : $src:literal) => { - Instr::Reg(RegInstr::Eq { src1: _a!($D : $dst), src2: _a!($S : $src) }) + Instr::Reg(RegInstr::Eq { src1: a!($D : $dst), src2: a!($S : $src) }) }; (eq $D:ident . $dst:ident, $S:ident : $src:literal) => { - Instr::Reg(RegInstr::Eq { src1: _a!($D . $dst), src2: _a!($S : $src) }) + Instr::Reg(RegInstr::Eq { src1: a!($D . $dst), src2: a!($S : $src) }) }; (eq $D:ident : $dst:literal, $S:ident : $src:ident) => { - Instr::Reg(RegInstr::Eq { src1: _a!($D : $dst), src2: _a!($S : $src) }) + Instr::Reg(RegInstr::Eq { src1: a!($D : $dst), src2: a!($S : $src) }) }; (eq $D:ident : $dst:ident, $S:ident : $src:ident) => { - Instr::Reg(RegInstr::Eq { src1: _a!($D : $dst), src2: _a!($S : $src) }) + Instr::Reg(RegInstr::Eq { src1: a!($D : $dst), src2: a!($S : $src) }) }; (eq $D:ident . $dst:ident, $S:ident : $src:ident) => { - Instr::Reg(RegInstr::Eq { src1: _a!($D . $dst), src2: _a!($S : $src) }) + Instr::Reg(RegInstr::Eq { src1: a!($D . $dst), src2: a!($S : $src) }) }; (eq $D:ident : $dst:literal, $S:ident . $src:ident) => { - Instr::Reg(RegInstr::Eq { src1: _a!($D : $dst), src2: _a!($S . $src) }) + Instr::Reg(RegInstr::Eq { src1: a!($D : $dst), src2: a!($S . $src) }) }; (eq $D:ident : $dst:ident, $S:ident . $src:ident) => { - Instr::Reg(RegInstr::Eq { src1: _a!($D : $dst), src2: _a!($S . $src) }) + Instr::Reg(RegInstr::Eq { src1: a!($D : $dst), src2: a!($S . $src) }) }; (eq $D:ident . $dst:ident, $S:ident . $src:ident) => { - Instr::Reg(RegInstr::Eq { src1: _a!($D . $dst), src2: _a!($S . $src) }) + Instr::Reg(RegInstr::Eq { src1: a!($D . $dst), src2: a!($S . $src) }) }; // Modulo-increment (incmod $A:ident : $idx:literal, $val:literal) => { #[cfg(feature = "GFA")] - Instr::GFqA(FieldInstr::IncMod { src_dst: _a!($A : $idx), val: $val }) + Instr::GFqA(FieldInstr::IncMod { src_dst: a!($A : $idx), val: $val }) }; (incmod $A:ident : $idx:ident, $val:literal) => { #[cfg(feature = "GFA")] - Instr::GFqA(FieldInstr::IncMod { src_dst: _a!($A : $idx), val: $val }) + Instr::GFqA(FieldInstr::IncMod { src_dst: a!($A : $idx), val: $val }) }; (incmod $A:ident . $idx:ident, $val:literal) => { #[cfg(feature = "GFA")] - Instr::GFqA(FieldInstr::IncMod { src_dst: _a!($A . $idx), val: $val }) + Instr::GFqA(FieldInstr::IncMod { src_dst: a!($A . $idx), val: $val }) }; // Modulo-decrement (decmod $A:ident : $idx:literal, $val:literal) => { #[cfg(feature = "GFA")] - Instr::GFqA(FieldInstr::DecMod { src_dst: _a!($A : $idx), val: $val }) + Instr::GFqA(FieldInstr::DecMod { src_dst: a!($A : $idx), val: $val }) }; (decmod $A:ident : $idx:ident, $val:literal) => { #[cfg(feature = "GFA")] - Instr::GFqA(FieldInstr::DecMod { src_dst: _a!($A : $idx), val: $val }) + Instr::GFqA(FieldInstr::DecMod { src_dst: a!($A : $idx), val: $val }) }; (decmod $A:ident . $idx:ident, $val:literal) => { #[cfg(feature = "GFA")] - Instr::GFqA(FieldInstr::DecMod { src_dst: _a!($A . $idx), val: $val }) + Instr::GFqA(FieldInstr::DecMod { src_dst: a!($A . $idx), val: $val }) }; // Modulo-negate (negmod $A:ident : $idx:literal) => { #[cfg(feature = "GFA")] - Instr::GFqA(FieldInstr::NegMod { src_dst: _a!($A : $idx) }) + Instr::GFqA(FieldInstr::NegMod { src_dst: a!($A : $idx) }) }; (negmod $A:ident : $idx:ident) => { #[cfg(feature = "GFA")] - Instr::GFqA(FieldInstr::NegMod { src_dst: _a!($A : $idx) }) + Instr::GFqA(FieldInstr::NegMod { src_dst: a!($A : $idx) }) }; (negmod $A:ident . $idx:ident) => { #[cfg(feature = "GFA")] - Instr::GFqA(FieldInstr::NegMod { src_dst: _a!($A . $idx) }) + Instr::GFqA(FieldInstr::NegMod { src_dst: a!($A . $idx) }) }; // Modulo-add (addmod A128 : $dst:literal, A128 : $src1:literal, A128 : $src2:literal) => { @@ -456,16 +456,15 @@ macro_rules! instr { } #[macro_export] -#[doc(hidden)] -macro_rules! _a { +macro_rules! a { ($A:ident : $idx:literal) => { -RegA::$A(_a_idx!(: $idx)) +$crate::regs::RegA::$A(_a_idx!(: $idx)) }; ($A:ident : $idx:ident) => { -RegA::$A(_a_idx!(: $idx)) +$crate::regs::RegA::$A(_a_idx!(: $idx)) }; ($A:ident. $idx:ident) => { -RegA::$A(_a_idx!(. $idx)) +$crate::regs::RegA::$A(_a_idx!(. $idx)) }; } @@ -473,12 +472,12 @@ RegA::$A(_a_idx!(. $idx)) #[doc(hidden)] macro_rules! _a_idx { (: $idx:literal) => { - IdxA::from(paste! { Idx32 :: [< L $idx >] }) + $crate::regs::IdxA::from($crate::paste! { $crate::regs::Idx32 :: [< L $idx >] }) }; (: $idx:ident) => { - IdxA::from(Idx32::$idx) + $crate::regs::IdxA::from($crate::regs::Idx32::$idx) }; (. $idx:ident) => { - IdxA::from(paste! { Idx32 :: [< S $idx >] }) + $crate::regs::IdxA::from($crate::paste! { $crate::regs::Idx32 :: [< S $idx >] }) }; } diff --git a/src/library/marshaller.rs b/src/library/marshaller.rs index 24983b2..caaa874 100644 --- a/src/library/marshaller.rs +++ b/src/library/marshaller.rs @@ -109,6 +109,13 @@ where Self: 'a } } +impl<'a> Marshaller<'a, SmallBlob, SmallBlob> +where Self: 'a +{ + #[cfg(test)] + pub fn into_code_data(self) -> (SmallBlob, SmallBlob) { (self.bytecode, self.data) } +} + impl<'a, C, D> Marshaller<'a, C, D> where C: AsRef<[u8]>, @@ -182,7 +189,7 @@ where impl<'a, C, D> Marshaller<'a, C, D> where - C: AsRef<[u8]> + AsMut<[u8]>, + C: AsRef<[u8]> + AsMut<[u8]> + Extend, D: AsRef<[u8]>, Self: 'a, { @@ -191,9 +198,12 @@ where let value = ((value as u64) << (self.bit_pos.to_u8())).to_le_bytes(); let n_bytes = (cnt + self.bit_pos.to_u8() + 7) / 8; for i in 0..n_bytes { - if self.is_eof() { + if self.bytecode.as_ref().len() >= u16::MAX as usize { return Err(CodeEofError); } + if self.is_eof() { + self.bytecode.extend([0]); + } let byte_pos = self.byte_pos as usize; let bit_pos = self.bit_pos.to_u8(); let byte = &mut self.bytecode.as_mut()[byte_pos]; @@ -346,7 +356,7 @@ where impl<'a, C, D> BytecodeWrite for Marshaller<'a, C, D> where - C: AsRef<[u8]> + AsMut<[u8]>, + C: AsRef<[u8]> + AsMut<[u8]> + Extend, D: AsRef<[u8]> + AsMut<[u8]> + Extend, Self: 'a, { @@ -466,8 +476,7 @@ mod tests { #[test] fn write() { let libseg = LibsSeg::default(); - let mut code = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - let mut marshaller = Marshaller::with(&mut code, vec![], &libseg); + let mut marshaller = Marshaller::with(vec![], vec![], &libseg); marshaller.write_2bits(u2::with(0b00000011)).unwrap(); marshaller.write_3bits(u3::with(0b00000101)).unwrap(); marshaller.write_7bits(u7::with(0b01011111)).unwrap(); @@ -478,8 +487,8 @@ mod tests { marshaller.write_word(two_bytes).unwrap(); let number = 255u8; marshaller.write_fixed(255u8.to_le_bytes()).unwrap(); + let (code, data) = marshaller.finish(); - let data = marshaller.data; let mut marshaller = Marshaller::with(code, data, &libseg); assert_eq!(marshaller.read_2bits().unwrap().to_u8(), 0b00000011); assert_eq!(marshaller.read_3bits().unwrap().to_u8(), 0b00000101); @@ -494,8 +503,7 @@ mod tests { #[test] fn write_data() { let libseg = LibsSeg::default(); - let mut code = [0, 0, 0, 0, 0, 0]; - let mut marshaller = Marshaller::with(&mut code, vec![], &libseg); + let mut marshaller = Marshaller::with(vec![], vec![], &libseg); marshaller.write_fixed(256u16.to_le_bytes()).unwrap(); assert_eq!(marshaller.data, vec![0, 1]); } @@ -503,11 +511,13 @@ mod tests { #[test] fn write_eof() { let libseg = LibsSeg::default(); - let mut code = [0, 0]; - let mut marshaller = Marshaller::with(&mut code, vec![], &libseg); + let mut marshaller = Marshaller::with(vec![0x00; 0xFFFD], vec![], &libseg); + marshaller.seek(0xFFFD).unwrap_err(); + marshaller.byte_pos = 0xFFFD; marshaller.write_2bits(u2::with(0b00000011)).unwrap(); marshaller.write_3bits(u3::with(0b00000101)).unwrap(); marshaller.write_7bits(u7::with(0b01011111)).unwrap(); - assert!(marshaller.write_byte(0b11100111).is_err()); + marshaller.write_byte(0b11100111).unwrap_err(); + assert_eq!(&marshaller.bytecode[0xFFFD..], &[0b11110111, 0b1011]); } }