From a02daa56f94b4d80cf009d66c2378cd7809f19d7 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Fri, 19 Apr 2024 09:40:54 +0200 Subject: [PATCH 01/10] isa: remove bytecount method from Bytecode trait --- src/isa/bytecode.rs | 140 -------------------------------------------- 1 file changed, 140 deletions(-) diff --git a/src/isa/bytecode.rs b/src/isa/bytecode.rs index 0fbcb06..92fda37 100644 --- a/src/isa/bytecode.rs +++ b/src/isa/bytecode.rs @@ -67,9 +67,6 @@ impl ::std::error::Error for BytecodeError { /// bound by u16), (3) it provides too many fails in situations when we can't /// fail because of `u16`-bounding and exclusive in-memory encoding handling. pub trait Bytecode { - /// Returns number of bytes which instruction and its argument occupies - fn byte_count(&self) -> u16; - /// Returns range of instruction btecodes covered by a set of operations fn instr_range() -> RangeInclusive; @@ -106,26 +103,6 @@ impl Bytecode for Instr where Extension: InstructionSet, { - fn byte_count(&self) -> u16 { - match self { - Instr::ControlFlow(instr) => instr.byte_count(), - Instr::Put(instr) => instr.byte_count(), - Instr::Move(instr) => instr.byte_count(), - Instr::Cmp(instr) => instr.byte_count(), - Instr::Arithmetic(instr) => instr.byte_count(), - Instr::Bitwise(instr) => instr.byte_count(), - Instr::Bytes(instr) => instr.byte_count(), - Instr::Digest(instr) => instr.byte_count(), - #[cfg(feature = "secp256k1")] - Instr::Secp256k1(instr) => instr.byte_count(), - #[cfg(feature = "curve25519")] - Instr::Curve25519(instr) => instr.byte_count(), - Instr::ExtensionCodes(instr) => instr.byte_count(), - Instr::ReservedInstruction(instr) => instr.byte_count(), - Instr::Nop => 1, - } - } - #[inline] fn instr_range() -> RangeInclusive { 0..=u8::MAX } @@ -235,17 +212,6 @@ where } impl Bytecode for ControlFlowOp { - fn byte_count(&self) -> u16 { - match self { - ControlFlowOp::Fail | ControlFlowOp::Succ => 1, - ControlFlowOp::Jmp(_) | ControlFlowOp::Jif(_) => 3, - ControlFlowOp::Routine(_) => 3, - ControlFlowOp::Call(_) => 4, - ControlFlowOp::Exec(_) => 4, - ControlFlowOp::Ret => 1, - } - } - #[inline] fn instr_range() -> RangeInclusive { INSTR_FAIL..=INSTR_RET } @@ -308,17 +274,6 @@ impl Bytecode for ControlFlowOp { } impl Bytecode for PutOp { - fn byte_count(&self) -> u16 { - match self { - PutOp::ClrA(_, _) | PutOp::ClrF(_, _) | PutOp::ClrR(_, _) => 2, - PutOp::PutA(_, _, _) - | PutOp::PutIfA(_, _, _) - | PutOp::PutF(_, _, _) - | PutOp::PutR(_, _, _) - | PutOp::PutIfR(_, _, _) => 3, - } - } - #[inline] fn instr_range() -> RangeInclusive { INSTR_CLRA..=INSTR_PUTIFR } @@ -437,9 +392,6 @@ impl Bytecode for PutOp { } impl Bytecode for MoveOp { - #[inline] - fn byte_count(&self) -> u16 { 3 } - #[inline] fn instr_range() -> RangeInclusive { INSTR_MOV..=INSTR_CFA } @@ -604,23 +556,6 @@ impl Bytecode for MoveOp { } impl Bytecode for CmpOp { - fn byte_count(&self) -> u16 { - match self { - CmpOp::GtA(_, _, _, _) - | CmpOp::LtA(_, _, _, _) - | CmpOp::GtF(_, _, _, _) - | CmpOp::LtF(_, _, _, _) - | CmpOp::GtR(_, _, _) - | CmpOp::LtR(_, _, _) - | CmpOp::EqA(_, _, _, _) - | CmpOp::EqF(_, _, _, _) - | CmpOp::EqR(_, _, _, _) => 3, - CmpOp::IfZA(_, _) | CmpOp::IfZR(_, _) | CmpOp::IfNA(_, _) | CmpOp::IfNR(_, _) => 2, - CmpOp::St(_, _, _) => 2, - CmpOp::StInv => 1, - } - } - #[inline] fn instr_range() -> RangeInclusive { INSTR_LGT..=INSTR_STINV } @@ -775,22 +710,6 @@ impl Bytecode for CmpOp { } impl Bytecode for ArithmeticOp { - fn byte_count(&self) -> u16 { - match self { - ArithmeticOp::AddA(_, _, _, _) - | ArithmeticOp::AddF(_, _, _, _) - | ArithmeticOp::SubA(_, _, _, _) - | ArithmeticOp::SubF(_, _, _, _) - | ArithmeticOp::MulA(_, _, _, _) - | ArithmeticOp::MulF(_, _, _, _) - | ArithmeticOp::DivA(_, _, _, _) - | ArithmeticOp::DivF(_, _, _, _) - | ArithmeticOp::Rem(_, _, _, _) - | ArithmeticOp::Stp(_, _, _) => 3, - ArithmeticOp::Neg(_, _) | ArithmeticOp::Abs(_, _) => 2, - } - } - #[inline] fn instr_range() -> RangeInclusive { INSTR_ADD..=INSTR_REM } @@ -898,23 +817,6 @@ impl Bytecode for ArithmeticOp { } impl Bytecode for BitwiseOp { - fn byte_count(&self) -> u16 { - match self { - BitwiseOp::And(_, _, _, _) | BitwiseOp::Or(_, _, _, _) | BitwiseOp::Xor(_, _, _, _) => { - 3 - } - BitwiseOp::Not(_, _) => 2, - - BitwiseOp::Shl(_, _, _, _) - | BitwiseOp::ShrA(_, _, _, _, _) - | BitwiseOp::ShrR(_, _, _, _) - | BitwiseOp::Scl(_, _, _, _) - | BitwiseOp::Scr(_, _, _, _) => 3, - - BitwiseOp::RevA(_, _) | BitwiseOp::RevR(_, _) => 2, - } - } - #[inline] fn instr_range() -> RangeInclusive { INSTR_AND..=INSTR_REVR } @@ -1071,24 +973,6 @@ impl Bytecode for BitwiseOp { } impl Bytecode for BytesOp { - fn byte_count(&self) -> u16 { - match self { - BytesOp::Put(_, _, _) => 6, - BytesOp::Mov(_, _) | BytesOp::Swp(_, _) => 2, - BytesOp::Fill(_, _, _, _, _) => 3, - BytesOp::Len(_, _, _) | BytesOp::Cnt(_, _, _) => 3, - BytesOp::Eq(_, _) => 2, - BytesOp::Con(_, _, _, _, _) => 4, - BytesOp::Find(_, _) => 2, - BytesOp::Extr(_, _, _, _) | BytesOp::Inj(_, _, _, _) => 3, - BytesOp::Join(_, _, _) => 3, - BytesOp::Splt(_, _, _, _, _) => 4, - BytesOp::Ins(_, _, _, _) => 3, - BytesOp::Del(_, _, _, _, _, _, _, _, _) => 4, - BytesOp::Rev(_, _) => 2, - } - } - #[inline] fn instr_range() -> RangeInclusive { INSTR_PUT..=INSTR_REV } @@ -1288,9 +1172,6 @@ impl Bytecode for BytesOp { } impl Bytecode for DigestOp { - #[inline] - fn byte_count(&self) -> u16 { 3 } - #[inline] fn instr_range() -> RangeInclusive { INSTR_RIPEMD..=INSTR_SHA512 } @@ -1338,15 +1219,6 @@ impl Bytecode for DigestOp { } impl Bytecode for Secp256k1Op { - fn byte_count(&self) -> u16 { - match self { - Secp256k1Op::Gen(_, _) => 2, - Secp256k1Op::Mul(_, _, _, _) => 3, - Secp256k1Op::Add(_, _) => 2, - Secp256k1Op::Neg(_, _) => 2, - } - } - #[inline] fn instr_range() -> RangeInclusive { INSTR_SECP_GEN..=INSTR_SECP_NEG } @@ -1406,15 +1278,6 @@ impl Bytecode for Secp256k1Op { } impl Bytecode for Curve25519Op { - fn byte_count(&self) -> u16 { - match self { - Curve25519Op::Gen(_, _) => 2, - Curve25519Op::Mul(_, _, _, _) => 3, - Curve25519Op::Add(_, _, _, _) => 3, - Curve25519Op::Neg(_, _) => 2, - } - } - #[inline] fn instr_range() -> RangeInclusive { INSTR_ED_GEN..=INSTR_ED_NEG } @@ -1481,9 +1344,6 @@ impl Bytecode for Curve25519Op { } impl Bytecode for ReservedOp { - #[inline] - fn byte_count(&self) -> u16 { 1 } - #[inline] fn instr_range() -> RangeInclusive { INSTR_RESV_FROM..=INSTR_ISAE_TO } From 2348d891cc3049329b3c923ea111f11582e2bba3 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 20 Apr 2024 10:03:41 +0200 Subject: [PATCH 02/10] isa: fix doc for arithmetic operations --- src/isa/instr.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/isa/instr.rs b/src/isa/instr.rs index fd49953..5fb8eaa 100644 --- a/src/isa/instr.rs +++ b/src/isa/instr.rs @@ -421,35 +421,35 @@ pub enum CmpOp { /// `wrap` flag is provided). #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Display)] pub enum ArithmeticOp { - /// Adds values from two integer arithmetic registers and puts result into the first register. + /// Adds values from two integer arithmetic registers and puts result into the second register. #[display("add.{0} {1}{2},{1}{3}")] AddA(IntFlags, RegA, Reg32, Reg32), - /// Adds values from two float arithmetic registers and puts result into the first register. + /// Adds values from two float arithmetic registers and puts result into the second register. #[display("add.{0} {1}{2},{1}{3}")] AddF(RoundingFlag, RegF, Reg32, Reg32), - /// Subtracts values from two integer arithmetic registers and puts result into the first + /// Subtracts values from two integer arithmetic registers and puts result into the second /// register. #[display("sub.{0} {1}{2},{1}{3}")] SubA(IntFlags, RegA, Reg32, Reg32), - /// Subtracts values from two float arithmetic registers and puts result into the first + /// Subtracts values from two float arithmetic registers and puts result into the second /// register. #[display("sub.{0} {1}{2},{1}{3}")] SubF(RoundingFlag, RegF, Reg32, Reg32), - /// Multiplies values from two integer arithmetic registers and puts result into the first + /// Multiplies values from two integer arithmetic registers and puts result into the second /// register. #[display("mul.{0} {1}{2},{1}{3}")] MulA(IntFlags, RegA, Reg32, Reg32), - /// Multiplies values from two float arithmetic registers and puts result into the first + /// Multiplies values from two float arithmetic registers and puts result into the second /// register. #[display("mul.{0} {1}{2},{1}{3}")] MulF(RoundingFlag, RegF, Reg32, Reg32), - /// Divides values from two integer arithmetic registers and puts result into the first + /// Divides values from two integer arithmetic registers and puts result into the second /// register. /// /// Since the division operation may not result in overflow, the overflow flag is used to @@ -462,14 +462,14 @@ pub enum ArithmeticOp { #[display("div.{0} {1}{2},{1}{3}")] DivA(IntFlags, RegA, Reg32, Reg32), - /// Divides values from two float arithmetic registers and puts result into the first register. + /// Divides values from two float arithmetic registers and puts result into the second register. #[display("div.{0} {1}{2},{1}{3}")] DivF(RoundingFlag, RegF, Reg32, Reg32), /// Modulo division. /// /// Puts a reminder of the division of source register on destination register into the - /// the first register. + /// second register. #[display("rem {0}{1},{2}{3}")] Rem(RegA, Reg32, RegA, Reg32), From a5a0f5b172e5886c52073d786a66b0b2b435d9c5 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 20 Apr 2024 10:10:03 +0200 Subject: [PATCH 03/10] lib: make LibId display params match other ids across the ecosystem --- src/isa/instr.rs | 3 ++- src/library/lib.rs | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/isa/instr.rs b/src/isa/instr.rs index 5fb8eaa..98211e5 100644 --- a/src/isa/instr.rs +++ b/src/isa/instr.rs @@ -462,7 +462,8 @@ pub enum ArithmeticOp { #[display("div.{0} {1}{2},{1}{3}")] DivA(IntFlags, RegA, Reg32, Reg32), - /// Divides values from two float arithmetic registers and puts result into the second register. + /// Divides values from two float arithmetic registers and puts result into the second + /// register. #[display("div.{0} {1}{2},{1}{3}")] DivF(RoundingFlag, RegF, Reg32, Reg32), diff --git a/src/library/lib.rs b/src/library/lib.rs index 09e323b..d8bf84b 100644 --- a/src/library/lib.rs +++ b/src/library/lib.rs @@ -32,7 +32,7 @@ use core::str::FromStr; use amplify::confinement::SmallBlob; use amplify::{confinement, ByteArray, Bytes32}; -use baid58::{Baid58ParseError, FromBaid58, ToBaid58}; +use baid58::{Baid58ParseError, Chunking, FromBaid58, ToBaid58, CHUNKING_32}; use sha2::{Digest, Sha256}; use strict_encoding::{StrictDeserialize, StrictSerialize}; @@ -67,7 +67,9 @@ pub struct LibId( impl ToBaid58<32> for LibId { const HRI: &'static str = "alu"; + const CHUNKING: Option = CHUNKING_32; fn to_baid58_payload(&self) -> [u8; 32] { self.to_byte_array() } + fn to_baid58_string(&self) -> String { self.to_string() } } impl FromBaid58<32> for LibId {} @@ -79,10 +81,13 @@ impl FromStr for LibId { } impl Display for LibId { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + if f.alternate() { + f.write_str("urn:ubideco:alu:")?; + } if f.sign_minus() { - write!(f, "urn:ubideco:{::<}", self.to_baid58()) + write!(f, "{:.2}", self.to_baid58()) } else { - write!(f, "urn:ubideco:{::<#}", self.to_baid58()) + write!(f, "{:#.2}", self.to_baid58()) } } } @@ -484,11 +489,13 @@ mod test { let id = LibId::with("FLOAT", b"", b"", &none!()); assert_eq!( format!("{id}"), - "urn:ubideco:alu:GrjjwmeTsibiEeYYtjokmc8j4Jn1KWL2SX8NugG6T5kZ#pinball-eternal-colombo" + "Grjjwm-eTsibiEe-YYtjokmc-8j4Jn1KW-L2SX8Nug-G6T5kZ#pinball-eternal-colombo" ); + assert_eq!(format!("{id:-}"), "Grjjwm-eTsibiEe-YYtjokmc-8j4Jn1KW-L2SX8Nug-G6T5kZ"); assert_eq!( - format!("{id:-}"), - "urn:ubideco:alu:GrjjwmeTsibiEeYYtjokmc8j4Jn1KWL2SX8NugG6T5kZ" + format!("{id:#}"), + "urn:ubideco:alu:Grjjwm-eTsibiEe-YYtjokmc-8j4Jn1KW-L2SX8Nug-G6T5kZ#\ + pinball-eternal-colombo" ); } From c3a5f11f70acd86c9c2b48dc58b5ae6666c0ed79 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 20 Apr 2024 10:23:11 +0200 Subject: [PATCH 04/10] isa: macro asm allow first argument to be constant --- src/isa/macros.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/isa/macros.rs b/src/isa/macros.rs index d157a73..2eb2d04 100644 --- a/src/isa/macros.rs +++ b/src/isa/macros.rs @@ -121,6 +121,10 @@ macro_rules! aluasm_inner { $code.push($crate::instr!{ $op $arglit, $( $arg [ $idx ] ),+ }); $crate::aluasm_inner! { $code => $( $tt )* } }; + { $code:ident => $op:ident $arglit:ident, $( $arg:ident [ $idx:literal ] ),+ ; $($tt:tt)* } => { + $code.push($crate::instr!{ $op $arglit, $( $arg [ $idx ] ),+ }); + $crate::aluasm_inner! { $code => $( $tt )* } + }; { $code:ident => $op:ident . $flag:ident $arglit:literal, $( $arg:ident [ $idx:literal ] ),+ ; $($tt:tt)* } => { $code.push($crate::instr!{ $op . $flag $arglit, $( $arg [ $idx ] ),+ }); $crate::aluasm_inner! { $code => $( $tt )* } From 40751bae7ba35d82deb6247e2195897edba1f98c Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 20 Apr 2024 10:24:49 +0200 Subject: [PATCH 05/10] isa: macro asm allow constants in jump positions --- src/isa/macros.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/isa/macros.rs b/src/isa/macros.rs index 2eb2d04..e89d5f5 100644 --- a/src/isa/macros.rs +++ b/src/isa/macros.rs @@ -97,6 +97,10 @@ macro_rules! aluasm_inner { $code.push($crate::instr!{ $op $arg @ $lib }); $crate::aluasm_inner! { $code => $( $tt )* } }; + { $code:ident => $op:ident $arg:ident @ $lib:ident ; $($tt:tt)* } => { + $code.push($crate::instr!{ $op $arg @ $lib }); + $crate::aluasm_inner! { $code => $( $tt )* } + }; { $code:ident => $op:ident $( $arg:literal ),+ ; $($tt:tt)* } => { $code.push($crate::instr!{ $op $( $arg ),+ }); $crate::aluasm_inner! { $code => $( $tt )* } @@ -159,24 +163,45 @@ macro_rules! instr { (jmp $offset:literal) => { Instr::ControlFlow(ControlFlowOp::Jmp($offset)) }; + (jmp $offset:ident) => { + Instr::ControlFlow(ControlFlowOp::Jmp($offset)) + }; (jif $offset:literal) => { Instr::ControlFlow(ControlFlowOp::Jif($offset)) }; + (jif $offset:ident) => { + Instr::ControlFlow(ControlFlowOp::Jif($offset)) + }; (routine $offset:literal) => { Instr::ControlFlow(ControlFlowOp::Reutine($offset)) }; + (routine $offset:ident) => { + Instr::ControlFlow(ControlFlowOp::Reutine($offset)) + }; (call $offset:literal @ $lib:ident) => { Instr::ControlFlow(ControlFlowOp::Call(LibSite::with( $offset, stringify!($lib).parse().expect("wrong library reference"), ))) }; + (call $offset:ident @ $lib:ident) => { + Instr::ControlFlow(ControlFlowOp::Call(LibSite::with( + $offset, + stringify!($lib).parse().expect("wrong library reference"), + ))) + }; (exec $offset:literal @ $lib:ident) => { Instr::ControlFlow(ControlFlowOp::Exec(LibSite::with( $offset, stringify!($lib).parse().expect("wrong library reference"), ))) }; + (exec $offset:ident @ $lib:ident) => { + Instr::ControlFlow(ControlFlowOp::Exec(LibSite::with( + $offset, + stringify!($lib).parse().expect("wrong library reference"), + ))) + }; (ret) => { Instr::ControlFlow(ControlFlowOp::Ret) }; From 6eabff999a364ce6a33332fd8e1ebe543fd98457 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 20 Apr 2024 10:34:06 +0200 Subject: [PATCH 06/10] isa: change `succ` to `test` opcode --- src/isa/bytecode.rs | 6 +++--- src/isa/exec.rs | 17 +++++++++++------ src/isa/instr.rs | 8 ++++---- src/isa/macros.rs | 4 ++-- src/isa/opcodes.rs | 2 +- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/isa/bytecode.rs b/src/isa/bytecode.rs index 92fda37..bb4a300 100644 --- a/src/isa/bytecode.rs +++ b/src/isa/bytecode.rs @@ -218,7 +218,7 @@ impl Bytecode for ControlFlowOp { fn instr_byte(&self) -> u8 { match self { ControlFlowOp::Fail => INSTR_FAIL, - ControlFlowOp::Succ => INSTR_SUCC, + ControlFlowOp::Test => INSTR_TEST, ControlFlowOp::Jmp(_) => INSTR_JMP, ControlFlowOp::Jif(_) => INSTR_JIF, ControlFlowOp::Routine(_) => INSTR_ROUTINE, @@ -242,7 +242,7 @@ impl Bytecode for ControlFlowOp { { match self { ControlFlowOp::Fail => {} - ControlFlowOp::Succ => {} + ControlFlowOp::Test => {} ControlFlowOp::Jmp(pos) | ControlFlowOp::Jif(pos) | ControlFlowOp::Routine(pos) => { writer.write_u16(*pos)? } @@ -261,7 +261,7 @@ impl Bytecode for ControlFlowOp { { Ok(match reader.read_u8()? { INSTR_FAIL => Self::Fail, - INSTR_SUCC => Self::Succ, + INSTR_TEST => Self::Test, INSTR_JMP => Self::Jmp(reader.read_u16()?), INSTR_JIF => Self::Jif(reader.read_u16()?), INSTR_ROUTINE => Self::Routine(reader.read_u16()?), diff --git a/src/isa/exec.rs b/src/isa/exec.rs index 42b6f56..4d54532 100644 --- a/src/isa/exec.rs +++ b/src/isa/exec.rs @@ -232,9 +232,12 @@ impl InstructionSet for ControlFlowOp { regs.st0 = false; ExecStep::Stop } - ControlFlowOp::Succ => { - regs.st0 = true; - ExecStep::Stop + ControlFlowOp::Test => { + if regs.st0 { + ExecStep::Next + } else { + ExecStep::Stop + } } ControlFlowOp::Jmp(offset) => { regs.jmp().map(|_| ExecStep::Jump(*offset)).unwrap_or(ExecStep::Stop) @@ -1775,7 +1778,9 @@ mod tests { assert_eq!(register.get_n(RegA::A16, Reg32::Reg1), MaybeNumber::none()); assert_eq!(register.get_n(RegA::A16, Reg32::Reg2), MaybeNumber::none()); assert!(!register.st0); - ControlFlowOp::Succ.exec(&mut register, lib_site, &()); + CmpOp::StInv.exec(&mut register, lib_site, &()); + assert!(register.st0); + ControlFlowOp::Test.exec(&mut register, lib_site, &()); let s1 = [0u8; u16::MAX as usize]; let s2 = [0u8; u16::MAX as usize]; @@ -1903,8 +1908,8 @@ mod tests { &(), ); assert!(!register.st0); - ControlFlowOp::Succ.exec(&mut register, lib_site, &()); - assert!(register.st0); + ControlFlowOp::Test.exec(&mut register, lib_site, &()); + assert!(!register.st0); CmpOp::EqR(NoneEqFlag::NonEqual, RegR::R512, Reg32::Reg0, Reg32::Reg2).exec( &mut register, lib_site, diff --git a/src/isa/instr.rs b/src/isa/instr.rs index 98211e5..b67b09d 100644 --- a/src/isa/instr.rs +++ b/src/isa/instr.rs @@ -115,10 +115,10 @@ pub enum ControlFlowOp { #[display("fail")] Fail, - /// Completes program execution writing `true` to `st0` (indicating program success). Does not - /// modify value of call stack registers. - #[display("succ")] - Succ, + /// Checks the value of `st0` register. If the value is `false`, stops execution of the + /// program. Otherwise, it is a no-operation. + #[display("test")] + Test, /// Unconditionally jumps to an offset. Increments `cy0`. #[display("jmp {0:#06X}")] diff --git a/src/isa/macros.rs b/src/isa/macros.rs index e89d5f5..6aa7ee7 100644 --- a/src/isa/macros.rs +++ b/src/isa/macros.rs @@ -157,8 +157,8 @@ macro_rules! instr { (fail) => { Instr::ControlFlow(ControlFlowOp::Fail) }; - (succ) => { - Instr::ControlFlow(ControlFlowOp::Succ) + (test) => { + Instr::ControlFlow(ControlFlowOp::Test) }; (jmp $offset:literal) => { Instr::ControlFlow(ControlFlowOp::Jmp($offset)) diff --git a/src/isa/opcodes.rs b/src/isa/opcodes.rs index 75385f8..46f1bf4 100644 --- a/src/isa/opcodes.rs +++ b/src/isa/opcodes.rs @@ -26,7 +26,7 @@ // Control-flow instructions pub const INSTR_FAIL: u8 = 0b00_000_000; -pub const INSTR_SUCC: u8 = 0b00_000_001; +pub const INSTR_TEST: u8 = 0b00_000_001; pub const INSTR_JMP: u8 = 0b00_000_010; pub const INSTR_JIF: u8 = 0b00_000_011; pub const INSTR_ROUTINE: u8 = 0b00_000_100; From 888764cdc425414cf59398e03ea76613acd66157 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 20 Apr 2024 12:46:51 +0200 Subject: [PATCH 07/10] isa: macro asm support constant ident in put argument --- src/isa/macros.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/isa/macros.rs b/src/isa/macros.rs index 6aa7ee7..4aab582 100644 --- a/src/isa/macros.rs +++ b/src/isa/macros.rs @@ -145,6 +145,10 @@ macro_rules! aluasm_inner { $code.push($crate::instr!{ $op $arg [ $idx ] , $arglit }); $crate::aluasm_inner! { $code => $( $tt )* } }; + { $code:ident => $op:ident $arg:ident [ $idx:literal ] , $arglit:ident ; $($tt:tt)* } => { + $code.push($crate::instr!{ $op $arg [ $idx ] , $arglit }); + $crate::aluasm_inner! { $code => $( $tt )* } + }; { $code:ident => $op:ident . $flag:ident $arg:ident [ $idx:literal ], $arglit:expr ; $($tt:tt)* } => { $code.push($crate::instr!{ $op . $flag $arg [ $idx ], $arglit }); $crate::aluasm_inner! { $code => $( $tt )* } @@ -221,6 +225,9 @@ macro_rules! instr { $crate::_reg_idx16!($offset_idx), )) }; + (put s16[$idx:literal], $val:ident) => {{ + Instr::Bytes(BytesOp::Put(RegS::from($idx), Box::new(ByteStr::with(&$val)), false)) + }}; (put s16[$idx:literal], $val:literal) => {{ Instr::Bytes(BytesOp::Put(RegS::from($idx), Box::new(ByteStr::with(&$val)), false)) }}; @@ -281,6 +288,12 @@ macro_rules! instr { num.reshape(reg.layout()); Instr::Put($crate::_reg_sfx!(PutOp, Put, $reg)(reg, $crate::_reg_idx!($idx), Box::new(num))) }}; + (put $reg:ident[$idx:literal], $val:ident) => {{ + let mut num = MaybeNumber::from($val); + let reg = $crate::_reg_ty!(Reg, $reg); + num.reshape(reg.layout()); + Instr::Put($crate::_reg_sfx!(PutOp, Put, $reg)(reg, $crate::_reg_idx!($idx), Box::new(num))) + }}; (putif $reg:ident[$idx:literal], $val:literal) => {{ let s = stringify!($val); let mut num = s.parse::().expect(&format!("invalid number literal `{}`", s)); @@ -292,6 +305,16 @@ macro_rules! instr { Box::new(num), )) }}; + (putif $reg:ident[$idx:literal], $val:ident) => {{ + let mut num = MaybeNumber::from($val); + let reg = $crate::_reg_ty!(Reg, $reg); + num.reshape(reg.layout()); + Instr::Put($crate::_reg_sfx!(PutOp, PutIf, $reg)( + reg, + $crate::_reg_idx!($idx), + Box::new(num), + )) + }}; (swp $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal]) => {{ if $crate::_reg_ty!(Reg, $reg1) != $crate::_reg_ty!(Reg, $reg2) { From dc1f0aab525f593628e510065ac1e05b75a51d6e Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 20 Apr 2024 13:53:32 +0200 Subject: [PATCH 08/10] isa: macro asm allow lib refs with variables --- src/isa/macros.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/isa/macros.rs b/src/isa/macros.rs index 4aab582..afc213f 100644 --- a/src/isa/macros.rs +++ b/src/isa/macros.rs @@ -93,7 +93,7 @@ macro_rules! aluasm_inner { $code.push($crate::instr!{ $op }); $crate::aluasm_inner! { $code => $( $tt )* } }; - { $code:ident => $op:ident $arg:literal @ $lib:ident ; $($tt:tt)* } => { + { $code:ident => $op:ident $arg:literal @ $lib:literal ; $($tt:tt)* } => { $code.push($crate::instr!{ $op $arg @ $lib }); $crate::aluasm_inner! { $code => $( $tt )* } }; @@ -182,28 +182,28 @@ macro_rules! instr { (routine $offset:ident) => { Instr::ControlFlow(ControlFlowOp::Reutine($offset)) }; - (call $offset:literal @ $lib:ident) => { + (call $offset:literal @ $lib:literal) => { Instr::ControlFlow(ControlFlowOp::Call(LibSite::with( $offset, - stringify!($lib).parse().expect("wrong library reference"), + $lib.parse().expect("wrong library reference"), ))) }; (call $offset:ident @ $lib:ident) => { Instr::ControlFlow(ControlFlowOp::Call(LibSite::with( $offset, - stringify!($lib).parse().expect("wrong library reference"), + $lib ))) }; - (exec $offset:literal @ $lib:ident) => { + (exec $offset:literal @ $lib:literal) => { Instr::ControlFlow(ControlFlowOp::Exec(LibSite::with( $offset, - stringify!($lib).parse().expect("wrong library reference"), + $lib.parse().expect("wrong library reference"), ))) }; (exec $offset:ident @ $lib:ident) => { Instr::ControlFlow(ControlFlowOp::Exec(LibSite::with( $offset, - stringify!($lib).parse().expect("wrong library reference"), + $lib ))) }; (ret) => { From 3c4d6c27d55505bbc7cfc50a125c75f5903b9fe5 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 22 Apr 2024 16:49:01 +0200 Subject: [PATCH 09/10] isa: improve Extr and Inj ops --- src/isa/bytecode.rs | 12 ++++++------ src/isa/instr.rs | 10 +++++----- src/isa/macros.rs | 14 +++++++++++--- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/isa/bytecode.rs b/src/isa/bytecode.rs index bb4a300..40b525a 100644 --- a/src/isa/bytecode.rs +++ b/src/isa/bytecode.rs @@ -1043,8 +1043,8 @@ impl Bytecode for BytesOp { writer.write_bool(false)?; } BytesOp::Extr(src, dst, index, offset) | BytesOp::Inj(src, dst, index, offset) => { - writer.write_u5(src)?; - writer.write_u3(dst)?; + writer.write_u4(src)?; + writer.write_u4(dst)?; writer.write_u4(index)?; writer.write_u4(offset)?; } @@ -1126,14 +1126,14 @@ impl Bytecode for BytesOp { op } INSTR_EXTR => Self::Extr( - reader.read_u5()?.into(), - reader.read_u3()?.into(), + reader.read_u4()?.into(), + reader.read_u4()?.into(), reader.read_u4()?.into(), reader.read_u4()?.into(), ), INSTR_INJ => Self::Inj( - reader.read_u5()?.into(), - reader.read_u3()?.into(), + reader.read_u4()?.into(), + reader.read_u4()?.into(), reader.read_u4()?.into(), reader.read_u4()?.into(), ), diff --git a/src/isa/instr.rs b/src/isa/instr.rs index b67b09d..8979e26 100644 --- a/src/isa/instr.rs +++ b/src/isa/instr.rs @@ -698,18 +698,18 @@ pub enum BytesOp { /// If the source string register - or offset register is uninitialized, sets destination to /// uninitialized state and `st0` to `false`. #[display("extr {0},{1}{2},a16{3}")] - Extr(/** `s` register index */ RegS, RegR, Reg16, /** `a16` register with offset */ Reg16), + Extr(/** `s` register index */ RegS, RegAR, Reg16, /** `a16` register with offset */ Reg16), /// Inject general `R` register value at a given position to string register, replacing value /// of the corresponding bytes. If the insert offset is larger than the current length of the /// string, the length is extended and all bytes inbetween previous length and the new length /// are initialized with zeros. If the length of the inserted string plus insert offset exceeds - /// the maximum string register length (2^16 bytes), than the destination register is set to + /// the maximum string register length (2^16 bytes), then the destination register is set to /// `None` state and `st0` is set to `false`. Otherwise, `st0` value is not modified. #[display("inj {0},{1}{2},{1}{3}")] Inj( /** `s` register index acting as the source and destination */ RegS, - RegR, + RegAR, Reg16, /** `a16` register with offset */ Reg16, ), @@ -754,7 +754,7 @@ pub enum BytesOp { /// Rule on `st0` changes: if at least one of the destination registers is set to `None`, or /// `offset` value exceeds source string length, `st0` is set to `false`; otherwise its value /// is not modified - #[display("splt.{2} {0},a16{1},{3},{4}")] + #[display("splt.{0} {2},a16{1},{3},{4}")] Splt( SplitFlag, /** `a16` register index with offset value */ Reg32, @@ -792,7 +792,7 @@ pub enum BytesOp { /// /// /// In all of these cases `st0` is set to `false`. Otherwise, `st0` value is not modified. - #[display("ins.{3} {0},{1},a16{2}")] + #[display("ins.{0} {1},a16{2},{2}")] Ins( InsertFlag, /** `a16` register index with offset value for insert location */ Reg32, diff --git a/src/isa/macros.rs b/src/isa/macros.rs index afc213f..74cbde3 100644 --- a/src/isa/macros.rs +++ b/src/isa/macros.rs @@ -217,11 +217,19 @@ macro_rules! instr { )) }; - (extr s16[$idx:literal], $regr:ident[$regr_idx:literal],a16[$offset_idx:literal]) => { + (extr s16[$idx:literal], $reg:ident[$reg_idx:literal], a16[$offset_idx:literal]) => { Instr::Bytes(BytesOp::Extr( RegS::from($idx), - $crate::_reg_ty!(Reg, $regr), - $crate::_reg_idx16!($regr_idx), + $crate::_reg_ty!(Reg, $reg), + $crate::_reg_idx16!($reg_idx), + $crate::_reg_idx16!($offset_idx), + )) + }; + (inj s16[$idx:literal], $reg:ident[$reg_idx:literal], a16[$offset_idx:literal]) => { + Instr::Bytes(BytesOp::Inj( + RegS::from($idx), + $crate::_reg_ty!(Reg, $reg), + $crate::_reg_idx16!($reg_idx), $crate::_reg_idx16!($offset_idx), )) }; From 4058c09640de6419a55022c43420c56f08caf897 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 22 Apr 2024 16:56:51 +0200 Subject: [PATCH 10/10] isa: asm fix RegAR macro --- src/isa/exec.rs | 2 +- src/isa/macros.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/isa/exec.rs b/src/isa/exec.rs index 4d54532..ffc05d2 100644 --- a/src/isa/exec.rs +++ b/src/isa/exec.rs @@ -1320,7 +1320,7 @@ impl InstructionSet for BytesOp { let offset = regs.a16[*offset as u8 as usize].filter(|e| *e < s_len)?; let end = offset .checked_add(dst.layout().bytes()) - .filter(|e| *e < s_len) + .filter(|e| *e <= s_len) .unwrap_or_else(|| { regs.st0 = false; s_len diff --git a/src/isa/macros.rs b/src/isa/macros.rs index 74cbde3..810508f 100644 --- a/src/isa/macros.rs +++ b/src/isa/macros.rs @@ -71,7 +71,7 @@ macro_rules! aluasm_isa { MergeFlag, MoveOp, PutOp, RoundingFlag, Secp256k1Op, SignFlag, NoneEqFlag }; use ::aluvm::reg::{ - Reg16, Reg32, Reg8, RegA, RegA2, RegBlockAFR, RegBlockAR, RegF, RegR, RegS, + Reg16, Reg32, Reg8, RegA, RegA2, RegAR, RegBlockAFR, RegBlockAR, RegF, RegR, RegS, NumericRegister, }; use ::aluvm::library::LibSite; @@ -220,7 +220,7 @@ macro_rules! instr { (extr s16[$idx:literal], $reg:ident[$reg_idx:literal], a16[$offset_idx:literal]) => { Instr::Bytes(BytesOp::Extr( RegS::from($idx), - $crate::_reg_ty!(Reg, $reg), + $crate::_reg_tyar!($reg), $crate::_reg_idx16!($reg_idx), $crate::_reg_idx16!($offset_idx), )) @@ -228,7 +228,7 @@ macro_rules! instr { (inj s16[$idx:literal], $reg:ident[$reg_idx:literal], a16[$offset_idx:literal]) => { Instr::Bytes(BytesOp::Inj( RegS::from($idx), - $crate::_reg_ty!(Reg, $reg), + $crate::_reg_tyar!($reg), $crate::_reg_idx16!($reg_idx), $crate::_reg_idx16!($offset_idx), )) @@ -1355,6 +1355,60 @@ macro_rules! _reg_tyr { }; } +#[doc(hidden)] +#[macro_export] +macro_rules! _reg_tyar { + (a8) => { + RegAR::A(RegA::A8) + }; + (a16) => { + RegAR::A(RegA::A16) + }; + (a32) => { + RegAR::A(RegA::A32) + }; + (a64) => { + RegAR::A(RegA::A64) + }; + (a128) => { + RegAR::A(RegA::A128) + }; + (a256) => { + RegAR::A(RegA::A256) + }; + (a512) => { + RegAR::A(RegA::A512) + }; + (a1024) => { + RegAR::A(RegA::A1024) + }; + + (r128) => { + RegAR::R(RegR::R128) + }; + (r160) => { + RegAR::R(RegR::R160) + }; + (r256) => { + RegAR::R(RegR::R256) + }; + (r512) => { + RegAR::R(RegR::R512) + }; + (r1024) => { + RegAR::R(RegR::R1024) + }; + (r2048) => { + RegAR::R(RegR::R2048) + }; + (r4096) => { + RegAR::R(RegR::R4096) + }; + (r8192) => { + RegAR::R(RegR::R8192) + }; +} + #[doc(hidden)] #[macro_export] macro_rules! _reg_idx {