diff --git a/examples/asm.rs b/examples/asm.rs index 16ec639..8229b19 100644 --- a/examples/asm.rs +++ b/examples/asm.rs @@ -16,9 +16,9 @@ use aluvm::{aluasm, Prog, Vm}; fn main() { let code = aluasm! { clr r1024[5] ; - put 5,a16[8] ; - putif 0xaf67937b5498dc,r256[1] ; - putif 13,a8[1] ; + put a16[8],5 ; + putif r256[1],0xaf67937b5498dc ; + putif a8[1],13 ; swp a8[1],a8[2] ; swp f256[8],f256[7] ; dup a256[1],a256[7] ; @@ -40,24 +40,24 @@ fn main() { ifz r2048[17] ; inv st0 ; st.s a8[1] ; - put 13,a32[12] ; - put 66,a32[13] ; + put a32[12],13 ; + put a32[13],66 ; add.uc a32[12],a32[13] ; add.sw a32[12],a32[13] ; sub.sc a32[13],a32[12] ; mul.uw a32[12],a32[13] ; div.cu a32[12],a32[13] ; - put 2.13,f32[12] ; - put 5.18,f32[13] ; + put f32[12],2.13 ; + put f32[13],5.18 ; add.z f32[12],f32[13] ; sub.n f32[13],f32[12] ; mul.c f32[12],f32[13] ; div.f f32[12],f32[13] ; - rem a64[8],a8[2] ; + rem a8[2],a64[8] ; inc a16[3] ; - add 5,a16[4] ; + add a16[4],5 ; dec a16[8] ; - sub 82,a16[4] ; + sub a16[4],82 ; neg a64[15] ; abs f128[11] ; and a32[5],a32[6],a32[5] ; @@ -69,14 +69,14 @@ fn main() { scr r256[24],a16[22] ; scl r256[24],a16[22] ; rev a512[28] ; - ripemd s16[9],r160[7] ; - sha2 s16[19],r256[2] ; - secpgen r256[1],r512[1] ; + ripemd r160[7],s16[9] ; + sha2 r256[2],s16[19] ; + secpgen r512[1],r256[1] ; dup r512[1],r512[22] ; spy a512[1],r512[22] ; secpmul r256[1],r512[1],r512[2] ; - secpadd r512[22],r512[1] ; - secpneg r512[1],r512[3] ; + secpadd r512[1],r512[22] ; + secpneg r512[3],r512[1] ; ifz a16[8] ; jif 190 ; call 56 @ alu07EnUZgFtu28sWqqH3womkTopXCkgAGsCLvLnYvNcPLRt ; diff --git a/src/data/byte_str.rs b/src/data/byte_str.rs index 5a658f4..cf961d0 100644 --- a/src/data/byte_str.rs +++ b/src/data/byte_str.rs @@ -137,16 +137,20 @@ impl ByteStr { #[inline] pub fn is_empty(&self) -> bool { self.len == 0 } - /// Adjusts the length of the string if necessary + /// Adjusts the length of the string #[inline] pub fn adjust_len(&mut self, new_len: u16) { self.len = new_len } + /// Extends the length of the string if necessary + #[inline] + pub fn extend_len(&mut self, new_len: u16) { self.len = new_len.max(self.len) } + /// Fills range within a string with the provided byte value, increasing string length if /// necessary pub fn fill(&mut self, range: Range, val: u8) { let start = range.start; let end = range.end; - self.adjust_len(end); + self.extend_len(end); self.bytes[start as usize..end as usize].fill(val); } diff --git a/src/isa/asm.rs b/src/isa/asm.rs index f1dc60d..57e596d 100644 --- a/src/isa/asm.rs +++ b/src/isa/asm.rs @@ -32,8 +32,8 @@ /// /// let code = aluasm! { /// clr r1024[5] ; -/// put 378,a16[8] ; -/// putif 0xaf67937b5498dc,r128[5] ; +/// put a16[8],378 ; +/// putif r128[5],0xaf67937b5498dc ; /// swp a8[1],a8[2] ; /// swp f256[8],f256[7] ; /// dup a256[1],a256[7] ; @@ -63,7 +63,7 @@ macro_rules! aluasm { use std::boxed::Box; use $crate::isa::{ - ArithmeticOp, BitwiseOp, BytesOp, CmpOp, ControlFlowOp, DigestOp, FloatEqFlag, Instr, IntFlags, + ArithmeticOp, BitwiseOp, BytesOp, CmpOp, ControlFlowOp, DigestOp, ExtendFlag, FloatEqFlag, Instr, IntFlags, MergeFlag, MoveOp, ReservedOp, PutOp, RoundingFlag, Secp256k1Op, SignFlag, NoneEqFlag, }; use $crate::reg::{ @@ -113,10 +113,6 @@ macro_rules! aluasm_inner { $code.push($crate::instr!{ $op . $flag $( $arg [ $idx ] ),+ }); $crate::aluasm_inner! { $code => $( $tt )* } }; - { $code:ident => $op:ident $arglit:literal , $arg:ident [ $idx:literal ] ; $($tt:tt)* } => { - $code.push($crate::instr!{ $op $arglit , $arg [ $idx ] }); - $crate::aluasm_inner! { $code => $( $tt )* } - }; { $code:ident => $op:ident $arg:ident [ $idx:literal ] , $arglit:literal ; $($tt:tt)* } => { $code.push($crate::instr!{ $op $arg [ $idx ] , $arglit }); $crate::aluasm_inner! { $code => $( $tt )* } @@ -168,7 +164,7 @@ macro_rules! instr { )) }; - (extr s16[$idx:literal], $regr:ident[$regr_idx:literal],a16[$offset_idx:literal]) => { + (extr $regr:ident[$regr_idx:literal],s16[$idx:literal],a16[$offset_idx:literal]) => { Instr::Bytes(BytesOp::Extr( RegS::from($idx), $crate::_reg_ty!(Reg, $regr), @@ -177,16 +173,34 @@ macro_rules! instr { )) }; (put s16[$idx:literal], $val:literal) => {{ - Instr::Bytes(BytesOp::Put(RegS::from($idx), Box::new(ByteStr::with($val)), false)) + Instr::Bytes(BytesOp::Put(RegS::from($idx), Box::new(ByteStr::with(&$val)), false)) + }}; + (fill.e s16[$idx0:literal],a16[$idx1:literal],a16[$idx2:literal],a8[$idx3:literal]) => {{ + Instr::Bytes(BytesOp::Fill( + RegS::from($idx0), + $crate::_reg_idx!($idx1), + $crate::_reg_idx!($idx2), + $crate::_reg_idx!($idx3), + ExtendFlag::Extend, + )) }}; - (put $val:literal, $reg:ident[$idx:literal]) => {{ + (fill.f s16[$idx0:literal],a16[$idx1:literal],a16[$idx2:literal],a8[$idx3:literal]) => {{ + Instr::Bytes(BytesOp::Fill( + RegS::from($idx0), + $crate::_reg_idx!($idx1), + $crate::_reg_idx!($idx2), + $crate::_reg_idx!($idx3), + ExtendFlag::Fail, + )) + }}; + (put $reg:ident[$idx:literal], $val:literal) => {{ let s = stringify!($val); let mut num = s.parse::().expect(&format!("invalid number literal `{}`", s)); 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 $val:literal, $reg:ident[$idx:literal]) => {{ + (putif $reg:ident[$idx:literal], $val:literal) => {{ let s = stringify!($val); let mut num = s.parse::().expect(&format!("invalid number literal `{}`", s)); let reg = $crate::_reg_ty!(Reg, $reg); @@ -208,79 +222,79 @@ macro_rules! instr { $crate::_reg_idx!($idx2), )) }}; - (mov $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal]) => {{ - if $crate::_reg_ty!(Reg, $reg1) != $crate::_reg_ty!(Reg, $reg2) { + (mov $dst_reg:ident[$dst_idx:literal], $src_reg:ident[$src_idx:literal]) => {{ + if $crate::_reg_ty!(Reg, $src_reg) != $crate::_reg_ty!(Reg, $dst_reg) { panic!("Move operation must be performed between registers of the same type"); } - Instr::Move($crate::_reg_sfx!(MoveOp, Mov, $reg1)( - $crate::_reg_ty!(Reg, $reg1), - $crate::_reg_idx!($idx1), - $crate::_reg_idx!($idx2), + Instr::Move($crate::_reg_sfx!(MoveOp, Mov, $src_reg)( + $crate::_reg_ty!(Reg, $src_reg), + $crate::_reg_idx!($src_idx), + $crate::_reg_idx!($dst_idx), )) }}; - (dup $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal]) => {{ - if $crate::_reg_ty!(Reg, $reg1) != $crate::_reg_ty!(Reg, $reg2) { + (dup $dst_reg:ident[$dst_idx:literal], $src_reg:ident[$src_idx:literal]) => {{ + if $crate::_reg_ty!(Reg, $src_reg) != $crate::_reg_ty!(Reg, $dst_reg) { panic!("Dup operation must be performed between registers of the same type"); } - Instr::Move($crate::_reg_sfx!(MoveOp, Dup, $reg1)( - $crate::_reg_ty!(Reg, $reg1), - $crate::_reg_idx!($idx1), - $crate::_reg_idx!($idx2), + Instr::Move($crate::_reg_sfx!(MoveOp, Dup, $src_reg)( + $crate::_reg_ty!(Reg, $src_reg), + $crate::_reg_idx!($src_idx), + $crate::_reg_idx!($dst_idx), )) }}; - (cpy $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal]) => {{ - if $crate::_reg_ty!(Reg, $reg1) != $crate::_reg_ty!(Reg, $reg2) { + (cpy $dst_reg:ident[$dst_idx:literal], $src_reg:ident[$src_idx:literal]) => {{ + if $crate::_reg_ty!(Reg, $src_reg) != $crate::_reg_ty!(Reg, $dst_reg) { panic!("Copy operation must be performed between registers of the same type"); } - Instr::Move($crate::_reg_sfx!(MoveOp, Cpy, $reg1)( - $crate::_reg_ty!(Reg, $reg1), - $crate::_reg_idx!($idx1), - $crate::_reg_ty!(Reg, $reg2), - $crate::_reg_idx!($idx2), + Instr::Move($crate::_reg_sfx!(MoveOp, Cpy, $src_reg)( + $crate::_reg_ty!(Reg, $src_reg), + $crate::_reg_idx!($src_idx), + $crate::_reg_ty!(Reg, $dst_reg), + $crate::_reg_idx!($dst_idx), )) }}; - (cnv $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal]) => {{ - match ($crate::_reg_block!($reg1), $crate::_reg_block!($reg2)) { + (cnv $dst_reg:ident[$dst_idx:literal], $src_reg:ident[$src_idx:literal]) => {{ + match ($crate::_reg_block!($src_reg), $crate::_reg_block!($dst_reg)) { (RegBlockAFR::A, RegBlockAFR::F) => Instr::Move(MoveOp::CnvAF( - $crate::_reg_tya!(Reg, $reg1), - $crate::_reg_idx!($idx1), - $crate::_reg_tyf!(Reg, $reg2), - $crate::_reg_idx!($idx2), + $crate::_reg_tya!(Reg, $src_reg), + $crate::_reg_idx!($src_idx), + $crate::_reg_tyf!(Reg, $dst_reg), + $crate::_reg_idx!($dst_idx), )), (RegBlockAFR::F, RegBlockAFR::A) => Instr::Move(MoveOp::CnvFA( - $crate::_reg_tyf!(Reg, $reg1), - $crate::_reg_idx!($idx1), - $crate::_reg_tya!(Reg, $reg2), - $crate::_reg_idx!($idx2), + $crate::_reg_tyf!(Reg, $src_reg), + $crate::_reg_idx!($src_idx), + $crate::_reg_tya!(Reg, $dst_reg), + $crate::_reg_idx!($dst_idx), )), (RegBlockAFR::A, RegBlockAFR::A) => Instr::Move(MoveOp::CnvA( - $crate::_reg_tya!(Reg, $reg1), - $crate::_reg_idx!($idx1), - $crate::_reg_tya!(Reg, $reg1), - $crate::_reg_idx!($idx2), + $crate::_reg_tya!(Reg, $src_reg), + $crate::_reg_idx!($src_idx), + $crate::_reg_tya!(Reg, $src_reg), + $crate::_reg_idx!($dst_idx), )), (RegBlockAFR::F, RegBlockAFR::F) => Instr::Move(MoveOp::CnvF( - $crate::_reg_tyf!(Reg, $reg1), - $crate::_reg_idx!($idx1), - $crate::_reg_tyf!(Reg, $reg1), - $crate::_reg_idx!($idx2), + $crate::_reg_tyf!(Reg, $src_reg), + $crate::_reg_idx!($src_idx), + $crate::_reg_tyf!(Reg, $src_reg), + $crate::_reg_idx!($dst_idx), )), (_, _) => panic!("Conversion operation between unsupported register types"), } }}; - (spy $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal]) => {{ - match ($crate::_reg_block!($reg1), $crate::_reg_block!($reg2)) { + (spy $dst_reg:ident[$dst_idx:literal], $src_reg:ident[$src_idx:literal]) => {{ + match ($crate::_reg_block!($src_reg), $crate::_reg_block!($dst_reg)) { (RegBlockAFR::A, RegBlockAFR::R) => Instr::Move(MoveOp::SpyAR( - $crate::_reg_tya!(Reg, $reg1), - $crate::_reg_idx!($idx1), - $crate::_reg_tyr!(Reg, $reg2), - $crate::_reg_idx!($idx2), + $crate::_reg_tya!(Reg, $src_reg), + $crate::_reg_idx!($src_idx), + $crate::_reg_tyr!(Reg, $dst_reg), + $crate::_reg_idx!($dst_idx), )), (RegBlockAFR::R, RegBlockAFR::A) => Instr::Move(MoveOp::SpyAR( - $crate::_reg_tya!(Reg, $reg2), - $crate::_reg_idx!($idx2), - $crate::_reg_tyr!(Reg, $reg1), - $crate::_reg_idx!($idx1), + $crate::_reg_tya!(Reg, $dst_reg), + $crate::_reg_idx!($dst_idx), + $crate::_reg_tyr!(Reg, $src_reg), + $crate::_reg_idx!($src_idx), )), (_, _) => { panic!("Swap-conversion operation is supported only between A and R registers") @@ -464,7 +478,7 @@ macro_rules! instr { $crate::_reg_idx!($idx2), )) }}; - (cmp s16[$idx1:literal],s16[$idx2:literal]) => {{ + (eq s16[$idx1:literal],s16[$idx2:literal]) => {{ Instr::Bytes(BytesOp::Eq(RegS::from($idx1), RegS::from($idx2))) }}; (ifn $reg:ident[$idx:literal]) => { @@ -500,101 +514,101 @@ macro_rules! instr { Instr::Cmp(CmpOp::StInv) }; - (add. $flag:ident $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal]) => { - match ($crate::_reg_block!($reg1), $crate::_reg_block!($reg2)) { + (add. $flag:ident $dst_reg:ident[$dst_idx:literal], $reg1:ident[$idx1:literal]) => { + match ($crate::_reg_block!($reg1), $crate::_reg_block!($dst_reg)) { (RegBlockAFR::A, RegBlockAFR::A) => Instr::Arithmetic(ArithmeticOp::AddA( $crate::_int_flags!($flag), $crate::_reg_tya!(Reg, $reg1), $crate::_reg_idx!($idx1), - $crate::_reg_idx!($idx2), + $crate::_reg_idx!($dst_idx), )), (RegBlockAFR::F, RegBlockAFR::F) => Instr::Arithmetic(ArithmeticOp::AddF( $crate::_rounding_flag!($flag), $crate::_reg_tyf!(Reg, $reg1), $crate::_reg_idx!($idx1), - $crate::_reg_idx!($idx2), + $crate::_reg_idx!($dst_idx), )), (a, b) if a == b => panic!("addition requires integer or float registers"), - (_, _) if $crate::_reg_ty!(Reg, $reg1) != $crate::_reg_ty!(Reg, $reg2) => { + (_, _) if $crate::_reg_ty!(Reg, $reg1) != $crate::_reg_ty!(Reg, $dst_reg) => { panic!("addition must be performed between registers of the same size") } (_, _) => panic!("addition must be performed between registers of the same type"), } }; - (sub. $flag:ident $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal]) => { - match ($crate::_reg_block!($reg1), $crate::_reg_block!($reg2)) { + (sub. $flag:ident $dst_reg:ident[$dst_idx:literal], $reg1:ident[$idx1:literal]) => { + match ($crate::_reg_block!($reg1), $crate::_reg_block!($dst_reg)) { (RegBlockAFR::A, RegBlockAFR::A) => Instr::Arithmetic(ArithmeticOp::SubA( $crate::_int_flags!($flag), $crate::_reg_tya!(Reg, $reg1), $crate::_reg_idx!($idx1), - $crate::_reg_idx!($idx2), + $crate::_reg_idx!($dst_idx), )), (RegBlockAFR::F, RegBlockAFR::F) => Instr::Arithmetic(ArithmeticOp::SubF( $crate::_rounding_flag!($flag), $crate::_reg_tyf!(Reg, $reg1), $crate::_reg_idx!($idx1), - $crate::_reg_idx!($idx2), + $crate::_reg_idx!($dst_idx), )), (a, b) if a == b => panic!("subtraction requires integer or float registers"), - (_, _) if $crate::_reg_ty!(Reg, $reg1) != $crate::_reg_ty!(Reg, $reg2) => { + (_, _) if $crate::_reg_ty!(Reg, $reg1) != $crate::_reg_ty!(Reg, $dst_reg) => { panic!("subtraction must be performed between registers of the same size") } (_, _) => panic!("subtraction must be performed between registers of the same type"), } }; - (mul. $flag:ident $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal]) => { - match ($crate::_reg_block!($reg1), $crate::_reg_block!($reg2)) { + (mul. $flag:ident $dst_reg:ident[$dst_idx:literal], $reg1:ident[$idx1:literal]) => { + match ($crate::_reg_block!($reg1), $crate::_reg_block!($dst_reg)) { (RegBlockAFR::A, RegBlockAFR::A) => Instr::Arithmetic(ArithmeticOp::MulA( $crate::_int_flags!($flag), $crate::_reg_tya!(Reg, $reg1), $crate::_reg_idx!($idx1), - $crate::_reg_idx!($idx2), + $crate::_reg_idx!($dst_idx), )), (RegBlockAFR::F, RegBlockAFR::F) => Instr::Arithmetic(ArithmeticOp::MulF( $crate::_rounding_flag!($flag), $crate::_reg_tyf!(Reg, $reg1), $crate::_reg_idx!($idx1), - $crate::_reg_idx!($idx2), + $crate::_reg_idx!($dst_idx), )), (a, b) if a == b => panic!("multiplication requires integer or float registers"), - (_, _) if $crate::_reg_ty!(Reg, $reg1) != $crate::_reg_ty!(Reg, $reg2) => { + (_, _) if $crate::_reg_ty!(Reg, $reg1) != $crate::_reg_ty!(Reg, $dst_reg) => { panic!("multiplication must be performed between registers of the same size") } (_, _) => panic!("multiplication must be performed between registers of the same type"), } }; - (div. $flag:ident $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal]) => { - match ($crate::_reg_block!($reg1), $crate::_reg_block!($reg2)) { + (div. $flag:ident $dst_reg:ident[$dst_idx:literal], $reg1:ident[$idx1:literal]) => { + match ($crate::_reg_block!($reg1), $crate::_reg_block!($dst_reg)) { (RegBlockAFR::A, RegBlockAFR::A) => Instr::Arithmetic(ArithmeticOp::DivA( $crate::_int_flags!($flag), $crate::_reg_tya!(Reg, $reg1), $crate::_reg_idx!($idx1), - $crate::_reg_idx!($idx2), + $crate::_reg_idx!($dst_idx), )), (RegBlockAFR::F, RegBlockAFR::F) => Instr::Arithmetic(ArithmeticOp::DivF( $crate::_rounding_flag!($flag), $crate::_reg_tyf!(Reg, $reg1), $crate::_reg_idx!($idx1), - $crate::_reg_idx!($idx2), + $crate::_reg_idx!($dst_idx), )), (a, b) if a == b => panic!("division requires integer or float registers"), - (_, _) if $crate::_reg_ty!(Reg, $reg1) != $crate::_reg_ty!(Reg, $reg2) => { + (_, _) if $crate::_reg_ty!(Reg, $reg1) != $crate::_reg_ty!(Reg, $dst_reg) => { panic!("division must be performed between registers of the same size") } (_, _) => panic!("division must be performed between registers of the same type"), } }; - (rem $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal]) => { + (rem $dst_reg:ident[$dst_idx:literal], $reg1:ident[$idx1:literal]) => { if $crate::_reg_block!($reg1) != RegBlockAFR::A - || $crate::_reg_block!($reg2) != RegBlockAFR::A + || $crate::_reg_block!($dst_reg) != RegBlockAFR::A { panic!("modulo division must be performed only using integer arithmetic registers"); } else { Instr::Arithmetic(ArithmeticOp::Rem( $crate::_reg_tya!(Reg, $reg1), $crate::_reg_idx!($idx1), - $crate::_reg_tya!(Reg, $reg2), - $crate::_reg_idx!($idx2), + $crate::_reg_tya!(Reg, $dst_reg), + $crate::_reg_idx!($dst_idx), )) } }; @@ -605,7 +619,7 @@ macro_rules! instr { Step::with(1), )) }; - (add $step:literal, $reg:ident[$idx:literal]) => { + (add $reg:ident[$idx:literal], $step:literal) => { Instr::Arithmetic(ArithmeticOp::Stp( $crate::_reg_tya!(Reg, $reg), $crate::_reg_idx!($idx), @@ -619,7 +633,7 @@ macro_rules! instr { Step::with(-1), )) }; - (sub $step:literal, $reg:ident[$idx:literal]) => { + (sub $reg:ident[$idx:literal], $step:literal) => { Instr::Arithmetic(ArithmeticOp::Stp( $crate::_reg_tya!(Reg, $reg), $crate::_reg_idx!($idx), @@ -639,9 +653,14 @@ macro_rules! instr { )) }; - (and $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal], $reg3:ident[$idx3:literal]) => { + ( + and + $dst_reg:ident[$dst_idx:literal], + $reg1:ident[$idx1:literal], + $reg2:ident[$idx2:literal] + ) => { if $crate::_reg_ty!(Reg, $reg1) != $crate::_reg_ty!(Reg, $reg2) - || $crate::_reg_ty!(Reg, $reg2) != $crate::_reg_ty!(Reg, $reg3) + || $crate::_reg_ty!(Reg, $reg2) != $crate::_reg_ty!(Reg, $dst_reg) { panic!("`and` operation must use the same type of registers for all of its operands"); } else if $crate::_reg_block!($reg1) != RegBlockAFR::A @@ -653,13 +672,15 @@ macro_rules! instr { $crate::_reg_ty!(Reg, $reg1).into(), $crate::_reg_idx16!($idx1), $crate::_reg_idx16!($idx2), - $crate::_reg_idx16!($idx3), + $crate::_reg_idx16!($dst_idx), )) } }; - (or $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal], $reg3:ident[$idx3:literal]) => { + ( + or $dst_reg:ident[$dst_idx:literal], $reg2:ident[$idx2:literal], $reg1:ident[$idx1:literal] + ) => { if $crate::_reg_ty!(Reg, $reg1) != $crate::_reg_ty!(Reg, $reg2) - || $crate::_reg_ty!(Reg, $reg2) != $crate::_reg_ty!(Reg, $reg3) + || $crate::_reg_ty!(Reg, $reg2) != $crate::_reg_ty!(Reg, $dst_reg) { panic!("`or` operation must use the same type of registers for all of its operands"); } else if $crate::_reg_block!($reg1) != RegBlockAFR::A @@ -671,13 +692,18 @@ macro_rules! instr { $crate::_reg_ty!(Reg, $reg1).into(), $crate::_reg_idx16!($idx1), $crate::_reg_idx16!($idx2), - $crate::_reg_idx16!($idx3), + $crate::_reg_idx16!($dst_idx), )) } }; - (xor $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal], $reg3:ident[$idx3:literal]) => { + ( + xor + $dst_reg:ident[$dst_idx:literal], + $reg2:ident[$idx2:literal], + $reg1:ident[$idx1:literal] + ) => { if $crate::_reg_ty!(Reg, $reg1) != $crate::_reg_ty!(Reg, $reg2) - || $crate::_reg_ty!(Reg, $reg2) != $crate::_reg_ty!(Reg, $reg3) + || $crate::_reg_ty!(Reg, $reg2) != $crate::_reg_ty!(Reg, $dst_reg) { panic!("`xor` operation must use the same type of registers for all of its operands"); } else if $crate::_reg_block!($reg1) != RegBlockAFR::A @@ -689,7 +715,7 @@ macro_rules! instr { $crate::_reg_ty!(Reg, $reg1).into(), $crate::_reg_idx16!($idx1), $crate::_reg_idx16!($idx2), - $crate::_reg_idx16!($idx3), + $crate::_reg_idx16!($dst_idx), )) } }; @@ -757,17 +783,17 @@ macro_rules! instr { } }; - (ripemd s16[$idx1:literal],r160[$idx2:literal]) => { + (ripemd r160[$idx2:literal],s16[$idx1:literal]) => { Instr::Digest(DigestOp::Ripemd(RegS::from($idx1), $crate::_reg_idx16!($idx2))) }; - (sha2 s16[$idx1:literal],r256[$idx2:literal]) => { + (sha2 r256[$idx2:literal],s16[$idx1:literal]) => { Instr::Digest(DigestOp::Sha256(RegS::from($idx1), $crate::_reg_idx16!($idx2))) }; - (sha2 s16[$idx1:literal],r512[$idx2:literal]) => { + (sha2 r512[$idx2:literal],s16[$idx1:literal]) => { Instr::Digest(DigestOp::Sha512(RegS::from($idx1), $crate::_reg_idx16!($idx2))) }; - (secpgen $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal]) => { + (secpgen $reg2:ident[$idx2:literal], $reg1:ident[$idx1:literal]) => { if $crate::_reg_block!($reg1) != RegBlockAFR::R || $crate::_reg_block!($reg2) != RegBlockAFR::R { @@ -777,7 +803,7 @@ macro_rules! instr { } }; ( - secpmul $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal], $reg3:ident[$idx3:literal] + secpmul $reg3:ident[$idx3:literal], $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal] ) => { if $crate::_reg_ty!(Reg, $reg2) != $crate::_reg_ty!(Reg, $reg3) { panic!("ecmul instruction can be used only with registers of the same type"); @@ -790,7 +816,7 @@ macro_rules! instr { )) } }; - (secpadd $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal]) => { + (secpadd $reg2:ident[$idx2:literal], $reg1:ident[$idx1:literal]) => { if $crate::_reg_block!($reg1) != RegBlockAFR::R || $crate::_reg_block!($reg2) != RegBlockAFR::R { @@ -799,7 +825,7 @@ macro_rules! instr { Instr::Secp256k1(Secp256k1Op::Add($crate::_reg_idx!($idx1), $crate::_reg_idx8!($idx2))) } }; - (secpneg $reg1:ident[$idx1:literal], $reg2:ident[$idx2:literal]) => { + (secpneg $reg2:ident[$idx2:literal], $reg1:ident[$idx1:literal]) => { if $crate::_reg_block!($reg1) != RegBlockAFR::R || $crate::_reg_block!($reg2) != RegBlockAFR::R { diff --git a/src/isa/exec.rs b/src/isa/exec.rs index f76264e..66373f4 100644 --- a/src/isa/exec.rs +++ b/src/isa/exec.rs @@ -619,7 +619,7 @@ impl InstructionSet for BytesOp { if bs.len() <= range.end && *flag == ExtendFlag::Fail { return None; } - bs.fill(o1..o2, val); + bs.fill(range, val); Some(()) }; f().unwrap_or_else(|| regs.st0 = false); diff --git a/src/isa/instr.rs b/src/isa/instr.rs index 73b17c3..af15117 100644 --- a/src/isa/instr.rs +++ b/src/isa/instr.rs @@ -631,11 +631,11 @@ pub enum BytesOp { /// /// If any of the offsets or value registers are unset, sets `st0` to `false` and does not /// change destination value. - #[display("fill {0},a16{1},a16{2},a8{3}")] + #[display("fill.{4} {0},a16{1},a16{2},a8{3}")] Fill( /** `s` register index */ RegS, /** `a16` register holding first offset */ Reg32, - /** `a16` register holding second offset (inclusive) */ Reg32, + /** `a16` register holding second offset (exclusive) */ Reg32, /** `a8` register index holding the value */ Reg32, /** Exception handling flag */ ExtendFlag, ), @@ -665,7 +665,7 @@ pub enum BytesOp { /// Check equality of two strings, putting result into `st0`. /// /// If both of strings are uninitialized, `st0` assigned `true` value. - #[display("cmp {0},{1}")] + #[display("eq {0},{1}")] Eq(RegS, RegS), /// Compute offset and length of the `n`th fragment shared between two strings ("conjoint diff --git a/src/reg/core_regs.rs b/src/reg/core_regs.rs index 35d5feb..f3a46be 100644 --- a/src/reg/core_regs.rs +++ b/src/reg/core_regs.rs @@ -693,6 +693,12 @@ impl Debug for CoreRegs { } } + write!(f, "\n{}S-REG:{}\t", sect, reset)?; + for i in 0..16 { + if let Some(ref v) = self.s16[i] { + write!(f, "{}s16{}[{}{:02}{}]={}{}{}\n\t", reg, eq, reset, i, eq, val, v, reset)?; + } + } Ok(()) } } diff --git a/tests/asm.rs b/tests/asm.rs index 980b4b9..e9aeb3d 100644 --- a/tests/asm.rs +++ b/tests/asm.rs @@ -16,8 +16,8 @@ use aluvm::{aluasm, Prog, Vm}; #[test] fn a8_ne() { let code = aluasm! { - put 12,a8[1]; - put 9,a8[2]; + put a8[1],12; + put a8[2],9; eq.n a8[1],a8[2]; ret; }; @@ -27,8 +27,8 @@ fn a8_ne() { #[test] fn a8_eq() { let code = aluasm! { - put 9,a8[1]; - put 9,a8[2]; + put a8[1],9; + put a8[2],9; eq.n a8[1],a8[2]; ret; }; @@ -48,8 +48,8 @@ fn a8_eq() { #[test] fn a16_eq() { let code = aluasm! { - put 4,a16[1]; - put 4,a16[2]; + put a16[1],4; + put a16[2],4; eq.n a16[1],a16[2]; ret; }; @@ -59,8 +59,8 @@ fn a16_eq() { #[test] fn a_eq_fail() { let code = aluasm! { - put 3,a16[1]; - put 4,a16[2]; + put a16[1],3; + put a16[2],4; eq.n a16[1],a16[2]; ret; }; @@ -88,8 +88,8 @@ fn a_eq_noneeq_noneq() { #[test] fn a_gt_u() { let code = aluasm! { - put 2,a8[1]; - put 1,a8[2]; + put a8[1],2; + put a8[2],1; gt.u a8[1],a8[2]; ret; }; @@ -99,22 +99,22 @@ fn a_gt_u() { #[test] fn a_gt_s() { let code = aluasm! { - put 1,a8[1]; - put 255,a8[2]; // -1 + put a8[1],1; + put a8[2],255; // -1 gt.s a8[1],a8[2]; ret; }; run(code, true); let code = aluasm! { - put 1,a8[1]; - put -1,a8[2]; + put a8[1],1; + put a8[2],-1; gt.s a8[1],a8[2]; ret; }; run(code, true); let code = aluasm! { - put 1,a8[1]; - put 2,a8[2]; + put a8[1],1; + put a8[2],2; gt.s a8[1],a8[2]; ret; }; @@ -124,8 +124,8 @@ fn a_gt_s() { #[test] fn a_lt_u() { let code = aluasm! { - put 1,a8[1]; - put 2,a8[2]; + put a8[1],1; + put a8[2],2; lt.u a8[1],a8[2]; ret; }; @@ -135,22 +135,22 @@ fn a_lt_u() { #[test] fn a_lt_s() { let code = aluasm! { - put 255,a8[1]; // -1 - put 1,a8[2]; + put a8[1],255; + put a8[2],1; lt.s a8[1],a8[2]; ret; }; run(code, true); let code = aluasm! { - put -1,a8[1]; - put 1,a8[2]; + put a8[1],-1; + put a8[2],1; lt.s a8[1],a8[2]; ret; }; run(code, true); let code = aluasm! { - put 2,a8[1]; - put 1,a8[2]; + put a8[1],2; + put a8[2],1; lt.s a8[1],a8[2]; ret; }; @@ -160,9 +160,9 @@ fn a_lt_s() { #[test] fn stp_add() { let code = aluasm! { - put 3,a8[1]; - add 4,a8[1]; - put 7,a8[2]; + put a8[1],3; + add a8[1],4; + put a8[2],7; eq.n a8[1],a8[2]; ret; }; @@ -172,9 +172,9 @@ fn stp_add() { #[test] fn stp_sub() { let code = aluasm! { - put 3,a8[1]; - sub 4,a8[1]; - put -1,a8[2]; + put a8[1],3; + sub a8[1],4; + put a8[2],-1; eq.n a8[1],a8[2]; ret; }; @@ -184,10 +184,10 @@ fn stp_sub() { #[test] fn float() { let code = aluasm! { - put 1.25,f32[8]; - put 1.5,f32[9]; - put 2.75,f32[10]; - add.f f32[8],f32[9]; + put f32[8],1.25; + put f32[9],1.5; + put f32[10],2.75; + add.f f32[9],f32[8]; eq.e f32[9],f32[10]; ret; }; @@ -199,14 +199,14 @@ fn bytes_put() { let code = aluasm! { put s16[1],"aaa"; put s16[2],"aaa"; - cmp s16[1],s16[2]; + eq s16[1],s16[2]; ret; }; run(code, true); let code = aluasm! { put s16[1],"aaa"; put s16[2],"bbb"; - cmp s16[1],s16[2]; + eq s16[1],s16[2]; ret; }; run(code, false); @@ -216,18 +216,18 @@ fn bytes_put() { fn bytes_extr() { let code = aluasm! { put s16[0],"################@@@@@@"; - put 0,a16[0]; - extr s16[0],r128[0],a16[0]; - put 0x23232323232323232323232323232323,r128[1]; + put a16[0],0; + extr r128[0],s16[0],a16[0]; + put r128[1],0x23232323232323232323232323232323; eq.n r128[0],r128[1]; ret; }; run(code, true); let code = aluasm! { put s16[0],"################@@@@@@"; - put 3,a16[0]; - extr s16[0],r128[0],a16[0]; - put 0x40404023232323232323232323232323,r128[1]; + put a16[0],3; + extr r128[0],s16[0],a16[0]; + put r128[1],0x40404023232323232323232323232323; eq.n r128[0],r128[1]; ret; }; @@ -238,52 +238,52 @@ fn bytes_extr() { fn bytes_extr_offset_exceed() { let code = aluasm! { put s16[0],"123456788901234567"; - put 0,a16[0]; - extr s16[0],r128[0],a16[0]; + put a16[0],0; + extr r128[0],s16[0],a16[0]; ret; }; run(code, true); let code = aluasm! { put s16[0],"123456788901234567"; - put 1,a16[0]; - extr s16[0],r128[0],a16[0]; + put a16[0],1; + extr r128[0],s16[0],a16[0]; ret; }; run(code, true); let code = aluasm! { put s16[0],"123456788901234567"; - put 2,a16[0]; - extr s16[0],r128[0],a16[0]; + put a16[0],2; + extr r128[0],s16[0],a16[0]; ret; }; run(code, false); let code = aluasm! { put s16[0],"123456788901234567"; - put 2,a16[0]; - extr s16[0],r128[0],a16[0]; + put a16[0],2; + extr r128[0],s16[0],a16[0]; ret; }; run(code, false); let code = aluasm! { put s16[0],"################@"; - put 1,a16[0]; - extr s16[0],r128[0],a16[0]; - put 0x40232323232323232323232323232323,r128[1]; + put a16[0],1; + extr r128[0],s16[0],a16[0]; + put r128[1],0x40232323232323232323232323232323; eq.n r128[0],r128[1]; ret; }; run(code, true); let code = aluasm! { put s16[0],"123456788901234567"; - put 100,a16[0]; - extr s16[0],r128[0],a16[0]; + put a16[0],100; + extr r128[0],s16[0],a16[0]; ret; }; run(code, false); let code = aluasm! { put s16[0],"123"; - put 0,a16[0]; - extr s16[0],r128[0],a16[0]; + put a16[0],0; + extr r128[0],s16[0],a16[0]; ret; }; run(code, false); @@ -293,13 +293,13 @@ fn bytes_extr_offset_exceed() { fn bytes_extr_uninitialized_offset() { let code = aluasm! { put s16[0],"12345678890123456"; - extr s16[0],r128[0],a16[0]; + extr r128[0],s16[0],a16[0]; ret; }; run(code, false); let code = aluasm! { put s16[0],"12345678890123456"; - extr s16[0],r128[0],a16[0]; + extr r128[0],s16[0],a16[0]; eq.e r128[0],r128[1]; ret; }; @@ -309,14 +309,14 @@ fn bytes_extr_uninitialized_offset() { #[test] fn bytes_extr_uninitialized_bytes() { let code = aluasm! { - put 0,a16[0]; - extr s16[0],r128[0],a16[0]; + put a16[0],0; + extr r128[0],s16[0],a16[0]; ret; }; run(code, false); let code = aluasm! { - put 0,a16[0]; - extr s16[0],r128[0],a16[0]; + put a16[0],0; + extr r128[0],s16[0],a16[0]; eq.e r128[0],r128[1]; ret; };