diff --git a/internal/polkavm/common.go b/internal/polkavm/common.go index 32e11a7..d5adbb3 100644 --- a/internal/polkavm/common.go +++ b/internal/polkavm/common.go @@ -131,6 +131,16 @@ type Mutator interface { Trap() error Fallthrough() Sbrk(dst Reg, size Reg) error + CountSetBits64(d, s Reg) + CountSetBits32(d, s Reg) + LeadingZeroBits64(d, s Reg) + LeadingZeroBits32(d, s Reg) + TrailingZeroBits64(d, s Reg) + TrailingZeroBits32(d, s Reg) + SignExtend8(d, s Reg) + SignExtend16(d, s Reg) + ZeroExtend16(d, s Reg) + ReverseBytes(d, s Reg) MoveReg(d Reg, s Reg) BranchEq(s1 Reg, s2 Reg, target uint32) BranchEqImm(s1 Reg, s2 uint32, target uint32) @@ -204,7 +214,22 @@ type Mutator interface { CmovIfZero(d Reg, s, c Reg) CmovIfZeroImm(d Reg, c Reg, s uint32) CmovIfNotZero(d Reg, s, c Reg) + RotL64(d Reg, s, c Reg) + RotL32(d Reg, s, c Reg) + RotR64(d Reg, s, c Reg) + RotR32(d Reg, s, c Reg) + AndInv(d Reg, s, c Reg) + OrInv(d Reg, s, c Reg) + Xnor(d Reg, s, c Reg) + Max(d Reg, s, c Reg) + MaxU(d Reg, s, c Reg) + Min(d Reg, s, c Reg) + MinU(d Reg, s, c Reg) CmovIfNotZeroImm(d Reg, c Reg, s uint32) + RotR64Imm(d Reg, c Reg, s uint32) + RotR64ImmAlt(d Reg, c Reg, s uint32) + RotR32Imm(d Reg, c Reg, s uint32) + RotR32ImmAlt(d Reg, c Reg, s uint32) StoreU8(src Reg, offset uint32) error StoreU16(src Reg, offset uint32) error StoreU32(src Reg, offset uint32) error diff --git a/internal/polkavm/host_call/refine_functions_test.go b/internal/polkavm/host_call/refine_functions_test.go index 635b72e..b31126f 100644 --- a/internal/polkavm/host_call/refine_functions_test.go +++ b/internal/polkavm/host_call/refine_functions_test.go @@ -699,7 +699,7 @@ func TestInvoke(t *testing.T) { assert.Equal(t, []uint64{0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0}, invokeGasAndRegs[1:]) } -var addInstrProgram = []byte{0, 0, 3, 8, 135, 9, 1} // copied from testvectors +var addInstrProgram = []byte{0, 0, 3, 190, 135, 9, 1} // copied from the future testvectors :P func TestExpunge(t *testing.T) { pp := &polkavm.Program{ diff --git a/internal/polkavm/instruction_codes.go b/internal/polkavm/instruction_codes.go new file mode 100644 index 0000000..99d8833 --- /dev/null +++ b/internal/polkavm/instruction_codes.go @@ -0,0 +1,170 @@ +//go:build !integration + +package polkavm + +const ( + // A.5.1. Instructions without Arguments + Trap Opcode = 0 // trap + Fallthrough Opcode = 1 // fallthrough + + // A.5.2. Instructions with Arguments of One Immediate. + Ecalli Opcode = 10 // ecalli + + // A.5.3. Instructions with Arguments of One Register and One Extended Width Immediate. + LoadImm64 Opcode = 20 // load_imm_64 + + // A.5.4. Instructions with Arguments of Two Immediates. + StoreImmU8 Opcode = 30 // store_imm_u8 + StoreImmU16 Opcode = 31 // store_imm_u16 + StoreImmU32 Opcode = 32 // store_imm_u32 + StoreImmU64 Opcode = 33 // store_imm_u64 + + // A.5.5. Instructions with Arguments of One Offset. + Jump Opcode = 40 + + // A.5.6. Instructions with Arguments of One Register & One Immediate. + JumpIndirect Opcode = 50 // jump_ind + LoadImm Opcode = 51 // load_imm + LoadU8 Opcode = 52 // load_u8 + LoadI8 Opcode = 53 // load_i8 + LoadU16 Opcode = 54 // load_u16 + LoadI16 Opcode = 55 // load_i16 + LoadU32 Opcode = 56 // load_u32 + LoadI32 Opcode = 57 // load_i32 + LoadU64 Opcode = 58 // load_u64 + StoreU8 Opcode = 59 // store_u8 + StoreU16 Opcode = 60 // store_u16 + StoreU32 Opcode = 61 // store_u32 + StoreU64 Opcode = 62 // store_u64 + + // A.5.7. Instructions with Arguments of One Register & Two Immediates. + StoreImmIndirectU8 Opcode = 70 // store_imm_ind_u8 + StoreImmIndirectU16 Opcode = 71 // store_imm_ind_u16 + StoreImmIndirectU32 Opcode = 72 // store_imm_ind_u32 + StoreImmIndirectU64 Opcode = 73 // store_imm_ind_u64 + + // A.5.8. Instructions with Arguments of One Register, One Immediate and One Offset. + LoadImmAndJump Opcode = 80 // load_imm_jump + BranchEqImm Opcode = 81 // branch_eq_imm + BranchNotEqImm Opcode = 82 // branch_ne_imm + BranchLessUnsignedImm Opcode = 83 // branch_lt_u_imm + BranchLessOrEqualUnsignedImm Opcode = 84 // branch_le_u_imm + BranchGreaterOrEqualUnsignedImm Opcode = 85 // branch_ge_u_imm + BranchGreaterUnsignedImm Opcode = 86 // branch_gt_u_imm + BranchLessSignedImm Opcode = 87 // branch_lt_s_imm + BranchLessOrEqualSignedImm Opcode = 88 // branch_le_s_imm + BranchGreaterOrEqualSignedImm Opcode = 89 // branch_ge_s_imm + BranchGreaterSignedImm Opcode = 90 // branch_gt_s_imm + + // A.5.9. Instructions with Arguments of Two Registers. + MoveReg Opcode = 100 // move_reg + Sbrk Opcode = 101 // sbrk + CountSetBits64 Opcode = 102 // count_set_bits_64 + CountSetBits32 Opcode = 103 // count_set_bits_32 + LeadingZeroBits64 Opcode = 104 // leading_zero_bits_64 + LeadingZeroBits32 Opcode = 105 // leading_zero_bits_32 + TrailingZeroBits64 Opcode = 106 // trailing_zero_bits_64 + TrailingZeroBits32 Opcode = 107 // trailing_zero_bits_32 + SignExtend8 Opcode = 108 // sign_extend_8 + SignExtend16 Opcode = 109 // sign_extend_16 + ZeroExtend16 Opcode = 110 // zero_extend_16 + ReverseBytes Opcode = 111 // reverse_bytes + + // A.5.10. Instructions with Arguments of Two Registers & One Immediate. + StoreIndirectU8 Opcode = 120 // store_ind_u8 + StoreIndirectU16 Opcode = 121 // store_ind_u16 + StoreIndirectU32 Opcode = 122 // store_ind_u32 + StoreIndirectU64 Opcode = 123 // store_ind_u64 + LoadIndirectU8 Opcode = 124 // load_ind_u8 + LoadIndirectI8 Opcode = 125 // load_ind_i8 + LoadIndirectU16 Opcode = 126 // load_ind_u16 + LoadIndirectI16 Opcode = 127 // load_ind_i16 + LoadIndirectU32 Opcode = 128 // load_ind_u32 + LoadIndirectI32 Opcode = 129 // load_ind_i32 + LoadIndirectU64 Opcode = 130 // load_ind_u64 + AddImm32 Opcode = 131 // add_imm_32 + AndImm Opcode = 132 // and_imm + XorImm Opcode = 133 // xor_imm + OrImm Opcode = 134 // or_imm + MulImm32 Opcode = 135 // mul_imm_32 + SetLessThanUnsignedImm Opcode = 136 // set_lt_u_imm + SetLessThanSignedImm Opcode = 137 // set_lt_s_imm + ShiftLogicalLeftImm32 Opcode = 138 // shlo_l_imm_32 + ShiftLogicalRightImm32 Opcode = 139 // shlo_r_imm_32 + ShiftArithmeticRightImm32 Opcode = 140 // shar_r_imm_32 + NegateAndAddImm32 Opcode = 141 // neg_add_imm_32 + SetGreaterThanUnsignedImm Opcode = 142 // set_gt_u_imm + SetGreaterThanSignedImm Opcode = 143 // set_gt_s_imm + ShiftLogicalRightImmAlt32 Opcode = 144 // shlo_r_imm_alt_32 + ShiftArithmeticRightImmAlt32 Opcode = 145 // shar_r_imm_alt_32 + ShiftLogicalLeftImmAlt32 Opcode = 146 // shlo_l_imm_alt_32 + CmovIfZeroImm Opcode = 147 // cmov_iz_imm + CmovIfNotZeroImm Opcode = 148 // cmov_nz_imm + AddImm64 Opcode = 149 // add_imm_64 + MulImm64 Opcode = 150 // mul_imm_64 + ShiftLogicalLeftImm64 Opcode = 151 // shlo_l_imm_64 + ShiftLogicalRightImm64 Opcode = 152 // shlo_r_imm_64 + ShiftArithmeticRightImm64 Opcode = 153 // shar_r_imm_64 + NegateAndAddImm64 Opcode = 154 // neg_add_imm_64 + ShiftLogicalLeftImmAlt64 Opcode = 155 // shlo_l_imm_alt_64 + ShiftLogicalRightImmAlt64 Opcode = 156 // shlo_r_imm_alt_64 + ShiftArithmeticRightImmAlt64 Opcode = 157 // shar_r_imm_alt_64 + RotR64Imm Opcode = 158 // rot_r_64_imm + RotR64ImmAlt Opcode = 159 // rot_r_64_imm_alt + RotR32Imm Opcode = 160 // rot_r_32_imm + RotR32ImmAlt Opcode = 161 // rot_r_32_imm_alt + + // A.5.11. Instructions with Arguments of Two Registers & One Offset. + BranchEq Opcode = 170 // branch_eq + BranchNotEq Opcode = 171 // branch_ne + BranchLessUnsigned Opcode = 172 // branch_lt_u + BranchLessSigned Opcode = 173 // branch_lt_s + BranchGreaterOrEqualUnsigned Opcode = 174 // branch_ge_u + BranchGreaterOrEqualSigned Opcode = 175 // branch_ge_s + + // A.5.12. Instruction with Arguments of Two Registers and Two Immediates. + LoadImmAndJumpIndirect Opcode = 180 // load_imm_jump_ind + + // A.5.13. Instructions with Arguments of Three Registers. + Add32 Opcode = 190 // add_32 + Sub32 Opcode = 191 // sub_32 + Mul32 Opcode = 192 // mul_32 + DivUnsigned32 Opcode = 193 // div_u_32 + DivSigned32 Opcode = 194 // div_s_32 + RemUnsigned32 Opcode = 195 // rem_u_32 + RemSigned32 Opcode = 196 // rem_s_32 + ShiftLogicalLeft32 Opcode = 197 // shlo_l_32 + ShiftLogicalRight32 Opcode = 198 // shlo_r_32 + ShiftArithmeticRight32 Opcode = 199 // shar_r_32 + Add64 Opcode = 200 // add_64 + Sub64 Opcode = 201 // sub_64 + Mul64 Opcode = 202 // mul_64 + DivUnsigned64 Opcode = 203 // div_u_64 + DivSigned64 Opcode = 204 // div_s_64 + RemUnsigned64 Opcode = 205 // rem_u_64 + RemSigned64 Opcode = 206 // rem_s_64 + ShiftLogicalLeft64 Opcode = 207 // shlo_l_64 + ShiftLogicalRight64 Opcode = 208 // shlo_r_64 + ShiftArithmeticRight64 Opcode = 209 // shar_r_64 + And Opcode = 210 // and + Xor Opcode = 211 // xor + Or Opcode = 212 // or + MulUpperSignedSigned Opcode = 213 // mul_upper_s_s + MulUpperUnsignedUnsigned Opcode = 214 // mul_upper_u_u + MulUpperSignedUnsigned Opcode = 215 // mul_upper_s_u + SetLessThanUnsigned Opcode = 216 // set_lt_u + SetLessThanSigned Opcode = 217 // set_lt_s + CmovIfZero Opcode = 218 // cmov_iz + CmovIfNotZero Opcode = 219 // cmov_nz + RotL64 Opcode = 220 // rot_l_64 + RotL32 Opcode = 221 // rot_l_32 + RotR64 Opcode = 222 // rot_r_64 + RotR32 Opcode = 223 // rot_r_32 + AndInv Opcode = 224 // and_inv + OrInv Opcode = 225 // or_inv + Xnor Opcode = 226 // xnor + Max Opcode = 227 // max + MaxU Opcode = 228 // max_u + Min Opcode = 229 // min + MinU Opcode = 230 // min_u +) diff --git a/internal/polkavm/instruction_codes_integration.go b/internal/polkavm/instruction_codes_integration.go new file mode 100644 index 0000000..ecea90d --- /dev/null +++ b/internal/polkavm/instruction_codes_integration.go @@ -0,0 +1,150 @@ +//go:build integration + +package polkavm + +import "math" + +const ( + Trap Opcode = 0 + Fallthrough Opcode = 17 + Ecalli Opcode = 78 + StoreImmU8 Opcode = 62 + StoreImmU16 Opcode = 79 + StoreImmU32 Opcode = 38 + Jump Opcode = 5 + JumpIndirect Opcode = 19 + LoadImm Opcode = 4 + LoadU8 Opcode = 60 + LoadI8 Opcode = 74 + LoadU16 Opcode = 76 + LoadI16 Opcode = 66 + LoadU32 Opcode = 10 + StoreU8 Opcode = 71 + StoreU16 Opcode = 69 + StoreU32 Opcode = 22 + StoreImmIndirectU8 Opcode = 26 + StoreImmIndirectU16 Opcode = 54 + StoreImmIndirectU32 Opcode = 13 + LoadImmAndJump Opcode = 6 + BranchEqImm Opcode = 7 + BranchNotEqImm Opcode = 15 + BranchLessUnsignedImm Opcode = 44 + BranchLessOrEqualUnsignedImm Opcode = 59 + BranchGreaterOrEqualUnsignedImm Opcode = 52 + BranchGreaterUnsignedImm Opcode = 50 + BranchLessSignedImm Opcode = 32 + BranchLessOrEqualSignedImm Opcode = 46 + BranchGreaterOrEqualSignedImm Opcode = 45 + BranchGreaterSignedImm Opcode = 53 + MoveReg Opcode = 82 + Sbrk Opcode = 87 + StoreIndirectU8 Opcode = 16 + StoreIndirectU16 Opcode = 29 + StoreIndirectU32 Opcode = 3 + LoadIndirectU8 Opcode = 11 + LoadIndirectI8 Opcode = 21 + LoadIndirectU16 Opcode = 37 + LoadIndirectI16 Opcode = 33 + LoadIndirectU32 Opcode = 1 + AddImm32 Opcode = 2 + AndImm Opcode = 18 + XorImm Opcode = 31 + OrImm Opcode = 49 + MulImm32 Opcode = 35 + SetLessThanUnsignedImm Opcode = 27 + SetLessThanSignedImm Opcode = 56 + ShiftLogicalLeftImm32 Opcode = 9 + ShiftLogicalRightImm32 Opcode = 14 + ShiftArithmeticRightImm32 Opcode = 25 + NegateAndAddImm32 Opcode = 40 + SetGreaterThanUnsignedImm Opcode = 39 + SetGreaterThanSignedImm Opcode = 61 + ShiftLogicalRightImmAlt32 Opcode = 72 + ShiftArithmeticRightImmAlt32 Opcode = 80 + ShiftLogicalLeftImmAlt32 Opcode = 75 + CmovIfZeroImm Opcode = 85 + CmovIfNotZeroImm Opcode = 86 + BranchEq Opcode = 24 + BranchNotEq Opcode = 30 + BranchLessUnsigned Opcode = 47 + BranchLessSigned Opcode = 48 + BranchGreaterOrEqualUnsigned Opcode = 41 + BranchGreaterOrEqualSigned Opcode = 43 + LoadImmAndJumpIndirect Opcode = 42 + Add32 Opcode = 8 + Sub32 Opcode = 20 + Mul32 Opcode = 34 + DivUnsigned32 Opcode = 68 + DivSigned32 Opcode = 64 + RemUnsigned32 Opcode = 73 + RemSigned32 Opcode = 70 + ShiftLogicalLeft32 Opcode = 55 + ShiftLogicalRight32 Opcode = 51 + ShiftArithmeticRight32 Opcode = 77 + And Opcode = 23 + Xor Opcode = 28 + Or Opcode = 12 + MulUpperSignedSigned Opcode = 67 + MulUpperUnsignedUnsigned Opcode = 57 + MulUpperSignedUnsigned Opcode = 81 + SetLessThanUnsigned Opcode = 36 + SetLessThanSigned Opcode = 58 + CmovIfZero Opcode = 83 + CmovIfNotZero Opcode = 84 +) + +const ( + StoreImmIndirectU64 Opcode = math.MaxUint8 - iota + StoreU64 + StoreImmU64 + LoadImm64 + StoreIndirectU64 + LoadIndirectI32 + LoadIndirectU64 + AddImm64 + MulImm64 + ShiftLogicalLeftImm64 + ShiftLogicalRightImm64 + ShiftArithmeticRightImm64 + NegateAndAddImm64 + ShiftLogicalLeftImmAlt64 + ShiftLogicalRightImmAlt64 + ShiftArithmeticRightImmAlt64 + Add64 + Sub64 + Mul64 + DivUnsigned64 + DivSigned64 + RemUnsigned64 + RemSigned64 + ShiftLogicalLeft64 + ShiftLogicalRight64 + ShiftArithmeticRight64 + LoadI32 + LoadU64 + CountSetBits64 + CountSetBits32 + LeadingZeroBits64 + LeadingZeroBits32 + TrailingZeroBits64 + TrailingZeroBits32 + SignExtend8 + SignExtend16 + ZeroExtend16 + ReverseBytes + RotR64Imm + RotR64ImmAlt + RotR32Imm + RotR32ImmAlt + RotL64 + RotL32 + RotR64 + RotR32 + AndInv + OrInv + Xnor + Max + MaxU + Min + MinU +) diff --git a/internal/polkavm/instructions.go b/internal/polkavm/instructions.go index 73d241e..645bac2 100644 --- a/internal/polkavm/instructions.go +++ b/internal/polkavm/instructions.go @@ -7,148 +7,6 @@ import ( type Opcode byte -const ( - // A.5.1. Instructions without Arguments - Trap Opcode = 0 // trap = 0 - Fallthrough Opcode = 17 // fallthrough = 1 - - // A.5.2. Instructions with Arguments of One Immediate. - Ecalli Opcode = 78 // ecalli = 10 - - // A.5.3. Instructions with Arguments of One Register and One Extended Width Immediate. - LoadImm64 = 255 - 20 // load_imm_64 = 20 - - // A.5.4. Instructions with Arguments of Two Immediates. - StoreImmU8 Opcode = 62 // store_imm_u8 = 30 - StoreImmU16 Opcode = 79 // store_imm_u16 = 31 - StoreImmU32 Opcode = 38 // store_imm_u32 = 32 - StoreImmU64 Opcode = 255 - 33 // store_imm_u64 = 33 - - // A.5.5. Instructions with Arguments of One Offset. - Jump Opcode = 5 - - // A.5.6. Instructions with Arguments of One Register & One Immediate. - JumpIndirect Opcode = 19 // jump_ind = 50 - LoadImm Opcode = 4 // load_imm = 51 - LoadU8 Opcode = 60 // load_u8 = 52 - LoadI8 Opcode = 74 // load_i8 = 53 - LoadU16 Opcode = 76 // load_u16 = 54 - LoadI16 Opcode = 66 // load_i16 = 55 - LoadU32 Opcode = 10 // load_u32 = 56 - LoadI32 Opcode = 255 - 57 // load_i32 = 57 - LoadU64 Opcode = 255 - 58 // load_u64 = 58 - StoreU8 Opcode = 71 // store_u8 = 59 - StoreU16 Opcode = 69 // store_u16 = 60 - StoreU32 Opcode = 22 // store_u32 = 61 - StoreU64 Opcode = 255 - 62 // store_u64 = 62 - - // A.5.7. Instructions with Arguments of One Register & Two Immediates. - StoreImmIndirectU8 Opcode = 26 // store_imm_ind_u8 = 70 - StoreImmIndirectU16 Opcode = 54 // store_imm_ind_u16 = 71 - StoreImmIndirectU32 Opcode = 13 // store_imm_ind_u32 = 72 - StoreImmIndirectU64 Opcode = 300 - 73 // store_imm_ind_u64 = 73 // todo fix opcode numbers - - // A.5.8. Instructions with Arguments of One Register, One Immediate and One Offset. - LoadImmAndJump Opcode = 6 // load_imm_jump = 80 - BranchEqImm Opcode = 7 // branch_eq_imm = 81 - BranchNotEqImm Opcode = 15 // branch_ne_imm = 82 - BranchLessUnsignedImm Opcode = 44 // branch_lt_u_imm = 83 - BranchLessOrEqualUnsignedImm Opcode = 59 // branch_le_u_imm = 84 - BranchGreaterOrEqualUnsignedImm Opcode = 52 // branch_ge_u_imm = 85 - BranchGreaterUnsignedImm Opcode = 50 // branch_gt_u_imm = 86 - BranchLessSignedImm Opcode = 32 // branch_lt_s_imm = 87 - BranchLessOrEqualSignedImm Opcode = 46 // branch_le_s_imm = 88 - BranchGreaterOrEqualSignedImm Opcode = 45 // branch_ge_s_imm = 89 - BranchGreaterSignedImm Opcode = 53 // branch_gt_s_imm = 90 - - // A.5.9. Instructions with Arguments of Two Registers. - MoveReg Opcode = 82 // move_reg = 100 - Sbrk Opcode = 87 // sbrk = 101 - - // A.5.10. Instructions with Arguments of Two Registers & One Immediate. - StoreIndirectU8 Opcode = 16 // store_ind_u8 = 110 - StoreIndirectU16 Opcode = 29 // store_ind_u16 = 111 - StoreIndirectU32 Opcode = 3 // store_ind_u32 = 112 - StoreIndirectU64 Opcode = 350 - 113 // store_ind_u64 = 113 // todo fix opcode numbers - LoadIndirectU8 Opcode = 11 // load_ind_u8 = 114 - LoadIndirectI8 Opcode = 21 // load_ind_i8 = 115 - LoadIndirectU16 Opcode = 37 // load_ind_u16 = 116 - LoadIndirectI16 Opcode = 33 // load_ind_i16 = 117 - LoadIndirectU32 Opcode = 1 // load_ind_u32 = 118 - LoadIndirectI32 Opcode = 255 - 119 // load_ind_i32 = 119 - LoadIndirectU64 Opcode = 255 - 120 // load_ind_u64 = 120 - AddImm32 Opcode = 2 // add_imm_32 = 121 - AndImm Opcode = 18 // and_imm = 122 - XorImm Opcode = 31 // xor_imm = 123 - OrImm Opcode = 49 // or_imm = 124 - MulImm32 Opcode = 35 // mul_imm_32 = 125 - SetLessThanUnsignedImm Opcode = 27 // set_lt_u_imm = 126 - SetLessThanSignedImm Opcode = 56 // set_lt_s_imm = 127 - ShiftLogicalLeftImm32 Opcode = 9 // shlo_l_imm_32 = 128 - ShiftLogicalRightImm32 Opcode = 14 // shlo_r_imm_32 = 129 - ShiftArithmeticRightImm32 Opcode = 25 // shar_r_imm_32 = 130 - NegateAndAddImm32 Opcode = 40 // neg_add_imm_32 = 131 - SetGreaterThanUnsignedImm Opcode = 39 // set_gt_u_imm = 132 - SetGreaterThanSignedImm Opcode = 61 // set_gt_s_imm = 133 - ShiftLogicalRightImmAlt32 Opcode = 72 // shlo_r_imm_alt_32 = 134 - ShiftArithmeticRightImmAlt32 Opcode = 80 // shar_r_imm_alt_32 = 135 - ShiftLogicalLeftImmAlt32 Opcode = 75 // shlo_l_imm_alt_32 = 136 - CmovIfZeroImm Opcode = 85 // cmov_iz_imm = 137 - CmovIfNotZeroImm Opcode = 86 // cmov_nz_imm = 138 - AddImm64 Opcode = 139 // add_imm_64 = 139 - MulImm64 Opcode = 140 // mul_imm_64 = 140 - ShiftLogicalLeftImm64 Opcode = 141 // shlo_l_imm_64 = 141 - ShiftLogicalRightImm64 Opcode = 142 // shlo_r_imm_64 = 142 - ShiftArithmeticRightImm64 Opcode = 143 // shar_r_imm_64 = 143 - NegateAndAddImm64 Opcode = 144 // neg_add_imm_64 = 144 - ShiftLogicalLeftImmAlt64 Opcode = 145 // shlo_l_imm_alt_64 = 145 - ShiftLogicalRightImmAlt64 Opcode = 146 // shlo_r_imm_alt_64 = 146 - ShiftArithmeticRightImmAlt64 Opcode = 147 // shar_r_imm_alt_64 = 147 - - // A.5.11. Instructions with Arguments of Two Registers & One Offset. - BranchEq Opcode = 24 // branch_eq = 150 - BranchNotEq Opcode = 30 // branch_ne = 151 - BranchLessUnsigned Opcode = 47 // branch_lt_u = 152 - BranchLessSigned Opcode = 48 // branch_lt_s = 153 - BranchGreaterOrEqualUnsigned Opcode = 41 // branch_ge_u = 154 - BranchGreaterOrEqualSigned Opcode = 43 // branch_ge_s = 155 - - // A.5.12. Instruction with Arguments of Two Registers and Two Immediates. - LoadImmAndJumpIndirect Opcode = 42 // load_imm_jump_ind = 160 - - // A.5.13. Instructions with Arguments of Three Registers. - Add32 Opcode = 8 // add_32 = 170 - Sub32 Opcode = 20 // sub_32 = 171 - Mul32 Opcode = 34 // mul_32 = 172 - DivUnsigned32 Opcode = 68 // div_u_32 = 173 - DivSigned32 Opcode = 64 // div_s_32 = 174 - RemUnsigned32 Opcode = 73 // rem_u_32 = 175 - RemSigned32 Opcode = 70 // rem_s_32 = 176 - ShiftLogicalLeft32 Opcode = 55 // shlo_l_32 = 177 - ShiftLogicalRight32 Opcode = 51 // shlo_r_32 = 178 - ShiftArithmeticRight32 Opcode = 77 // shar_r_32 = 179 - Add64 Opcode = 180 // add_64 = 180 - Sub64 Opcode = 181 // sub_64 = 181 - Mul64 Opcode = 182 // mul_64 = 182 - DivUnsigned64 Opcode = 183 // div_u_64 = 183 - DivSigned64 Opcode = 184 // div_s_64 = 184 - RemUnsigned64 Opcode = 185 // rem_u_64 = 185 - RemSigned64 Opcode = 186 // rem_s_64 = 186 - ShiftLogicalLeft64 Opcode = 187 // shlo_l_64 = 187 - ShiftLogicalRight64 Opcode = 188 // shlo_r_64 = 188 - ShiftArithmeticRight64 Opcode = 189 // shar_r_64 = 189 - And Opcode = 23 // and = 190 - Xor Opcode = 28 // xor = 191 - Or Opcode = 12 // or = 192 - MulUpperSignedSigned Opcode = 67 // mul_upper_s_s = 193 - MulUpperUnsignedUnsigned Opcode = 57 // mul_upper_u_u = 194 - MulUpperSignedUnsigned Opcode = 81 // mul_upper_s_u = 195 - SetLessThanUnsigned Opcode = 36 // set_lt_u = 196 - SetLessThanSigned Opcode = 58 // set_lt_s = 197 - CmovIfZero Opcode = 83 // cmov_iz = 198 - CmovIfNotZero Opcode = 84 // cmov_nz = 199 -) - var GasCosts = map[Opcode]Gas{ Trap: 1, Fallthrough: 1, @@ -188,6 +46,16 @@ var GasCosts = map[Opcode]Gas{ BranchGreaterSignedImm: 1, MoveReg: 1, Sbrk: 1, + CountSetBits64: 1, + CountSetBits32: 1, + LeadingZeroBits64: 1, + LeadingZeroBits32: 1, + TrailingZeroBits64: 1, + TrailingZeroBits32: 1, + SignExtend8: 1, + SignExtend16: 1, + ZeroExtend16: 1, + ReverseBytes: 1, StoreIndirectU8: 1, StoreIndirectU16: 1, StoreIndirectU32: 1, @@ -226,6 +94,10 @@ var GasCosts = map[Opcode]Gas{ ShiftLogicalLeftImmAlt64: 1, ShiftLogicalRightImmAlt64: 1, ShiftArithmeticRightImmAlt64: 1, + RotR64Imm: 1, + RotR64ImmAlt: 1, + RotR32Imm: 1, + RotR32ImmAlt: 1, BranchEq: 1, BranchNotEq: 1, BranchLessUnsigned: 1, @@ -263,6 +135,17 @@ var GasCosts = map[Opcode]Gas{ SetLessThanSigned: 1, CmovIfZero: 1, CmovIfNotZero: 1, + RotL64: 1, + RotL32: 1, + RotR64: 1, + RotR32: 1, + AndInv: 1, + OrInv: 1, + Xnor: 1, + Max: 1, + MaxU: 1, + Min: 1, + MinU: 1, } type Reg uint @@ -341,7 +224,12 @@ var ( BranchLessOrEqualSignedImm, BranchGreaterOrEqualSignedImm, BranchGreaterSignedImm, } // Instructions with Arguments of Two Registers. - instrRegReg = []Opcode{MoveReg, Sbrk} + instrRegReg = []Opcode{ + MoveReg, Sbrk, + CountSetBits64, CountSetBits32, LeadingZeroBits64, + LeadingZeroBits32, TrailingZeroBits64, TrailingZeroBits32, + SignExtend8, SignExtend16, ZeroExtend16, ReverseBytes, + } // Instructions with Arguments of Two Registers & One Immediate. instrReg2Imm = []Opcode{ StoreIndirectU8, StoreIndirectU16, StoreIndirectU32, StoreIndirectU64, @@ -357,6 +245,7 @@ var ( ShiftLogicalLeftImm64, ShiftLogicalRightImm64, ShiftArithmeticRightImm64, NegateAndAddImm64, ShiftLogicalLeftImmAlt64, ShiftLogicalRightImmAlt64, ShiftArithmeticRightImmAlt64, + RotR64Imm, RotR64ImmAlt, RotR32Imm, RotR32ImmAlt, } // Instructions with Arguments of Two Registers & One Offset. instrReg2Offset = []Opcode{ @@ -373,6 +262,7 @@ var ( ShiftLogicalLeft64, ShiftLogicalRight64, ShiftArithmeticRight64, And, Xor, Or, MulUpperSignedSigned, MulUpperUnsignedUnsigned, MulUpperSignedUnsigned, SetLessThanUnsigned, SetLessThanSigned, CmovIfZero, CmovIfNotZero, + RotL64, RotL32, RotR64, RotR32, AndInv, OrInv, Xnor, Max, MaxU, Min, MinU, } ) @@ -729,6 +619,14 @@ func (i *Instruction) Mutate(mutator Mutator) (uint32, error) { mutator.CmovIfZeroImm(i.Reg[0], i.Reg[1], i.Imm[0]) case CmovIfNotZeroImm: mutator.CmovIfNotZeroImm(i.Reg[0], i.Reg[1], i.Imm[0]) + case RotR64Imm: + mutator.RotR64Imm(i.Reg[0], i.Reg[1], i.Imm[0]) + case RotR64ImmAlt: + mutator.RotR64ImmAlt(i.Reg[0], i.Reg[1], i.Imm[0]) + case RotR32Imm: + mutator.RotR32Imm(i.Reg[0], i.Reg[1], i.Imm[0]) + case RotR32ImmAlt: + mutator.RotR32ImmAlt(i.Reg[0], i.Reg[1], i.Imm[0]) case BranchEq: mutator.BranchEq(i.Reg[0], i.Reg[1], i.Imm[0]) case BranchNotEq: @@ -801,6 +699,28 @@ func (i *Instruction) Mutate(mutator Mutator) (uint32, error) { mutator.CmovIfZero(i.Reg[0], i.Reg[1], i.Reg[2]) case CmovIfNotZero: mutator.CmovIfNotZero(i.Reg[0], i.Reg[1], i.Reg[2]) + case RotL64: + mutator.RotL64(i.Reg[0], i.Reg[1], i.Reg[2]) + case RotL32: + mutator.RotL32(i.Reg[0], i.Reg[1], i.Reg[2]) + case RotR64: + mutator.RotR64(i.Reg[0], i.Reg[1], i.Reg[2]) + case RotR32: + mutator.RotR32(i.Reg[0], i.Reg[1], i.Reg[2]) + case AndInv: + mutator.AndInv(i.Reg[0], i.Reg[1], i.Reg[2]) + case OrInv: + mutator.OrInv(i.Reg[0], i.Reg[1], i.Reg[2]) + case Xnor: + mutator.Xnor(i.Reg[0], i.Reg[1], i.Reg[2]) + case Max: + mutator.Max(i.Reg[0], i.Reg[1], i.Reg[2]) + case MaxU: + mutator.MaxU(i.Reg[0], i.Reg[1], i.Reg[2]) + case Min: + mutator.Min(i.Reg[0], i.Reg[1], i.Reg[2]) + case MinU: + mutator.MinU(i.Reg[0], i.Reg[1], i.Reg[2]) case Jump: mutator.Jump(i.Imm[0]) case Ecalli: @@ -817,6 +737,26 @@ func (i *Instruction) Mutate(mutator Mutator) (uint32, error) { mutator.MoveReg(i.Reg[0], i.Reg[1]) case Sbrk: return 0, mutator.Sbrk(i.Reg[0], i.Reg[1]) + case CountSetBits64: + mutator.CountSetBits64(i.Reg[0], i.Reg[1]) + case CountSetBits32: + mutator.CountSetBits32(i.Reg[0], i.Reg[1]) + case LeadingZeroBits64: + mutator.LeadingZeroBits64(i.Reg[0], i.Reg[1]) + case LeadingZeroBits32: + mutator.LeadingZeroBits32(i.Reg[0], i.Reg[1]) + case TrailingZeroBits64: + mutator.TrailingZeroBits64(i.Reg[0], i.Reg[1]) + case TrailingZeroBits32: + mutator.TrailingZeroBits32(i.Reg[0], i.Reg[1]) + case SignExtend8: + mutator.SignExtend8(i.Reg[0], i.Reg[1]) + case SignExtend16: + mutator.SignExtend16(i.Reg[0], i.Reg[1]) + case ZeroExtend16: + mutator.ZeroExtend16(i.Reg[0], i.Reg[1]) + case ReverseBytes: + mutator.ReverseBytes(i.Reg[0], i.Reg[1]) case LoadImmAndJumpIndirect: return 0, mutator.LoadImmAndJumpIndirect(i.Reg[0], i.Reg[1], i.Imm[0], i.Imm[1]) case LoadImm64: diff --git a/internal/polkavm/instructions_test.go b/internal/polkavm/instructions_test.go index e993808..522454a 100644 --- a/internal/polkavm/instructions_test.go +++ b/internal/polkavm/instructions_test.go @@ -133,6 +133,32 @@ func TestInstruction_Mutate(t *testing.T) { mutator.EXPECT().Jump(gomock.Any()).Times(1) mutator.EXPECT().JumpIndirect(gomock.Any(), gomock.Any()).Times(1) mutator.EXPECT().LoadImm64(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().CountSetBits64(gomock.Any(), gomock.Any()) + mutator.EXPECT().CountSetBits32(gomock.Any(), gomock.Any()) + mutator.EXPECT().LeadingZeroBits64(gomock.Any(), gomock.Any()) + mutator.EXPECT().LeadingZeroBits32(gomock.Any(), gomock.Any()) + mutator.EXPECT().TrailingZeroBits64(gomock.Any(), gomock.Any()) + mutator.EXPECT().TrailingZeroBits32(gomock.Any(), gomock.Any()) + mutator.EXPECT().SignExtend8(gomock.Any(), gomock.Any()) + mutator.EXPECT().SignExtend16(gomock.Any(), gomock.Any()) + mutator.EXPECT().ZeroExtend16(gomock.Any(), gomock.Any()) + mutator.EXPECT().ReverseBytes(gomock.Any(), gomock.Any()) + mutator.EXPECT().RotR64Imm(gomock.Any(), gomock.Any(), gomock.Any()) + mutator.EXPECT().RotR64ImmAlt(gomock.Any(), gomock.Any(), gomock.Any()) + mutator.EXPECT().RotR32Imm(gomock.Any(), gomock.Any(), gomock.Any()) + mutator.EXPECT().RotR32ImmAlt(gomock.Any(), gomock.Any(), gomock.Any()) + mutator.EXPECT().RotL64(gomock.Any(), gomock.Any(), gomock.Any()) + mutator.EXPECT().RotL32(gomock.Any(), gomock.Any(), gomock.Any()) + mutator.EXPECT().RotR64(gomock.Any(), gomock.Any(), gomock.Any()) + mutator.EXPECT().RotR32(gomock.Any(), gomock.Any(), gomock.Any()) + mutator.EXPECT().AndInv(gomock.Any(), gomock.Any(), gomock.Any()) + mutator.EXPECT().OrInv(gomock.Any(), gomock.Any(), gomock.Any()) + mutator.EXPECT().Xnor(gomock.Any(), gomock.Any(), gomock.Any()) + mutator.EXPECT().Max(gomock.Any(), gomock.Any(), gomock.Any()) + mutator.EXPECT().MaxU(gomock.Any(), gomock.Any(), gomock.Any()) + mutator.EXPECT().Min(gomock.Any(), gomock.Any(), gomock.Any()) + mutator.EXPECT().MinU(gomock.Any(), gomock.Any(), gomock.Any()) + for _, opcode := range allInstrOpcodes { instr := Instruction{ Opcode: opcode, diff --git a/internal/polkavm/interpreter/mutator.go b/internal/polkavm/interpreter/mutator.go index cf4e805..2b795e4 100644 --- a/internal/polkavm/interpreter/mutator.go +++ b/internal/polkavm/interpreter/mutator.go @@ -1,6 +1,7 @@ package interpreter import ( + "log" "math" "github.com/eigerco/strawberry/pkg/serialization/codec/jam" @@ -148,7 +149,36 @@ func (m *Mutator) Sbrk(dst polkavm.Reg, sizeReg polkavm.Reg) error { m.setNext32(dst, heapTop) return nil } - +func (m *Mutator) CountSetBits64(d polkavm.Reg, s polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) CountSetBits32(d polkavm.Reg, s polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) LeadingZeroBits64(d polkavm.Reg, s polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) LeadingZeroBits32(d polkavm.Reg, s polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) TrailingZeroBits64(d polkavm.Reg, s polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) TrailingZeroBits32(d polkavm.Reg, s polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) SignExtend8(d polkavm.Reg, s polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) SignExtend16(d polkavm.Reg, s polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) ZeroExtend16(d polkavm.Reg, s polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) ReverseBytes(d polkavm.Reg, s polkavm.Reg) { + panic("todo: implement") +} func (m *Mutator) MoveReg(d polkavm.Reg, s polkavm.Reg) { m.setNext32(d, m.get32(s)) } @@ -219,7 +249,7 @@ func (m *Mutator) ShiftArithmeticRightImm64(d polkavm.Reg, s1 polkavm.Reg, s2 ui m.setNext64(d, uint64(int64(m.get64(s1))>>s2)) } func (m *Mutator) ShiftArithmeticRightImmAlt32(d polkavm.Reg, s2 polkavm.Reg, s1 uint32) { - m.setNext32(d, uint32(int32(s1)>>m.get32(s2))) + m.setNext32(d, uint32(int32(uint32(s1))>>m.get32(s2))) } func (m *Mutator) ShiftArithmeticRightImmAlt64(d polkavm.Reg, s2 polkavm.Reg, s1 uint32) { m.setNext64(d, uint64(int64(s1)>>m.get64(s2))) @@ -237,7 +267,19 @@ func (m *Mutator) SetGreaterThanSignedImm(d polkavm.Reg, s1 polkavm.Reg, s2 uint m.setNext32(d, bool2uint32(int32(m.get32(s1)) > int32(s2))) } func (m *Mutator) ShiftLogicalRightImmAlt32(d polkavm.Reg, s2 polkavm.Reg, s1 uint32) { - m.setNext32(d, s1>>m.get32(s2)) + m.setNext32(d, uint32(s1)>>m.get32(s2)) +} +func (m *Mutator) RotR64Imm(d polkavm.Reg, c polkavm.Reg, s uint32) { + panic("todo: implement") +} +func (m *Mutator) RotR64ImmAlt(d polkavm.Reg, c polkavm.Reg, s uint32) { + panic("todo: implement") +} +func (m *Mutator) RotR32Imm(d polkavm.Reg, c polkavm.Reg, s uint32) { + panic("todo: implement") +} +func (m *Mutator) RotR32ImmAlt(d polkavm.Reg, c polkavm.Reg, s uint32) { + panic("todo: implement") } func (m *Mutator) ShiftLogicalRightImmAlt64(d polkavm.Reg, s2 polkavm.Reg, s1 uint32) { m.setNext32(d, s1>>m.get32(s2)) @@ -455,6 +497,39 @@ func (m *Mutator) CmovIfNotZero(d polkavm.Reg, s, c polkavm.Reg) { } m.instance.NextOffsets() } +func (m *Mutator) RotL64(d polkavm.Reg, s, c polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) RotL32(d polkavm.Reg, s, c polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) RotR64(d polkavm.Reg, s, c polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) RotR32(d polkavm.Reg, s, c polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) AndInv(d polkavm.Reg, s, c polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) OrInv(d polkavm.Reg, s, c polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) Xnor(d polkavm.Reg, s, c polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) Max(d polkavm.Reg, s, c polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) MaxU(d polkavm.Reg, s, c polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) Min(d polkavm.Reg, s, c polkavm.Reg) { + panic("todo: implement") +} +func (m *Mutator) MinU(d polkavm.Reg, s, c polkavm.Reg) { + panic("todo: implement") +} func (m *Mutator) CmovIfNotZeroImm(d polkavm.Reg, c polkavm.Reg, s uint32) { if m.get32(c) != 0 { m.set32(d, s) @@ -569,8 +644,10 @@ func (m *Mutator) LoadImmAndJumpIndirect(ra polkavm.Reg, base polkavm.Reg, value return m.djump(target) } func (m *Mutator) Jump(target uint32) { - m.instance.instructionOffset = target m.instance.startBasicBlock(m.program) + log.Println("target", target, (target>>31) == 1, (target<<1)>>1, m.instance.instructionIndex) + + m.branch(true, target) } func (m *Mutator) JumpIndirect(base polkavm.Reg, offset uint32) error { diff --git a/internal/polkavm/interpreter/utils.go b/internal/polkavm/interpreter/utils.go index 577b0e4..9eff567 100644 --- a/internal/polkavm/interpreter/utils.go +++ b/internal/polkavm/interpreter/utils.go @@ -30,8 +30,8 @@ func InvokeWholeProgram[X any](p []byte, entryPoint uint32, gas uint64, args []b return 0, nil, x, err } - result := make([]byte, regs[polkavm.A4]) - if err := memory1.Read(uint32(regs[polkavm.A3]), result); err != nil { + result := make([]byte, regs[polkavm.A0]) + if err := memory1.Read(uint32(regs[polkavm.A1]), result); err != nil { return 0, nil, x, err } diff --git a/internal/polkavm/mutator_mock.go b/internal/polkavm/mutator_mock.go index 3718171..1e65062 100644 --- a/internal/polkavm/mutator_mock.go +++ b/internal/polkavm/mutator_mock.go @@ -105,6 +105,18 @@ func (mr *MockMutatorMockRecorder) AndImm(arg0, arg1, arg2 interface{}) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AndImm", reflect.TypeOf((*MockMutator)(nil).AndImm), arg0, arg1, arg2) } +// AndInv mocks base method. +func (m *MockMutator) AndInv(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AndInv", arg0, arg1, arg2) +} + +// AndInv indicates an expected call of AndInv. +func (mr *MockMutatorMockRecorder) AndInv(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AndInv", reflect.TypeOf((*MockMutator)(nil).AndInv), arg0, arg1, arg2) +} + // BranchEq mocks base method. func (m *MockMutator) BranchEq(arg0, arg1 Reg, arg2 uint32) { m.ctrl.T.Helper() @@ -345,6 +357,30 @@ func (mr *MockMutatorMockRecorder) CmovIfZeroImm(arg0, arg1, arg2 interface{}) * return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CmovIfZeroImm", reflect.TypeOf((*MockMutator)(nil).CmovIfZeroImm), arg0, arg1, arg2) } +// CountSetBits32 mocks base method. +func (m *MockMutator) CountSetBits32(arg0, arg1 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "CountSetBits32", arg0, arg1) +} + +// CountSetBits32 indicates an expected call of CountSetBits32. +func (mr *MockMutatorMockRecorder) CountSetBits32(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CountSetBits32", reflect.TypeOf((*MockMutator)(nil).CountSetBits32), arg0, arg1) +} + +// CountSetBits64 mocks base method. +func (m *MockMutator) CountSetBits64(arg0, arg1 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "CountSetBits64", arg0, arg1) +} + +// CountSetBits64 indicates an expected call of CountSetBits64. +func (mr *MockMutatorMockRecorder) CountSetBits64(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CountSetBits64", reflect.TypeOf((*MockMutator)(nil).CountSetBits64), arg0, arg1) +} + // DivSigned32 mocks base method. func (m *MockMutator) DivSigned32(arg0, arg1, arg2 Reg) { m.ctrl.T.Helper() @@ -431,6 +467,30 @@ func (mr *MockMutatorMockRecorder) JumpIndirect(arg0, arg1 interface{}) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "JumpIndirect", reflect.TypeOf((*MockMutator)(nil).JumpIndirect), arg0, arg1) } +// LeadingZeroBits32 mocks base method. +func (m *MockMutator) LeadingZeroBits32(arg0, arg1 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "LeadingZeroBits32", arg0, arg1) +} + +// LeadingZeroBits32 indicates an expected call of LeadingZeroBits32. +func (mr *MockMutatorMockRecorder) LeadingZeroBits32(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LeadingZeroBits32", reflect.TypeOf((*MockMutator)(nil).LeadingZeroBits32), arg0, arg1) +} + +// LeadingZeroBits64 mocks base method. +func (m *MockMutator) LeadingZeroBits64(arg0, arg1 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "LeadingZeroBits64", arg0, arg1) +} + +// LeadingZeroBits64 indicates an expected call of LeadingZeroBits64. +func (mr *MockMutatorMockRecorder) LeadingZeroBits64(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LeadingZeroBits64", reflect.TypeOf((*MockMutator)(nil).LeadingZeroBits64), arg0, arg1) +} + // LoadI16 mocks base method. func (m *MockMutator) LoadI16(arg0 Reg, arg1 uint32) error { m.ctrl.T.Helper() @@ -677,6 +737,54 @@ func (mr *MockMutatorMockRecorder) LoadU8(arg0, arg1 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadU8", reflect.TypeOf((*MockMutator)(nil).LoadU8), arg0, arg1) } +// Max mocks base method. +func (m *MockMutator) Max(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Max", arg0, arg1, arg2) +} + +// Max indicates an expected call of Max. +func (mr *MockMutatorMockRecorder) Max(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Max", reflect.TypeOf((*MockMutator)(nil).Max), arg0, arg1, arg2) +} + +// MaxU mocks base method. +func (m *MockMutator) MaxU(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "MaxU", arg0, arg1, arg2) +} + +// MaxU indicates an expected call of MaxU. +func (mr *MockMutatorMockRecorder) MaxU(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MaxU", reflect.TypeOf((*MockMutator)(nil).MaxU), arg0, arg1, arg2) +} + +// Min mocks base method. +func (m *MockMutator) Min(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Min", arg0, arg1, arg2) +} + +// Min indicates an expected call of Min. +func (mr *MockMutatorMockRecorder) Min(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Min", reflect.TypeOf((*MockMutator)(nil).Min), arg0, arg1, arg2) +} + +// MinU mocks base method. +func (m *MockMutator) MinU(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "MinU", arg0, arg1, arg2) +} + +// MinU indicates an expected call of MinU. +func (mr *MockMutatorMockRecorder) MinU(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MinU", reflect.TypeOf((*MockMutator)(nil).MinU), arg0, arg1, arg2) +} + // MoveReg mocks base method. func (m *MockMutator) MoveReg(arg0, arg1 Reg) { m.ctrl.T.Helper() @@ -821,6 +929,18 @@ func (mr *MockMutatorMockRecorder) OrImm(arg0, arg1, arg2 interface{}) *gomock.C return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OrImm", reflect.TypeOf((*MockMutator)(nil).OrImm), arg0, arg1, arg2) } +// OrInv mocks base method. +func (m *MockMutator) OrInv(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "OrInv", arg0, arg1, arg2) +} + +// OrInv indicates an expected call of OrInv. +func (mr *MockMutatorMockRecorder) OrInv(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OrInv", reflect.TypeOf((*MockMutator)(nil).OrInv), arg0, arg1, arg2) +} + // RemSigned32 mocks base method. func (m *MockMutator) RemSigned32(arg0, arg1, arg2 Reg) { m.ctrl.T.Helper() @@ -869,6 +989,114 @@ func (mr *MockMutatorMockRecorder) RemUnsigned64(arg0, arg1, arg2 interface{}) * return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemUnsigned64", reflect.TypeOf((*MockMutator)(nil).RemUnsigned64), arg0, arg1, arg2) } +// ReverseBytes mocks base method. +func (m *MockMutator) ReverseBytes(arg0, arg1 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ReverseBytes", arg0, arg1) +} + +// ReverseBytes indicates an expected call of ReverseBytes. +func (mr *MockMutatorMockRecorder) ReverseBytes(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReverseBytes", reflect.TypeOf((*MockMutator)(nil).ReverseBytes), arg0, arg1) +} + +// RotL32 mocks base method. +func (m *MockMutator) RotL32(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RotL32", arg0, arg1, arg2) +} + +// RotL32 indicates an expected call of RotL32. +func (mr *MockMutatorMockRecorder) RotL32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RotL32", reflect.TypeOf((*MockMutator)(nil).RotL32), arg0, arg1, arg2) +} + +// RotL64 mocks base method. +func (m *MockMutator) RotL64(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RotL64", arg0, arg1, arg2) +} + +// RotL64 indicates an expected call of RotL64. +func (mr *MockMutatorMockRecorder) RotL64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RotL64", reflect.TypeOf((*MockMutator)(nil).RotL64), arg0, arg1, arg2) +} + +// RotR32 mocks base method. +func (m *MockMutator) RotR32(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RotR32", arg0, arg1, arg2) +} + +// RotR32 indicates an expected call of RotR32. +func (mr *MockMutatorMockRecorder) RotR32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RotR32", reflect.TypeOf((*MockMutator)(nil).RotR32), arg0, arg1, arg2) +} + +// RotR32Imm mocks base method. +func (m *MockMutator) RotR32Imm(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RotR32Imm", arg0, arg1, arg2) +} + +// RotR32Imm indicates an expected call of RotR32Imm. +func (mr *MockMutatorMockRecorder) RotR32Imm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RotR32Imm", reflect.TypeOf((*MockMutator)(nil).RotR32Imm), arg0, arg1, arg2) +} + +// RotR32ImmAlt mocks base method. +func (m *MockMutator) RotR32ImmAlt(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RotR32ImmAlt", arg0, arg1, arg2) +} + +// RotR32ImmAlt indicates an expected call of RotR32ImmAlt. +func (mr *MockMutatorMockRecorder) RotR32ImmAlt(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RotR32ImmAlt", reflect.TypeOf((*MockMutator)(nil).RotR32ImmAlt), arg0, arg1, arg2) +} + +// RotR64 mocks base method. +func (m *MockMutator) RotR64(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RotR64", arg0, arg1, arg2) +} + +// RotR64 indicates an expected call of RotR64. +func (mr *MockMutatorMockRecorder) RotR64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RotR64", reflect.TypeOf((*MockMutator)(nil).RotR64), arg0, arg1, arg2) +} + +// RotR64Imm mocks base method. +func (m *MockMutator) RotR64Imm(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RotR64Imm", arg0, arg1, arg2) +} + +// RotR64Imm indicates an expected call of RotR64Imm. +func (mr *MockMutatorMockRecorder) RotR64Imm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RotR64Imm", reflect.TypeOf((*MockMutator)(nil).RotR64Imm), arg0, arg1, arg2) +} + +// RotR64ImmAlt mocks base method. +func (m *MockMutator) RotR64ImmAlt(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RotR64ImmAlt", arg0, arg1, arg2) +} + +// RotR64ImmAlt indicates an expected call of RotR64ImmAlt. +func (mr *MockMutatorMockRecorder) RotR64ImmAlt(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RotR64ImmAlt", reflect.TypeOf((*MockMutator)(nil).RotR64ImmAlt), arg0, arg1, arg2) +} + // Sbrk mocks base method. func (m *MockMutator) Sbrk(arg0, arg1 Reg) error { m.ctrl.T.Helper() @@ -1171,6 +1399,30 @@ func (mr *MockMutatorMockRecorder) ShiftLogicalRightImmAlt64(arg0, arg1, arg2 in return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftLogicalRightImmAlt64", reflect.TypeOf((*MockMutator)(nil).ShiftLogicalRightImmAlt64), arg0, arg1, arg2) } +// SignExtend16 mocks base method. +func (m *MockMutator) SignExtend16(arg0, arg1 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SignExtend16", arg0, arg1) +} + +// SignExtend16 indicates an expected call of SignExtend16. +func (mr *MockMutatorMockRecorder) SignExtend16(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SignExtend16", reflect.TypeOf((*MockMutator)(nil).SignExtend16), arg0, arg1) +} + +// SignExtend8 mocks base method. +func (m *MockMutator) SignExtend8(arg0, arg1 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SignExtend8", arg0, arg1) +} + +// SignExtend8 indicates an expected call of SignExtend8. +func (mr *MockMutatorMockRecorder) SignExtend8(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SignExtend8", reflect.TypeOf((*MockMutator)(nil).SignExtend8), arg0, arg1) +} + // StoreImmIndirectU16 mocks base method. func (m *MockMutator) StoreImmIndirectU16(arg0 Reg, arg1, arg2 uint32) error { m.ctrl.T.Helper() @@ -1419,6 +1671,30 @@ func (mr *MockMutatorMockRecorder) Sub64(arg0, arg1, arg2 interface{}) *gomock.C return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Sub64", reflect.TypeOf((*MockMutator)(nil).Sub64), arg0, arg1, arg2) } +// TrailingZeroBits32 mocks base method. +func (m *MockMutator) TrailingZeroBits32(arg0, arg1 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "TrailingZeroBits32", arg0, arg1) +} + +// TrailingZeroBits32 indicates an expected call of TrailingZeroBits32. +func (mr *MockMutatorMockRecorder) TrailingZeroBits32(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TrailingZeroBits32", reflect.TypeOf((*MockMutator)(nil).TrailingZeroBits32), arg0, arg1) +} + +// TrailingZeroBits64 mocks base method. +func (m *MockMutator) TrailingZeroBits64(arg0, arg1 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "TrailingZeroBits64", arg0, arg1) +} + +// TrailingZeroBits64 indicates an expected call of TrailingZeroBits64. +func (mr *MockMutatorMockRecorder) TrailingZeroBits64(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TrailingZeroBits64", reflect.TypeOf((*MockMutator)(nil).TrailingZeroBits64), arg0, arg1) +} + // Trap mocks base method. func (m *MockMutator) Trap() error { m.ctrl.T.Helper() @@ -1433,6 +1709,18 @@ func (mr *MockMutatorMockRecorder) Trap() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Trap", reflect.TypeOf((*MockMutator)(nil).Trap)) } +// Xnor mocks base method. +func (m *MockMutator) Xnor(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Xnor", arg0, arg1, arg2) +} + +// Xnor indicates an expected call of Xnor. +func (mr *MockMutatorMockRecorder) Xnor(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Xnor", reflect.TypeOf((*MockMutator)(nil).Xnor), arg0, arg1, arg2) +} + // Xor mocks base method. func (m *MockMutator) Xor(arg0, arg1, arg2 Reg) { m.ctrl.T.Helper() @@ -1456,3 +1744,15 @@ func (mr *MockMutatorMockRecorder) XorImm(arg0, arg1, arg2 interface{}) *gomock. mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "XorImm", reflect.TypeOf((*MockMutator)(nil).XorImm), arg0, arg1, arg2) } + +// ZeroExtend16 mocks base method. +func (m *MockMutator) ZeroExtend16(arg0, arg1 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ZeroExtend16", arg0, arg1) +} + +// ZeroExtend16 indicates an expected call of ZeroExtend16. +func (mr *MockMutatorMockRecorder) ZeroExtend16(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ZeroExtend16", reflect.TypeOf((*MockMutator)(nil).ZeroExtend16), arg0, arg1) +} diff --git a/internal/polkavm/program.go b/internal/polkavm/program.go index 4ba758f..ffa32ce 100644 --- a/internal/polkavm/program.go +++ b/internal/polkavm/program.go @@ -355,7 +355,7 @@ func parseInstruction(code, bitmask []byte, instructionOffset int) (int, Instruc if opcode == LoadImm64 { reg1 := min(12, code[0]&0b1111) imm := uint64(0) - if err := jam.Unmarshal(code[1:9], imm); err != nil { + if err := jam.Unmarshal(code[1:9], &imm); err != nil { return 0, Instruction{}, err } return nextOffset, Instruction{ @@ -367,10 +367,12 @@ func parseInstruction(code, bitmask []byte, instructionOffset int) (int, Instruc }, nil } + log.Println("opcode", opcode) regs, imm, err := parseArgsTable[opcode](chunk[1:], uint32(instructionOffset), uint32(len(chunk[1:]))) if err != nil { return 0, Instruction{}, err } + log.Println("opcode, regs, imm", opcode, regs, imm) return nextOffset, Instruction{ Opcode: opcode, Reg: regs, diff --git a/internal/polkavm/program_test.go b/internal/polkavm/program_test.go index 737b59e..64d49bb 100644 --- a/internal/polkavm/program_test.go +++ b/internal/polkavm/program_test.go @@ -1,3 +1,5 @@ +//go:build integration + package polkavm import (