From acdd66f90d020b3ea8d623cb7d4cf74eea79a74c Mon Sep 17 00:00:00 2001 From: Daniel Vladco Date: Thu, 28 Nov 2024 13:14:20 +0200 Subject: [PATCH] feat: add 64 bit opcodes and uint64 registers (#146) * feat: add 64 bit opcodes and uint64 registers * fix: host func casting --- go.mod | 3 +- go.sum | 15 +- internal/polkavm/common.go | 71 +- .../polkavm/host_call/accumulate_functions.go | 28 +- .../host_call/accumulate_functions_test.go | 42 +- internal/polkavm/host_call/common.go | 24 +- .../polkavm/host_call/general_functions.go | 67 +- .../host_call/general_functions_test.go | 54 +- internal/polkavm/instructions.go | 548 ++++--- internal/polkavm/instructions_test.go | 152 ++ internal/polkavm/interpreter/instance.go | 2 +- .../polkavm/interpreter/interpreter_test.go | 12 +- internal/polkavm/interpreter/mutator.go | 304 ++-- internal/polkavm/interpreter/utils.go | 2 +- internal/polkavm/mutator_mock.go | 1458 +++++++++++++++++ internal/polkavm/program_test.go | 8 +- internal/statetransition/accumulate.go | 2 +- internal/statetransition/on_transfer.go | 2 +- tests/integration/pvm_integration_test.go | 2 +- 19 files changed, 2343 insertions(+), 453 deletions(-) create mode 100644 internal/polkavm/instructions_test.go create mode 100644 internal/polkavm/mutator_mock.go diff --git a/go.mod b/go.mod index fc67826..746580a 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,8 @@ go 1.22.5 require ( github.com/cockroachdb/pebble v1.1.0 github.com/ebitengine/purego v0.8.1 - github.com/stretchr/testify v1.9.0 + github.com/golang/mock v1.6.0 + github.com/stretchr/testify v1.10.0 golang.org/x/crypto v0.27.0 ) diff --git a/go.sum b/go.sum index cfe07d0..13f22ee 100644 --- a/go.sum +++ b/go.sum @@ -27,6 +27,8 @@ github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxI github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -59,10 +61,11 @@ github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3c github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -72,20 +75,27 @@ golang.org/x/exp v0.0.0-20240110193028-0dcbfd608b1e h1:723BNChdd0c2Wk6WOE320qGBi golang.org/x/exp v0.0.0-20240110193028-0dcbfd608b1e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= @@ -94,6 +104,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/polkavm/common.go b/internal/polkavm/common.go index 9e4b631..b66435b 100644 --- a/internal/polkavm/common.go +++ b/internal/polkavm/common.go @@ -78,13 +78,14 @@ func (m *Memory) Write(address uint32, data []byte) error { return nil } -type Registers [13]uint32 +type Registers [13]uint64 type Gas int64 // HostCall the generic Ω function definition Ωx(n, ϱ, ω, μ, x) defined in section A.6 type HostCall[X any] func(hostCall uint32, gasCounter Gas, regs Registers, mem Memory, x X) (Gas, Registers, Memory, X, error) +//go:generate go run github.com/golang/mock/mockgen --destination mutator_mock.go --package polkavm . Mutator type Mutator interface { Trap() error Fallthrough() @@ -108,40 +109,57 @@ type Mutator interface { BranchGreaterSignedImm(s1 Reg, s2 uint32, target uint32) SetLessThanUnsignedImm(d Reg, s1 Reg, s2 uint32) SetLessThanSignedImm(d Reg, s1 Reg, s2 uint32) - ShiftLogicalLeftImm(d Reg, s1 Reg, s2 uint32) - ShiftArithmeticRightImm(d Reg, s1 Reg, s2 uint32) - ShiftArithmeticRightImmAlt(d Reg, s1 Reg, s2 uint32) - NegateAndAddImm(d Reg, s1 Reg, s2 uint32) + ShiftLogicalLeftImm32(d Reg, s1 Reg, s2 uint32) + ShiftLogicalLeftImm64(d Reg, s1 Reg, s2 uint32) + ShiftArithmeticRightImm32(d Reg, s1 Reg, s2 uint32) + ShiftArithmeticRightImm64(d Reg, s1 Reg, s2 uint32) + ShiftArithmeticRightImmAlt32(d Reg, s1 Reg, s2 uint32) + ShiftArithmeticRightImmAlt64(d Reg, s1 Reg, s2 uint32) + NegateAndAddImm32(d Reg, s1 Reg, s2 uint32) + NegateAndAddImm64(d Reg, s1 Reg, s2 uint32) SetGreaterThanUnsignedImm(d Reg, s1 Reg, s2 uint32) SetGreaterThanSignedImm(d Reg, s1 Reg, s2 uint32) - ShiftLogicalRightImmAlt(d Reg, s1 Reg, s2 uint32) - ShiftLogicalLeftImmAlt(d Reg, s1 Reg, s2 uint32) - Add(d Reg, s1, s2 Reg) - AddImm(d Reg, s1 Reg, s2 uint32) - Sub(d Reg, s1, s2 Reg) + ShiftLogicalRightImmAlt32(d Reg, s1 Reg, s2 uint32) + ShiftLogicalRightImmAlt64(d Reg, s1 Reg, s2 uint32) + ShiftLogicalLeftImmAlt32(d Reg, s1 Reg, s2 uint32) + ShiftLogicalLeftImmAlt64(d Reg, s1 Reg, s2 uint32) + Add32(d Reg, s1, s2 Reg) + Add64(d Reg, s1, s2 Reg) + AddImm32(d Reg, s1 Reg, s2 uint32) + AddImm64(d Reg, s1 Reg, s2 uint32) + Sub32(d Reg, s1, s2 Reg) + Sub64(d Reg, s1, s2 Reg) And(d Reg, s1, s2 Reg) AndImm(d Reg, s1 Reg, s2 uint32) Xor(d Reg, s1, s2 Reg) XorImm(d Reg, s1 Reg, s2 uint32) Or(d Reg, s1, s2 Reg) OrImm(d Reg, s1 Reg, s2 uint32) - Mul(d Reg, s1, s2 Reg) - MulImm(d Reg, s1 Reg, s2 uint32) + Mul32(d Reg, s1, s2 Reg) + Mul64(d Reg, s1, s2 Reg) + MulImm32(d Reg, s1 Reg, s2 uint32) + MulImm64(d Reg, s1 Reg, s2 uint32) MulUpperSignedSigned(d Reg, s1, s2 Reg) - MulUpperSignedSignedImm(d Reg, s1 Reg, s2 uint32) MulUpperUnsignedUnsigned(d Reg, s1, s2 Reg) - MulUpperUnsignedUnsignedImm(d Reg, s1 Reg, s2 uint32) MulUpperSignedUnsigned(d Reg, s1, s2 Reg) SetLessThanUnsigned(d Reg, s1, s2 Reg) SetLessThanSigned(d Reg, s1, s2 Reg) - ShiftLogicalLeft(d Reg, s1, s2 Reg) - ShiftLogicalRight(d Reg, s1, s2 Reg) - ShiftLogicalRightImm(d Reg, s1 Reg, s2 uint32) - ShiftArithmeticRight(d Reg, s1, s2 Reg) - DivUnsigned(d Reg, s1, s2 Reg) - DivSigned(d Reg, s1, s2 Reg) - RemUnsigned(d Reg, s1, s2 Reg) - RemSigned(d Reg, s1, s2 Reg) + ShiftLogicalLeft32(d Reg, s1, s2 Reg) + ShiftLogicalLeft64(d Reg, s1, s2 Reg) + ShiftLogicalRight32(d Reg, s1, s2 Reg) + ShiftLogicalRight64(d Reg, s1, s2 Reg) + ShiftLogicalRightImm32(d Reg, s1 Reg, s2 uint32) + ShiftLogicalRightImm64(d Reg, s1 Reg, s2 uint32) + ShiftArithmeticRight32(d Reg, s1, s2 Reg) + ShiftArithmeticRight64(d Reg, s1, s2 Reg) + DivUnsigned32(d Reg, s1, s2 Reg) + DivUnsigned64(d Reg, s1, s2 Reg) + DivSigned32(d Reg, s1, s2 Reg) + DivSigned64(d Reg, s1, s2 Reg) + RemUnsigned32(d Reg, s1, s2 Reg) + RemUnsigned64(d Reg, s1, s2 Reg) + RemSigned32(d Reg, s1, s2 Reg) + RemSigned64(d Reg, s1, s2 Reg) CmovIfZero(d Reg, s, c Reg) CmovIfZeroImm(d Reg, c Reg, s uint32) CmovIfNotZero(d Reg, s, c Reg) @@ -149,26 +167,35 @@ type Mutator interface { StoreU8(src Reg, offset uint32) error StoreU16(src Reg, offset uint32) error StoreU32(src Reg, offset uint32) error + StoreU64(src Reg, offset uint32) error StoreImmU8(offset uint32, value uint32) error StoreImmU16(offset uint32, value uint32) error StoreImmU32(offset uint32, value uint32) error + StoreImmU64(offset uint32, value uint32) error StoreImmIndirectU8(base Reg, offset uint32, value uint32) error StoreImmIndirectU16(base Reg, offset uint32, value uint32) error StoreImmIndirectU32(base Reg, offset uint32, value uint32) error + StoreImmIndirectU64(base Reg, offset uint32, value uint32) error StoreIndirectU8(src Reg, base Reg, offset uint32) error StoreIndirectU16(src Reg, base Reg, offset uint32) error StoreIndirectU32(src Reg, base Reg, offset uint32) error + StoreIndirectU64(src Reg, base Reg, offset uint32) error LoadU8(dst Reg, offset uint32) error LoadI8(dst Reg, offset uint32) error LoadU16(dst Reg, offset uint32) error LoadI16(dst Reg, offset uint32) error LoadU32(dst Reg, offset uint32) error + LoadI32(dst Reg, offset uint32) error + LoadU64(dst Reg, offset uint32) error LoadIndirectU8(dst Reg, base Reg, offset uint32) error LoadIndirectI8(dst Reg, base Reg, offset uint32) error LoadIndirectU16(dst Reg, base Reg, offset uint32) error LoadIndirectI16(dst Reg, base Reg, offset uint32) error LoadIndirectU32(dst Reg, base Reg, offset uint32) error + LoadIndirectI32(dst Reg, base Reg, offset uint32) error + LoadIndirectU64(dst Reg, base Reg, offset uint32) error LoadImm(dst Reg, imm uint32) + LoadImm64(dst Reg, imm uint64) LoadImmAndJump(ra Reg, value uint32, target uint32) LoadImmAndJumpIndirect(ra Reg, base Reg, value, offset uint32) error Jump(target uint32) diff --git a/internal/polkavm/host_call/accumulate_functions.go b/internal/polkavm/host_call/accumulate_functions.go index 57a6093..0d2cfdf 100644 --- a/internal/polkavm/host_call/accumulate_functions.go +++ b/internal/polkavm/host_call/accumulate_functions.go @@ -23,12 +23,12 @@ func Bless(gas Gas, regs Registers, mem Memory, ctxPair AccumulateContextPair) ( // let [m, a, v, o, n] = ω7...12 managerServiceId, assignServiceId, designateServiceId, addr, servicesNr := regs[A0], regs[A1], regs[A2], regs[A3], regs[A4] // let g = {(s ↦ g) where E4(s) ⌢ E8(g) = μ_o+12i⋅⋅⋅+12 | i ∈ Nn} if Zo⋅⋅⋅+12n ⊂ Vμ otherwise ∇ - for i := range servicesNr { - serviceId, err := readNumber[block.ServiceId](mem, addr+(12*i), 4) + for i := range uint32(servicesNr) { + serviceId, err := readNumber[block.ServiceId](mem, uint32(addr)+(12*i), 4) if err != nil { return gas, withCode(regs, OOB), mem, ctxPair, err } - serviceGas, err := readNumber[uint64](mem, addr+(12*i)+4, 8) + serviceGas, err := readNumber[uint64](mem, uint32(addr)+(12*i)+4, 8) if err != nil { return gas, withCode(regs, OOB), mem, ctxPair, err } @@ -54,12 +54,12 @@ func Assign(gas Gas, regs Registers, mem Memory, ctxPair AccumulateContextPair) // let o = ω8 addr := regs[A1] core := regs[A0] - if core >= uint32(common.TotalNumberOfCores) { + if core >= uint64(common.TotalNumberOfCores) { return gas, withCode(regs, CORE), mem, ctxPair, nil } for i := 0; i < state.PendingAuthorizersQueueSize; i++ { bytes := make([]byte, 32) - if err := mem.Read(addr+uint32(32*i), bytes); err != nil { + if err := mem.Read(uint32(addr)+uint32(32*i), bytes); err != nil { return gas, withCode(regs, OOB), mem, ctxPair, nil } ctxPair.RegularCtx.AccumulationState.WorkReportsQueue[core][i] = crypto.Hash(bytes) @@ -84,7 +84,7 @@ func Designate(gas Gas, regs Registers, mem Memory, ctxPair AccumulateContextPai addr := regs[A0] for i := 0; i < common.NumberOfValidators; i++ { bytes := make([]byte, 336) - if err := mem.Read(addr+uint32(336*i), bytes); err != nil { + if err := mem.Read(uint32(addr)+uint32(336*i), bytes); err != nil { return gas, withCode(regs, OOB), mem, ctxPair, nil } @@ -109,7 +109,7 @@ func Checkpoint(gas Gas, regs Registers, mem Memory, ctxPair AccumulateContextPa ctxPair.ExceptionalCtx = ctxPair.RegularCtx // Set the new ϱ' value into ω′7 - regs[A0] = uint32(gas & ((1 << 32) - 1)) + regs[A0] = uint64(gas & ((1 << 32) - 1)) return gas, regs, mem, ctxPair, nil } @@ -126,7 +126,7 @@ func New(gas Gas, regs Registers, mem Memory, ctxPair AccumulateContextPair) (Ga // c = μo⋅⋅⋅+32 if No⋅⋅⋅+32 ⊂ Vμ otherwise ∇ codeHashBytes := make([]byte, 32) - if err := mem.Read(addr, codeHashBytes); err != nil { + if err := mem.Read(uint32(addr), codeHashBytes); err != nil { return gas, withCode(regs, OOB), mem, ctxPair, nil } @@ -149,7 +149,7 @@ func New(gas Gas, regs Registers, mem Memory, ctxPair AccumulateContextPair) (Ga // if a ≠ ∇ ∧ b ≥ (xs)t if b >= ctxPair.RegularCtx.ServiceAccount().ThresholdBalance() { - regs[A0] = uint32(ctxPair.RegularCtx.ServiceId) + regs[A0] = uint64(ctxPair.RegularCtx.ServiceId) currentAccount := ctxPair.RegularCtx.ServiceAccount() currentAccount.Balance = b ctxPair.RegularCtx.ServiceState[ctxPair.RegularCtx.ServiceId] = currentAccount @@ -176,7 +176,7 @@ func Upgrade(gas Gas, regs Registers, mem Memory, ctxPair AccumulateContextPair) // c = μo⋅⋅⋅+32 if No⋅⋅⋅+32 ⊂ Vμ otherwise ∇ codeHash := make([]byte, 32) - if err := mem.Read(addr, codeHash); err != nil { + if err := mem.Read(uint32(addr), codeHash); err != nil { return gas, withCode(regs, OOB), mem, ctxPair, nil } @@ -202,7 +202,7 @@ func Transfer(gas Gas, regs Registers, mem Memory, ctxPair AccumulateContextPair // m = μo⋅⋅⋅+M if No⋅⋅⋅+M ⊂ Vμ otherwise ∇ m := make([]byte, service.TransferMemoSizeBytes) - if err := mem.Read(o, m); err != nil { + if err := mem.Read(uint32(o), m); err != nil { return gas, withCode(regs, OK), mem, ctxPair, nil } @@ -263,7 +263,7 @@ func Quit(gas Gas, regs Registers, mem Memory, ctxPair AccumulateContextPair) (G // m = E−1(μo⋅⋅⋅+M) memo := make([]byte, service.TransferMemoSizeBytes) - if err := mem.Read(addr, memo); err != nil { + if err := mem.Read(uint32(addr), memo); err != nil { return gas, withCode(regs, OOB), mem, ctxPair, nil } @@ -309,7 +309,7 @@ func Solicit(gas Gas, regs Registers, mem Memory, ctxPair AccumulateContextPair, addr, preimageLength := regs[A0], regs[A1] // let h = μo⋅⋅⋅+32 if Zo⋅⋅⋅+32 ⊂ Vμ otherwise ∇ preimageHashBytes := make([]byte, 32) - if err := mem.Read(addr, preimageHashBytes); err != nil { + if err := mem.Read(uint32(addr), preimageHashBytes); err != nil { return gas, withCode(regs, OOB), mem, ctxPair, nil } @@ -350,7 +350,7 @@ func Forget(gas Gas, regs Registers, mem Memory, ctxPair AccumulateContextPair, // let h = μo⋅⋅⋅+32 if Zo⋅⋅⋅+32 ⊂ Vμ otherwise ∇ preimageHashBytes := make([]byte, 32) - if err := mem.Read(addr, preimageHashBytes); err != nil { + if err := mem.Read(uint32(addr), preimageHashBytes); err != nil { return gas, withCode(regs, OOB), mem, ctxPair, nil } diff --git a/internal/polkavm/host_call/accumulate_functions_test.go b/internal/polkavm/host_call/accumulate_functions_test.go index b91021a..e3e6f84 100644 --- a/internal/polkavm/host_call/accumulate_functions_test.go +++ b/internal/polkavm/host_call/accumulate_functions_test.go @@ -91,7 +91,7 @@ func TestAccumulate(t *testing.T) { A4: 3, }, expectedDeltaRegs: deltaRegs{ - A0: uint32(OK), + A0: uint64(OK), }, initialGas: 100, @@ -122,7 +122,7 @@ func TestAccumulate(t *testing.T) { initialGas: 100, expectedGas: 88, expectedDeltaRegs: deltaRegs{ - A0: uint32(OK), + A0: uint64(OK), }, expectedX: AccumulateContext{ AccumulationState: state.AccumulationState{ @@ -141,7 +141,7 @@ func TestAccumulate(t *testing.T) { initialGas: 100, expectedGas: 88, expectedDeltaRegs: deltaRegs{ - A0: uint32(OK), + A0: uint64(OK), }, expectedX: AccumulateContext{ AccumulationState: state.AccumulationState{ @@ -166,7 +166,7 @@ func TestAccumulate(t *testing.T) { }, initialRegs: deltaRegs{A1: 123123, A2: 123124123, A3: 756846353}, expectedDeltaRegs: deltaRegs{ - A0: uint32(currentServiceID), + A0: uint64(currentServiceID), }, initialGas: 100, expectedGas: 88, @@ -214,7 +214,7 @@ func TestAccumulate(t *testing.T) { }, initialRegs: deltaRegs{A1: 3453453453, A2: 456456456}, expectedDeltaRegs: deltaRegs{ - A0: uint32(OK), + A0: uint64(OK), }, initialGas: 100, expectedGas: 88, @@ -242,7 +242,7 @@ func TestAccumulate(t *testing.T) { A2: 80, // g }, expectedDeltaRegs: deltaRegs{ - A0: uint32(OK), + A0: uint64(OK), }, initialGas: 1000000100, expectedGas: 88, @@ -293,7 +293,7 @@ func TestAccumulate(t *testing.T) { A0: 1234, // d: receiver address }, expectedDeltaRegs: deltaRegs{ - A0: uint32(OK), + A0: uint64(OK), }, initialGas: 100, expectedGas: 88, @@ -379,7 +379,7 @@ func TestAccumulate(t *testing.T) { initialGas: 100, expectedGas: 88, expectedDeltaRegs: deltaRegs{ - A0: uint32(OK), + A0: uint64(OK), }, X: AccumulateContext{ ServiceId: currentServiceID, @@ -414,7 +414,7 @@ func TestAccumulate(t *testing.T) { initialGas: 100, expectedGas: 88, expectedDeltaRegs: deltaRegs{ - A0: uint32(OK), + A0: uint64(OK), }, X: AccumulateContext{ ServiceId: currentServiceID, @@ -451,7 +451,7 @@ func TestAccumulate(t *testing.T) { initialGas: 100, expectedGas: 88, expectedDeltaRegs: deltaRegs{ - A0: uint32(HUH), + A0: uint64(HUH), }, X: AccumulateContext{ ServiceId: currentServiceID, @@ -488,7 +488,7 @@ func TestAccumulate(t *testing.T) { initialGas: 100, expectedGas: 88, expectedDeltaRegs: deltaRegs{ - A0: uint32(FULL), + A0: uint64(FULL), }, X: AccumulateContext{ ServiceId: currentServiceID, @@ -515,7 +515,7 @@ func TestAccumulate(t *testing.T) { fn: fnTms(Forget), alloc: alloc{A0: hash2bytes(randomHash)}, initialRegs: deltaRegs{A1: 123}, - expectedDeltaRegs: deltaRegs{A0: uint32(OK)}, + expectedDeltaRegs: deltaRegs{A0: uint64(OK)}, initialGas: 100, expectedGas: 88, X: AccumulateContext{ @@ -547,7 +547,7 @@ func TestAccumulate(t *testing.T) { fn: fnTms(Forget), alloc: alloc{A0: hash2bytes(randomHash)}, initialRegs: deltaRegs{A1: 123}, - expectedDeltaRegs: deltaRegs{A0: uint32(OK)}, + expectedDeltaRegs: deltaRegs{A0: uint64(OK)}, initialGas: 100, expectedGas: 88, timeslot: randomTimeslot2, @@ -582,7 +582,7 @@ func TestAccumulate(t *testing.T) { fn: fnTms(Forget), alloc: alloc{A0: hash2bytes(randomHash)}, initialRegs: deltaRegs{A1: 123}, - expectedDeltaRegs: deltaRegs{A0: uint32(OK)}, + expectedDeltaRegs: deltaRegs{A0: uint64(OK)}, initialGas: 100, expectedGas: 88, timeslot: randomTimeslot2 + jamtime.PreimageExpulsionPeriod + 1, @@ -615,7 +615,7 @@ func TestAccumulate(t *testing.T) { fn: fnTms(Forget), alloc: alloc{A0: hash2bytes(randomHash)}, initialRegs: deltaRegs{A1: 123}, - expectedDeltaRegs: deltaRegs{A0: uint32(OK)}, + expectedDeltaRegs: deltaRegs{A0: uint64(OK)}, initialGas: 100, expectedGas: 88, timeslot: randomTimeslot2 + jamtime.PreimageExpulsionPeriod + 1, @@ -655,7 +655,7 @@ func TestAccumulate(t *testing.T) { mem := memoryMap.NewMemory(nil, nil, nil) initialRegs := Registers{ RA: VmAddressReturnToHost, - SP: memoryMap.StackAddressHigh, + SP: uint64(memoryMap.StackAddressHigh), } stackAddress := memoryMap.StackAddressLow for addrReg, v := range tc.alloc { @@ -663,7 +663,7 @@ func TestAccumulate(t *testing.T) { err = mem.Write(stackAddress, v) require.NoError(t, err) - initialRegs[addrReg] = stackAddress + initialRegs[addrReg] = uint64(stackAddress) stackAddress = stackAddress + uint32(len(v)) } for i, v := range tc.initialRegs { @@ -685,7 +685,7 @@ func TestAccumulate(t *testing.T) { expectedRegs := initialRegs for i, reg := range tc.expectedDeltaRegs { - expectedRegs[i] = reg + expectedRegs[i] = uint64(reg) } assert.Equal(t, expectedRegs, regs) assert.Equal(t, tc.expectedGas, gasRemaining) @@ -697,7 +697,7 @@ func TestAccumulate(t *testing.T) { type hostCall func(Gas, Registers, Memory, AccumulateContextPair, jamtime.Timeslot) (Gas, Registers, Memory, AccumulateContextPair, error) type alloc map[Reg][]byte -type deltaRegs map[Reg]uint32 +type deltaRegs map[Reg]uint64 func fixedSizeBytes(size int, b []byte) []byte { bb := make([]byte, size) @@ -706,8 +706,8 @@ func fixedSizeBytes(size int, b []byte) []byte { } func checkUint64(t *testing.T, gas uint64) deltaRegs { - a0 := uint32(math.Mod(float64(gas), 1<<32)) - a1 := uint32(math.Floor(float64(gas) / (1 << 32))) + a0 := uint64(math.Mod(float64(gas), 1<<32)) + a1 := uint64(math.Floor(float64(gas) / (1 << 32))) assert.Equal(t, gas, uint64(a1)<<32|uint64(a0)) return deltaRegs{ A0: a0, diff --git a/internal/polkavm/host_call/common.go b/internal/polkavm/host_call/common.go index 545552d..6813998 100644 --- a/internal/polkavm/host_call/common.go +++ b/internal/polkavm/host_call/common.go @@ -43,19 +43,19 @@ const ( ForgetID = 14 ) -type Code uint32 +type Code uint64 const ( - NONE Code = math.MaxUint32 - WHAT Code = math.MaxUint32 - 1 - OOB Code = math.MaxUint32 - 2 - WHO Code = math.MaxUint32 - 3 - FULL Code = math.MaxUint32 - 4 - CORE Code = math.MaxUint32 - 5 - CASH Code = math.MaxUint32 - 6 - LOW Code = math.MaxUint32 - 7 - HIGH Code = math.MaxUint32 - 8 - HUH Code = math.MaxUint32 - 9 + NONE Code = math.MaxUint64 + WHAT Code = math.MaxUint64 - 1 + OOB Code = math.MaxUint64 - 2 + WHO Code = math.MaxUint64 - 3 + FULL Code = math.MaxUint64 - 4 + CORE Code = math.MaxUint64 - 5 + CASH Code = math.MaxUint64 - 6 + LOW Code = math.MaxUint64 - 7 + HIGH Code = math.MaxUint64 - 8 + HUH Code = math.MaxUint64 - 9 OK Code = 0 ) @@ -98,6 +98,6 @@ func readNumber[U interface{ ~uint32 | ~uint64 }](mem Memory, addr uint32, lengt } func withCode(regs Registers, s Code) Registers { - regs[A0] = uint32(s) + regs[A0] = uint64(s) return regs } diff --git a/internal/polkavm/host_call/general_functions.go b/internal/polkavm/host_call/general_functions.go index 8b711d0..709716e 100644 --- a/internal/polkavm/host_call/general_functions.go +++ b/internal/polkavm/host_call/general_functions.go @@ -28,7 +28,7 @@ func GasRemaining(gas polkavm.Gas, regs polkavm.Registers) (polkavm.Gas, polkavm gas -= GasRemainingCost // Set the new ϱ' value into ω′7 - regs[polkavm.A0] = uint32(gas) + regs[polkavm.A0] = uint64(gas) return gas, regs, nil } @@ -44,12 +44,12 @@ func Lookup(gas polkavm.Gas, regs polkavm.Registers, mem polkavm.Memory, s servi // Determine the lookup key 'a' a := s - if uint64(omega7) != math.MaxUint64 && omega7 != uint32(serviceId) { + if uint64(omega7) != math.MaxUint64 && omega7 != uint64(serviceId) { var exists bool // Lookup service account by serviceId in the serviceState a, exists = serviceState[serviceId] if !exists { - regs[polkavm.A0] = uint32(NONE) + regs[polkavm.A0] = uint64(NONE) return gas, regs, mem, nil } } @@ -58,10 +58,9 @@ func Lookup(gas polkavm.Gas, regs polkavm.Registers, mem polkavm.Memory, s servi // Ensure the memory range is valid for hashing (µho..ho+32) memorySlice := make([]byte, 32) - err := mem.Read(ho, memorySlice) + err := mem.Read(uint32(ho), memorySlice) if err != nil { - regs[polkavm.A0] = uint32(OOB) - return gas, regs, mem, err + return gas, withCode(regs, OOB), mem, err } // Compute the hash H(µho..ho+32) @@ -70,8 +69,7 @@ func Lookup(gas polkavm.Gas, regs polkavm.Registers, mem polkavm.Memory, s servi // Lookup value in storage (v) using the hash v, exists := a.Storage[hash] if !exists { - regs[polkavm.A0] = uint32(NONE) - return gas, regs, mem, nil + return gas, withCode(regs, NONE), mem, nil } bo := regs[polkavm.A2] @@ -79,16 +77,14 @@ func Lookup(gas polkavm.Gas, regs polkavm.Registers, mem polkavm.Memory, s servi // Write value to memory if within bounds if len(v) > 0 && len(v) <= int(bz) { - if err = mem.Write(bo, v); err != nil { - regs[polkavm.A0] = uint32(OOB) - return gas, regs, mem, err + if err = mem.Write(uint32(bo), v); err != nil { + return gas, withCode(regs, OOB), mem, err } } else { - regs[polkavm.A0] = uint32(OOB) - return gas, regs, mem, err + return gas, withCode(regs, OOB), mem, err } - regs[polkavm.A0] = uint32(len(v)) + regs[polkavm.A0] = uint64(len(v)) return gas, regs, mem, err } @@ -106,7 +102,7 @@ func Read(gas polkavm.Gas, regs polkavm.Registers, mem polkavm.Memory, s service bz := regs[polkavm.A4] a := s - if uint64(omega7) != math.MaxUint64 && omega7 != uint32(serviceId) { + if uint64(omega7) != math.MaxUint64 && omega7 != uint64(serviceId) { var exists bool a, exists = serviceState[block.ServiceId(omega7)] if !exists { @@ -116,10 +112,9 @@ func Read(gas polkavm.Gas, regs polkavm.Registers, mem polkavm.Memory, s service // read key data from memory at ko..ko+kz keyData := make([]byte, kz) - err := mem.Read(ko, keyData) + err := mem.Read(uint32(ko), keyData) if err != nil { - regs[polkavm.A0] = uint32(OOB) - return gas, regs, mem, nil + return gas, withCode(regs, OOB), mem, nil } serviceIdBytes, err := jam.Marshal(omega7) @@ -137,24 +132,21 @@ func Read(gas polkavm.Gas, regs polkavm.Registers, mem polkavm.Memory, s service v, exists := a.Storage[k] if !exists { - regs[polkavm.A0] = uint32(NONE) - return gas, regs, mem, nil + return gas, withCode(regs, NONE), mem, nil } writeLen := int(math.Min(float64(bz), float64(len(v)))) if writeLen > 0 { - if err = mem.Write(bo, v[:writeLen]); err != nil { - regs[polkavm.A0] = uint32(OOB) - return gas, regs, mem, nil + if err = mem.Write(uint32(bo), v[:writeLen]); err != nil { + return gas, withCode(regs, OOB), mem, nil } - regs[polkavm.A0] = uint32(len(v)) + regs[polkavm.A0] = uint64(len(v)) return gas, regs, mem, nil } - regs[polkavm.A0] = uint32(NONE) - return gas, regs, mem, nil + return gas, withCode(regs, NONE), mem, nil } // Write ΩW(ϱ, ω, μ, s, s) @@ -170,7 +162,7 @@ func Write(gas polkavm.Gas, regs polkavm.Registers, mem polkavm.Memory, s servic vz := regs[polkavm.A3] keyData := make([]byte, kz) - err := mem.Read(ko, keyData) + err := mem.Read(uint32(ko), keyData) if err != nil { return gas, regs, mem, s, err } @@ -187,10 +179,9 @@ func Write(gas polkavm.Gas, regs polkavm.Registers, mem polkavm.Memory, s servic delete(a.Storage, k) } else { valueData := make([]byte, vz) - err := mem.Read(vo, valueData) + err := mem.Read(uint32(vo), valueData) if err != nil { - regs[polkavm.A0] = uint32(OOB) - return gas, regs, mem, s, err + return gas, withCode(regs, OOB), mem, s, err } a.Storage[k] = valueData @@ -198,17 +189,15 @@ func Write(gas polkavm.Gas, regs polkavm.Registers, mem polkavm.Memory, s servic storageItem, ok := s.Storage[k] if !ok { - regs[polkavm.A0] = uint32(NONE) - return gas, regs, mem, s, err + return gas, withCode(regs, NONE), mem, s, err } if a.ThresholdBalance() > a.Balance { - regs[polkavm.A0] = uint32(FULL) - return gas, regs, mem, s, err + return gas, withCode(regs, FULL), mem, s, err } // otherwise a.ThresholdBalance() <= a.Balance - regs[polkavm.A0] = uint32(len(storageItem)) // l + regs[polkavm.A0] = uint64(len(storageItem)) // l return gas, regs, mem, a, err // return service account 'a' as opposed to 's' for not successful paths } @@ -246,11 +235,9 @@ func Info(gas polkavm.Gas, regs polkavm.Registers, mem polkavm.Memory, serviceId return gas, regs, mem, polkavm.ErrPanicf(err.Error()) } - if err := mem.Write(omega8, m); err != nil { - regs[polkavm.A0] = uint32(OOB) - return gas, regs, mem, nil + if err := mem.Write(uint32(omega8), m); err != nil { + return gas, withCode(regs, OOB), mem, nil } - regs[polkavm.A0] = uint32(OK) - return gas, regs, mem, nil + return gas, withCode(regs, OK), mem, nil } diff --git a/internal/polkavm/host_call/general_functions_test.go b/internal/polkavm/host_call/general_functions_test.go index bd0c3ca..f30f777 100644 --- a/internal/polkavm/host_call/general_functions_test.go +++ b/internal/polkavm/host_call/general_functions_test.go @@ -65,7 +65,7 @@ func TestLookup(t *testing.T) { t.Run("service_not_found", func(t *testing.T) { initialRegs := polkavm.Registers{ polkavm.RA: polkavm.VmAddressReturnToHost, - polkavm.SP: memoryMap.StackAddressHigh, + polkavm.SP: uint64(memoryMap.StackAddressHigh), } mem := memoryMap.NewMemory(nil, nil, nil) initialGas := uint64(100) @@ -77,7 +77,7 @@ func TestLookup(t *testing.T) { gasRemaining, regs, _, _, err := interpreter.InvokeHostCall(pp, memoryMap, 0, initialGas, initialRegs, mem, hostCall, service.ServiceAccount{}) require.ErrorIs(t, err, polkavm.ErrHalt) - assert.Equal(t, uint32(host_call.NONE), regs[polkavm.A0]) + assert.Equal(t, uint64(host_call.NONE), regs[polkavm.A0]) assert.Equal(t, polkavm.Gas(initialGas)-host_call.LookupCost-polkavm.GasCosts[polkavm.JumpIndirect]-polkavm.GasCosts[polkavm.Ecalli], gasRemaining) }) @@ -96,10 +96,10 @@ func TestLookup(t *testing.T) { initialRegs := polkavm.Registers{ polkavm.RA: polkavm.VmAddressReturnToHost, - polkavm.SP: memoryMap.StackAddressHigh, - polkavm.A0: uint32(serviceId), - polkavm.A1: ho, - polkavm.A2: bo, + polkavm.SP: uint64(memoryMap.StackAddressHigh), + polkavm.A0: uint64(serviceId), + polkavm.A1: uint64(ho), + polkavm.A2: uint64(bo), polkavm.A3: 32, } sa := service.ServiceAccount{ @@ -124,7 +124,7 @@ func TestLookup(t *testing.T) { require.NoError(t, err) assert.Equal(t, val, actualValue) - assert.Equal(t, uint32(len(val)), regs[polkavm.A0]) + assert.Equal(t, uint64(len(val)), regs[polkavm.A0]) assert.Equal(t, polkavm.Gas(initialGas)-host_call.LookupCost-polkavm.GasCosts[polkavm.Ecalli]-polkavm.GasCosts[polkavm.JumpIndirect], gasRemaining) }) } @@ -145,7 +145,7 @@ func TestRead(t *testing.T) { value := []byte("value_to_read") // Compute the hash H(E4(s) || keyData) - serviceIdBytes, err := jam.Marshal(serviceId) + serviceIdBytes, err := jam.Marshal(uint64(serviceId)) require.NoError(t, err) hashInput := make([]byte, 0, len(serviceIdBytes)+len(keyData)) @@ -170,12 +170,12 @@ func TestRead(t *testing.T) { bz := uint32(32) initialRegs := polkavm.Registers{ polkavm.RA: polkavm.VmAddressReturnToHost, - polkavm.SP: memoryMap.StackAddressHigh, - polkavm.A0: uint32(serviceId), - polkavm.A1: ko, - polkavm.A2: kz, - polkavm.A3: bo, - polkavm.A4: bz, + polkavm.SP: uint64(memoryMap.StackAddressHigh), + polkavm.A0: uint64(serviceId), + polkavm.A1: uint64(ko), + polkavm.A2: uint64(kz), + polkavm.A3: uint64(bo), + polkavm.A4: uint64(bz), } mem := memoryMap.NewMemory(nil, nil, nil) err = mem.Write(ko, keyData) @@ -192,12 +192,12 @@ func TestRead(t *testing.T) { actualValue := make([]byte, len(value)) err = mem.Read(bo, actualValue) require.NoError(t, err) - require.Equal(t, value, actualValue) - require.Equal(t, uint32(len(value)), regs[polkavm.A0]) + assert.Equal(t, value, actualValue) + assert.Equal(t, uint64(len(value)), regs[polkavm.A0]) expectedGasRemaining := polkavm.Gas(initialGas) - host_call.ReadCost - polkavm.GasCosts[polkavm.Ecalli] - polkavm.GasCosts[polkavm.JumpIndirect] - require.Equal(t, expectedGasRemaining, gasRemaining) + assert.Equal(t, expectedGasRemaining, gasRemaining) } func TestWrite(t *testing.T) { @@ -238,11 +238,11 @@ func TestWrite(t *testing.T) { initialRegs := polkavm.Registers{ polkavm.RA: polkavm.VmAddressReturnToHost, - polkavm.SP: memoryMap.StackAddressHigh, - polkavm.A0: ko, - polkavm.A1: kz, - polkavm.A2: vo, - polkavm.A3: vz, + polkavm.SP: uint64(memoryMap.StackAddressHigh), + polkavm.A0: uint64(ko), + polkavm.A1: uint64(kz), + polkavm.A2: uint64(vo), + polkavm.A3: uint64(vz), } mem := memoryMap.NewMemory(nil, nil, nil) err = mem.Write(ko, keyData) @@ -267,7 +267,7 @@ func TestWrite(t *testing.T) { require.NoError(t, err) require.Equal(t, keyData, actualKey) - require.Equal(t, uint32(len(value)), regs[polkavm.A0]) + require.Equal(t, uint64(len(value)), regs[polkavm.A0]) require.NotNil(t, sa) storedValue, keyExists := sa.Storage[k] require.True(t, keyExists) @@ -317,9 +317,9 @@ func TestInfo(t *testing.T) { mem := memoryMap.NewMemory(nil, nil, nil) initialRegs := polkavm.Registers{ polkavm.RA: polkavm.VmAddressReturnToHost, - polkavm.SP: memoryMap.StackAddressHigh, - polkavm.A0: uint32(serviceId), - polkavm.A1: omega1, + polkavm.SP: uint64(memoryMap.StackAddressHigh), + polkavm.A0: uint64(serviceId), + polkavm.A1: uint64(omega1), } hostCall := func(hostCall uint32, gasCounter polkavm.Gas, regs polkavm.Registers, mem polkavm.Memory, x service.ServiceAccount) (polkavm.Gas, polkavm.Registers, polkavm.Memory, service.ServiceAccount, error) { gasCounter, regs, mem, err = host_call.Info(gasCounter, regs, mem, serviceId, serviceState) @@ -329,7 +329,7 @@ func TestInfo(t *testing.T) { gasRemaining, regs, _, _, err := interpreter.InvokeHostCall(pp, memoryMap, 0, initialGas, initialRegs, mem, hostCall, sampleAccount) require.ErrorIs(t, err, polkavm.ErrHalt) - require.Equal(t, uint32(host_call.OK), regs[polkavm.A0]) + require.Equal(t, uint64(host_call.OK), regs[polkavm.A0]) var accountInfo host_call.AccountInfo m, err := jam.Marshal(accountInfo) diff --git a/internal/polkavm/instructions.go b/internal/polkavm/instructions.go index 2f2bb31..9162480 100644 --- a/internal/polkavm/instructions.go +++ b/internal/polkavm/instructions.go @@ -2,117 +2,162 @@ package polkavm import ( "encoding/binary" + "fmt" ) type Opcode byte const ( - Trap Opcode = 0 - Fallthrough Opcode = 17 - - 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 - - LoadImmAndJump Opcode = 6 - BranchEqImm Opcode = 7 - BranchNotEqImm Opcode = 15 - BranchLessUnsignedImm Opcode = 44 - BranchLessSignedImm Opcode = 32 - BranchGreaterOrEqualUnsignedImm Opcode = 52 - BranchGreaterOrEqualSignedImm Opcode = 45 - BranchLessOrEqualSignedImm Opcode = 46 - BranchLessOrEqualUnsignedImm Opcode = 59 - BranchGreaterSignedImm Opcode = 53 - BranchGreaterUnsignedImm Opcode = 50 - - StoreImmIndirectU8 Opcode = 26 - StoreImmIndirectU16 Opcode = 54 - StoreImmIndirectU32 Opcode = 13 - - StoreIndirectU8 Opcode = 16 - StoreIndirectU16 Opcode = 29 - StoreIndirectU32 Opcode = 3 - LoadIndirectU8 Opcode = 11 - LoadIndirectI8 Opcode = 21 - LoadIndirectU16 Opcode = 37 - LoadIndirectI16 Opcode = 33 - LoadIndirectU32 Opcode = 1 - AddImm Opcode = 2 - AndImm Opcode = 18 - XorImm Opcode = 31 - OrImm Opcode = 49 - MulImm Opcode = 35 - MulUpperSignedSignedImm Opcode = 65 - MulUpperUnsignedUnsignedImm Opcode = 63 - SetLessThanUnsignedImm Opcode = 27 - SetLessThanSignedImm Opcode = 56 - ShiftLogicalLeftImm Opcode = 9 - ShiftLogicalRightImm Opcode = 14 - ShiftArithmeticRightImm Opcode = 25 - NegateAndAddImm Opcode = 40 - SetGreaterThanUnsignedImm Opcode = 39 - SetGreaterThanSignedImm Opcode = 61 - ShiftLogicalRightImmAlt Opcode = 72 - ShiftArithmeticRightImmAlt Opcode = 80 - ShiftLogicalLeftImmAlt 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 - - Add Opcode = 8 - Sub Opcode = 20 - And Opcode = 23 - Xor Opcode = 28 - Or Opcode = 12 - Mul Opcode = 34 - MulUpperSignedSigned Opcode = 67 - MulUpperUnsignedUnsigned Opcode = 57 - MulUpperSignedUnsigned Opcode = 81 - SetLessThanUnsigned Opcode = 36 - SetLessThanSigned Opcode = 58 - ShiftLogicalLeft Opcode = 55 - ShiftLogicalRight Opcode = 51 - ShiftArithmeticRight Opcode = 77 - DivUnsigned Opcode = 68 - DivSigned Opcode = 64 - RemUnsigned Opcode = 73 - RemSigned Opcode = 70 - - CmovIfZero Opcode = 83 - CmovIfNotZero Opcode = 84 + // A.5.1. Instructions without Arguments + Trap Opcode = 0 // trap = 0 + Fallthrough Opcode = 17 // fallthrough = 1 - Jump Opcode = 5 + // A.5.2. Instructions with Arguments of One Immediate. + Ecalli Opcode = 78 // ecalli = 10 - Ecalli Opcode = 78 + // A.5.3. Instructions with Arguments of One Register and One Extended Width Immediate. + LoadImm64 = 255 - 20 // load_imm_64 = 20 - StoreImmU8 Opcode = 62 - StoreImmU16 Opcode = 79 - StoreImmU32 Opcode = 38 + // 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 - MoveReg Opcode = 82 - Sbrk Opcode = 87 + // A.5.5. Instructions with Arguments of One Offset. + Jump Opcode = 5 - LoadImmAndJumpIndirect Opcode = 42 + // 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, + Ecalli: 1, + StoreImmU8: 1, + StoreImmU16: 1, + StoreImmU32: 1, + StoreImmU64: 1, + Jump: 1, JumpIndirect: 1, LoadImm: 1, LoadU8: 1, @@ -120,85 +165,104 @@ var GasCosts = map[Opcode]Gas{ LoadU16: 1, LoadI16: 1, LoadU32: 1, + LoadI32: 1, + LoadU64: 1, StoreU8: 1, StoreU16: 1, StoreU32: 1, + StoreU64: 1, + StoreImmIndirectU8: 1, + StoreImmIndirectU16: 1, + StoreImmIndirectU32: 1, + StoreImmIndirectU64: 1, LoadImmAndJump: 1, BranchEqImm: 1, BranchNotEqImm: 1, BranchLessUnsignedImm: 1, - BranchLessSignedImm: 1, + BranchLessOrEqualUnsignedImm: 1, BranchGreaterOrEqualUnsignedImm: 1, - BranchGreaterOrEqualSignedImm: 1, + BranchGreaterUnsignedImm: 1, + BranchLessSignedImm: 1, BranchLessOrEqualSignedImm: 1, - BranchLessOrEqualUnsignedImm: 1, + BranchGreaterOrEqualSignedImm: 1, BranchGreaterSignedImm: 1, - BranchGreaterUnsignedImm: 1, - StoreImmIndirectU8: 1, - StoreImmIndirectU16: 1, - StoreImmIndirectU32: 1, + MoveReg: 1, + Sbrk: 1, StoreIndirectU8: 1, StoreIndirectU16: 1, StoreIndirectU32: 1, + StoreIndirectU64: 1, LoadIndirectU8: 1, LoadIndirectI8: 1, LoadIndirectU16: 1, LoadIndirectI16: 1, LoadIndirectU32: 1, - AddImm: 1, + LoadIndirectI32: 1, + LoadIndirectU64: 1, + AddImm32: 1, AndImm: 1, XorImm: 1, OrImm: 1, - MulImm: 1, - MulUpperSignedSignedImm: 1, - MulUpperUnsignedUnsignedImm: 1, + MulImm32: 1, SetLessThanUnsignedImm: 1, SetLessThanSignedImm: 1, - ShiftLogicalLeftImm: 1, - ShiftLogicalRightImm: 1, - ShiftArithmeticRightImm: 1, - NegateAndAddImm: 1, + ShiftLogicalLeftImm32: 1, + ShiftLogicalRightImm32: 1, + ShiftArithmeticRightImm32: 1, + NegateAndAddImm32: 1, SetGreaterThanUnsignedImm: 1, SetGreaterThanSignedImm: 1, - ShiftLogicalRightImmAlt: 1, - ShiftArithmeticRightImmAlt: 1, - ShiftLogicalLeftImmAlt: 1, + ShiftLogicalRightImmAlt32: 1, + ShiftArithmeticRightImmAlt32: 1, + ShiftLogicalLeftImmAlt32: 1, CmovIfZeroImm: 1, CmovIfNotZeroImm: 1, + AddImm64: 1, + MulImm64: 1, + ShiftLogicalLeftImm64: 1, + ShiftLogicalRightImm64: 1, + ShiftArithmeticRightImm64: 1, + NegateAndAddImm64: 1, + ShiftLogicalLeftImmAlt64: 1, + ShiftLogicalRightImmAlt64: 1, + ShiftArithmeticRightImmAlt64: 1, BranchEq: 1, BranchNotEq: 1, BranchLessUnsigned: 1, BranchLessSigned: 1, BranchGreaterOrEqualUnsigned: 1, BranchGreaterOrEqualSigned: 1, - Add: 1, - Sub: 1, + LoadImmAndJumpIndirect: 1, + Add32: 1, + Sub32: 1, + Mul32: 1, + DivUnsigned32: 1, + DivSigned32: 1, + RemUnsigned32: 1, + RemSigned32: 1, + ShiftLogicalLeft32: 1, + ShiftLogicalRight32: 1, + ShiftArithmeticRight32: 1, + Add64: 1, + Sub64: 1, + Mul64: 1, + DivUnsigned64: 1, + DivSigned64: 1, + RemUnsigned64: 1, + RemSigned64: 1, + ShiftLogicalLeft64: 1, + ShiftLogicalRight64: 1, + ShiftArithmeticRight64: 1, And: 1, Xor: 1, Or: 1, - Mul: 1, MulUpperSignedSigned: 1, MulUpperUnsignedUnsigned: 1, MulUpperSignedUnsigned: 1, SetLessThanUnsigned: 1, SetLessThanSigned: 1, - ShiftLogicalLeft: 1, - ShiftLogicalRight: 1, - ShiftArithmeticRight: 1, - DivUnsigned: 1, - DivSigned: 1, - RemUnsigned: 1, - RemSigned: 1, CmovIfZero: 1, CmovIfNotZero: 1, - Jump: 1, - Ecalli: 1, - StoreImmU8: 1, - StoreImmU16: 1, - StoreImmU32: 1, - MoveReg: 1, - Sbrk: 1, - LoadImmAndJumpIndirect: 1, } type Reg uint @@ -290,30 +354,63 @@ func parseReg(v byte) Reg { } var ( - // Instructions with args: none + // Instructions without Arguments instrNone = []Opcode{Trap, Fallthrough} - // Instructions with args: reg, imm - instrRegImm = []Opcode{JumpIndirect, LoadImm, LoadU8, LoadI8, LoadU16, LoadI16, LoadU32, StoreU8, StoreU16, StoreU32} - // Instructions with args: reg, imm, offset - instrRegImmOffset = []Opcode{LoadImmAndJump, BranchEqImm, BranchNotEqImm, BranchLessUnsignedImm, BranchLessSignedImm, BranchGreaterOrEqualUnsignedImm, BranchGreaterOrEqualSignedImm, BranchLessOrEqualSignedImm, BranchLessOrEqualUnsignedImm, BranchGreaterSignedImm, BranchGreaterUnsignedImm} - // Instructions with args: reg, imm, imm - instrRegImm2 = []Opcode{StoreImmIndirectU8, StoreImmIndirectU16, StoreImmIndirectU32} - // Instructions with args: reg, reg, imm - instrReg2Imm = []Opcode{StoreIndirectU8, StoreIndirectU16, StoreIndirectU32, LoadIndirectU8, LoadIndirectI8, LoadIndirectU16, LoadIndirectI16, LoadIndirectU32, AddImm, AndImm, XorImm, OrImm, MulImm, MulUpperSignedSignedImm, MulUpperUnsignedUnsignedImm, SetLessThanUnsignedImm, SetLessThanSignedImm, ShiftLogicalLeftImm, ShiftLogicalRightImm, ShiftArithmeticRightImm, NegateAndAddImm, SetGreaterThanUnsignedImm, SetGreaterThanSignedImm, ShiftLogicalRightImmAlt, ShiftArithmeticRightImmAlt, ShiftLogicalLeftImmAlt, CmovIfZeroImm, CmovIfNotZeroImm} - // Instructions with args: reg, reg, offset - instrReg2Offset = []Opcode{BranchEq, BranchNotEq, BranchLessUnsigned, BranchLessSigned, BranchGreaterOrEqualUnsigned, BranchGreaterOrEqualSigned} - // Instructions with args: reg, reg, reg - instrReg3 = []Opcode{Add, Sub, And, Xor, Or, Mul, MulUpperSignedSigned, MulUpperUnsignedUnsigned, MulUpperSignedUnsigned, SetLessThanUnsigned, SetLessThanSigned, ShiftLogicalLeft, ShiftLogicalRight, ShiftArithmeticRight, DivUnsigned, DivSigned, RemUnsigned, RemSigned, CmovIfZero, CmovIfNotZero} - // Instructions with args: offset - instrOffset = []Opcode{Jump} - // Instructions with args: imm + // Instructions with Arguments of One Immediate. instrImm = []Opcode{Ecalli} - // Instructions with args: imm, imm - instrImm2 = []Opcode{StoreImmU8, StoreImmU16, StoreImmU32} - // Instructions with args: reg, reg + // Instructions with Arguments of One Register and One Extended Width Immediate. + instrRegImmExt = []Opcode{LoadImm64} + // Instructions with Arguments of Two Immediates. + instrImm2 = []Opcode{StoreImmU8, StoreImmU16, StoreImmU32, StoreImmU64} + // Instructions with Arguments of One Offset. + instrOffset = []Opcode{Jump} + // Instructions with Arguments of One Register & One Immediate. + instrRegImm = []Opcode{ + JumpIndirect, LoadImm, LoadU8, LoadI8, LoadU16, LoadI16, LoadU32, LoadI32, LoadU64, + StoreU8, StoreU16, StoreU32, StoreU64, + } + // Instructions with Arguments of One Register & Two Immediates. + instrRegImm2 = []Opcode{StoreImmIndirectU8, StoreImmIndirectU16, StoreImmIndirectU32, StoreImmIndirectU64} + // Instructions with Arguments of One Register, One Immediate and One Offset. + instrRegImmOffset = []Opcode{ + LoadImmAndJump, BranchEqImm, BranchNotEqImm, BranchLessUnsignedImm, BranchLessOrEqualUnsignedImm, + BranchGreaterOrEqualUnsignedImm, BranchGreaterUnsignedImm, BranchLessSignedImm, + BranchLessOrEqualSignedImm, BranchGreaterOrEqualSignedImm, BranchGreaterSignedImm, + } + // Instructions with Arguments of Two Registers. instrRegReg = []Opcode{MoveReg, Sbrk} - // Instructions with args: reg, reg, imm, imm + // Instructions with Arguments of Two Registers & One Immediate. + instrReg2Imm = []Opcode{ + StoreIndirectU8, StoreIndirectU16, StoreIndirectU32, StoreIndirectU64, + LoadIndirectU8, LoadIndirectI8, LoadIndirectU16, LoadIndirectI16, + LoadIndirectU32, LoadIndirectI32, LoadIndirectU64, + AddImm32, AndImm, XorImm, OrImm, MulImm32, + SetLessThanUnsignedImm, SetLessThanSignedImm, + ShiftLogicalLeftImm32, ShiftLogicalRightImm32, ShiftArithmeticRightImm32, + NegateAndAddImm32, SetGreaterThanUnsignedImm, SetGreaterThanSignedImm, + ShiftLogicalRightImmAlt32, ShiftArithmeticRightImmAlt32, ShiftLogicalLeftImmAlt32, + CmovIfZeroImm, CmovIfNotZeroImm, + AddImm64, MulImm64, + ShiftLogicalLeftImm64, ShiftLogicalRightImm64, ShiftArithmeticRightImm64, + NegateAndAddImm64, + ShiftLogicalLeftImmAlt64, ShiftLogicalRightImmAlt64, ShiftArithmeticRightImmAlt64, + } + // Instructions with Arguments of Two Registers & One Offset. + instrReg2Offset = []Opcode{ + BranchEq, BranchNotEq, BranchLessUnsigned, BranchLessSigned, + BranchGreaterOrEqualUnsigned, BranchGreaterOrEqualSigned, + } + // Instruction with Arguments of Two Registers and Two Immediates. instrReg2Imm2 = []Opcode{LoadImmAndJumpIndirect} + // Instructions with Arguments of Three Registers. + instrReg3 = []Opcode{ + Add32, Sub32, Mul32, DivUnsigned32, DivSigned32, RemUnsigned32, RemSigned32, + ShiftLogicalLeft32, ShiftLogicalRight32, ShiftArithmeticRight32, + Add64, Sub64, Mul64, DivUnsigned64, DivSigned64, RemUnsigned64, RemSigned64, + ShiftLogicalLeft64, ShiftLogicalRight64, ShiftArithmeticRight64, + And, Xor, Or, MulUpperSignedSigned, MulUpperUnsignedUnsigned, MulUpperSignedUnsigned, + SetLessThanUnsigned, SetLessThanSigned, CmovIfZero, CmovIfNotZero, + } ) type InstrParseArgFunc func(chunk []byte, instructionOffset, argsLength uint32) ([]Reg, []uint32) @@ -357,6 +454,12 @@ func init() { for _, code := range instrReg2Imm2 { parseArgsTable[code] = parseArgsRegs2Imm2 } + for _, code := range instrRegImmExt { + parseArgsTable[code] = func(chunk []byte, instructionOffset, argsLength uint32) ([]Reg, []uint32) { + // TODO parse extended immediate + return nil, nil + } + } } func clamp(start, end, value uint32) uint32 { @@ -484,6 +587,7 @@ func parseArgsRegs2Offset(code []byte, instructionOffset, skip uint32) ([]Reg, [ type Instruction struct { Opcode Opcode Imm []uint32 + ExtImm uint64 Reg []Reg Offset uint32 Length uint32 @@ -509,12 +613,18 @@ func (i *Instruction) Mutate(mutator Mutator) (uint32, error) { return 0, mutator.LoadI16(i.Reg[0], i.Imm[0]) case LoadU32: return 0, mutator.LoadU32(i.Reg[0], i.Imm[0]) + case LoadI32: + return 0, mutator.LoadI32(i.Reg[0], i.Imm[0]) + case LoadU64: + return 0, mutator.LoadU64(i.Reg[0], i.Imm[0]) case StoreU8: return 0, mutator.StoreU8(i.Reg[0], i.Imm[0]) case StoreU16: return 0, mutator.StoreU16(i.Reg[0], i.Imm[0]) case StoreU32: return 0, mutator.StoreU32(i.Reg[0], i.Imm[0]) + case StoreU64: + return 0, mutator.StoreU64(i.Reg[0], i.Imm[0]) case LoadImmAndJump: mutator.LoadImmAndJump(i.Reg[0], i.Imm[0], i.Imm[1]) case BranchEqImm: @@ -543,12 +653,16 @@ func (i *Instruction) Mutate(mutator Mutator) (uint32, error) { return 0, mutator.StoreImmIndirectU16(i.Reg[0], i.Imm[0], i.Imm[1]) case StoreImmIndirectU32: return 0, mutator.StoreImmIndirectU32(i.Reg[0], i.Imm[0], i.Imm[1]) + case StoreImmIndirectU64: + return 0, mutator.StoreImmIndirectU64(i.Reg[0], i.Imm[0], i.Imm[1]) case StoreIndirectU8: return 0, mutator.StoreIndirectU8(i.Reg[0], i.Reg[1], i.Imm[0]) case StoreIndirectU16: return 0, mutator.StoreIndirectU16(i.Reg[0], i.Reg[1], i.Imm[0]) case StoreIndirectU32: return 0, mutator.StoreIndirectU32(i.Reg[0], i.Reg[1], i.Imm[0]) + case StoreIndirectU64: + return 0, mutator.StoreIndirectU64(i.Reg[0], i.Reg[1], i.Imm[0]) case LoadIndirectU8: return 0, mutator.LoadIndirectU8(i.Reg[0], i.Reg[1], i.Imm[0]) case LoadIndirectI8: @@ -559,43 +673,60 @@ func (i *Instruction) Mutate(mutator Mutator) (uint32, error) { return 0, mutator.LoadIndirectI16(i.Reg[0], i.Reg[1], i.Imm[0]) case LoadIndirectU32: return 0, mutator.LoadIndirectU32(i.Reg[0], i.Reg[1], i.Imm[0]) - case AddImm: - - mutator.AddImm(i.Reg[0], i.Reg[1], i.Imm[0]) + case LoadIndirectI32: + return 0, mutator.LoadIndirectI32(i.Reg[0], i.Reg[1], i.Imm[0]) + case LoadIndirectU64: + return 0, mutator.LoadIndirectU64(i.Reg[0], i.Reg[1], i.Imm[0]) + case AddImm32: + mutator.AddImm32(i.Reg[0], i.Reg[1], i.Imm[0]) + case AddImm64: + mutator.AddImm64(i.Reg[0], i.Reg[1], i.Imm[0]) case AndImm: mutator.AndImm(i.Reg[0], i.Reg[1], i.Imm[0]) case XorImm: mutator.XorImm(i.Reg[0], i.Reg[1], i.Imm[0]) case OrImm: mutator.OrImm(i.Reg[0], i.Reg[1], i.Imm[0]) - case MulImm: - mutator.MulImm(i.Reg[0], i.Reg[1], i.Imm[0]) - case MulUpperSignedSignedImm: - mutator.MulUpperSignedSignedImm(i.Reg[0], i.Reg[1], i.Imm[0]) - case MulUpperUnsignedUnsignedImm: - mutator.MulUpperUnsignedUnsignedImm(i.Reg[0], i.Reg[1], i.Imm[0]) + case MulImm32: + mutator.MulImm32(i.Reg[0], i.Reg[1], i.Imm[0]) + case MulImm64: + mutator.MulImm64(i.Reg[0], i.Reg[1], i.Imm[0]) case SetLessThanUnsignedImm: mutator.SetLessThanUnsignedImm(i.Reg[0], i.Reg[1], i.Imm[0]) case SetLessThanSignedImm: mutator.SetLessThanSignedImm(i.Reg[0], i.Reg[1], i.Imm[0]) - case ShiftLogicalLeftImm: - mutator.ShiftLogicalLeftImm(i.Reg[0], i.Reg[1], i.Imm[0]) - case ShiftLogicalRightImm: - mutator.ShiftLogicalRightImm(i.Reg[0], i.Reg[1], i.Imm[0]) - case ShiftArithmeticRightImm: - mutator.ShiftArithmeticRightImm(i.Reg[0], i.Reg[1], i.Imm[0]) - case NegateAndAddImm: - mutator.NegateAndAddImm(i.Reg[0], i.Reg[1], i.Imm[0]) + case ShiftLogicalLeftImm32: + mutator.ShiftLogicalLeftImm32(i.Reg[0], i.Reg[1], i.Imm[0]) + case ShiftLogicalLeftImm64: + mutator.ShiftLogicalLeftImm64(i.Reg[0], i.Reg[1], i.Imm[0]) + case ShiftLogicalRightImm32: + mutator.ShiftLogicalRightImm32(i.Reg[0], i.Reg[1], i.Imm[0]) + case ShiftLogicalRightImm64: + mutator.ShiftLogicalRightImm64(i.Reg[0], i.Reg[1], i.Imm[0]) + case ShiftArithmeticRightImm32: + mutator.ShiftArithmeticRightImm32(i.Reg[0], i.Reg[1], i.Imm[0]) + case ShiftArithmeticRightImm64: + mutator.ShiftArithmeticRightImm64(i.Reg[0], i.Reg[1], i.Imm[0]) + case NegateAndAddImm32: + mutator.NegateAndAddImm32(i.Reg[0], i.Reg[1], i.Imm[0]) + case NegateAndAddImm64: + mutator.NegateAndAddImm64(i.Reg[0], i.Reg[1], i.Imm[0]) case SetGreaterThanUnsignedImm: mutator.SetGreaterThanUnsignedImm(i.Reg[0], i.Reg[1], i.Imm[0]) case SetGreaterThanSignedImm: mutator.SetGreaterThanSignedImm(i.Reg[0], i.Reg[1], i.Imm[0]) - case ShiftLogicalRightImmAlt: - mutator.ShiftLogicalRightImmAlt(i.Reg[0], i.Reg[1], i.Imm[0]) - case ShiftArithmeticRightImmAlt: - mutator.ShiftArithmeticRightImmAlt(i.Reg[0], i.Reg[1], i.Imm[0]) - case ShiftLogicalLeftImmAlt: - mutator.ShiftLogicalLeftImmAlt(i.Reg[0], i.Reg[1], i.Imm[0]) + case ShiftLogicalRightImmAlt32: + mutator.ShiftLogicalRightImmAlt32(i.Reg[0], i.Reg[1], i.Imm[0]) + case ShiftLogicalRightImmAlt64: + mutator.ShiftLogicalRightImmAlt64(i.Reg[0], i.Reg[1], i.Imm[0]) + case ShiftArithmeticRightImmAlt32: + mutator.ShiftArithmeticRightImmAlt32(i.Reg[0], i.Reg[1], i.Imm[0]) + case ShiftArithmeticRightImmAlt64: + mutator.ShiftArithmeticRightImmAlt64(i.Reg[0], i.Reg[1], i.Imm[0]) + case ShiftLogicalLeftImmAlt32: + mutator.ShiftLogicalLeftImmAlt32(i.Reg[0], i.Reg[1], i.Imm[0]) + case ShiftLogicalLeftImmAlt64: + mutator.ShiftLogicalLeftImmAlt64(i.Reg[0], i.Reg[1], i.Imm[0]) case CmovIfZeroImm: mutator.CmovIfZeroImm(i.Reg[0], i.Reg[1], i.Imm[0]) case CmovIfNotZeroImm: @@ -612,18 +743,24 @@ func (i *Instruction) Mutate(mutator Mutator) (uint32, error) { mutator.BranchGreaterOrEqualUnsigned(i.Reg[0], i.Reg[1], i.Imm[0]) case BranchGreaterOrEqualSigned: mutator.BranchGreaterOrEqualSigned(i.Reg[0], i.Reg[1], i.Imm[0]) - case Add: - mutator.Add(i.Reg[0], i.Reg[1], i.Reg[2]) - case Sub: - mutator.Sub(i.Reg[0], i.Reg[1], i.Reg[2]) + case Add32: + mutator.Add32(i.Reg[0], i.Reg[1], i.Reg[2]) + case Add64: + mutator.Add64(i.Reg[0], i.Reg[1], i.Reg[2]) + case Sub32: + mutator.Sub32(i.Reg[0], i.Reg[1], i.Reg[2]) + case Sub64: + mutator.Sub64(i.Reg[0], i.Reg[1], i.Reg[2]) case And: mutator.And(i.Reg[0], i.Reg[1], i.Reg[2]) case Xor: mutator.Xor(i.Reg[0], i.Reg[1], i.Reg[2]) case Or: mutator.Or(i.Reg[0], i.Reg[1], i.Reg[2]) - case Mul: - mutator.Mul(i.Reg[0], i.Reg[1], i.Reg[2]) + case Mul32: + mutator.Mul32(i.Reg[0], i.Reg[1], i.Reg[2]) + case Mul64: + mutator.Mul64(i.Reg[0], i.Reg[1], i.Reg[2]) case MulUpperSignedSigned: mutator.MulUpperSignedSigned(i.Reg[0], i.Reg[1], i.Reg[2]) case MulUpperUnsignedUnsigned: @@ -634,20 +771,34 @@ func (i *Instruction) Mutate(mutator Mutator) (uint32, error) { mutator.SetLessThanUnsigned(i.Reg[0], i.Reg[1], i.Reg[2]) case SetLessThanSigned: mutator.SetLessThanSigned(i.Reg[0], i.Reg[1], i.Reg[2]) - case ShiftLogicalLeft: - mutator.ShiftLogicalLeft(i.Reg[0], i.Reg[1], i.Reg[2]) - case ShiftLogicalRight: - mutator.ShiftLogicalRight(i.Reg[0], i.Reg[1], i.Reg[2]) - case ShiftArithmeticRight: - mutator.ShiftArithmeticRight(i.Reg[0], i.Reg[1], i.Reg[2]) - case DivUnsigned: - mutator.DivUnsigned(i.Reg[0], i.Reg[1], i.Reg[2]) - case DivSigned: - mutator.DivSigned(i.Reg[0], i.Reg[1], i.Reg[2]) - case RemUnsigned: - mutator.RemUnsigned(i.Reg[0], i.Reg[1], i.Reg[2]) - case RemSigned: - mutator.RemSigned(i.Reg[0], i.Reg[1], i.Reg[2]) + case ShiftLogicalLeft32: + mutator.ShiftLogicalLeft32(i.Reg[0], i.Reg[1], i.Reg[2]) + case ShiftLogicalLeft64: + mutator.ShiftLogicalLeft64(i.Reg[0], i.Reg[1], i.Reg[2]) + case ShiftLogicalRight32: + mutator.ShiftLogicalRight32(i.Reg[0], i.Reg[1], i.Reg[2]) + case ShiftLogicalRight64: + mutator.ShiftLogicalRight64(i.Reg[0], i.Reg[1], i.Reg[2]) + case ShiftArithmeticRight32: + mutator.ShiftArithmeticRight32(i.Reg[0], i.Reg[1], i.Reg[2]) + case ShiftArithmeticRight64: + mutator.ShiftArithmeticRight64(i.Reg[0], i.Reg[1], i.Reg[2]) + case DivUnsigned32: + mutator.DivUnsigned32(i.Reg[0], i.Reg[1], i.Reg[2]) + case DivUnsigned64: + mutator.DivUnsigned64(i.Reg[0], i.Reg[1], i.Reg[2]) + case DivSigned32: + mutator.DivSigned32(i.Reg[0], i.Reg[1], i.Reg[2]) + case DivSigned64: + mutator.DivSigned64(i.Reg[0], i.Reg[1], i.Reg[2]) + case RemUnsigned32: + mutator.RemUnsigned32(i.Reg[0], i.Reg[1], i.Reg[2]) + case RemUnsigned64: + mutator.RemUnsigned64(i.Reg[0], i.Reg[1], i.Reg[2]) + case RemSigned32: + mutator.RemSigned32(i.Reg[0], i.Reg[1], i.Reg[2]) + case RemSigned64: + mutator.RemSigned64(i.Reg[0], i.Reg[1], i.Reg[2]) case CmovIfZero: mutator.CmovIfZero(i.Reg[0], i.Reg[1], i.Reg[2]) case CmovIfNotZero: @@ -662,12 +813,19 @@ func (i *Instruction) Mutate(mutator Mutator) (uint32, error) { return 0, mutator.StoreImmU16(i.Imm[0], i.Imm[1]) case StoreImmU32: return 0, mutator.StoreImmU32(i.Imm[0], i.Imm[1]) + case StoreImmU64: + return 0, mutator.StoreImmU64(i.Imm[0], i.Imm[1]) case MoveReg: mutator.MoveReg(i.Reg[0], i.Reg[1]) case Sbrk: return 0, mutator.Sbrk(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: + mutator.LoadImm64(i.Reg[0], i.ExtImm) + return 0, nil + default: + return 0, fmt.Errorf("unsupported instruction opcode: %d", i.Opcode) } return 0, nil } diff --git a/internal/polkavm/instructions_test.go b/internal/polkavm/instructions_test.go new file mode 100644 index 0000000..e993808 --- /dev/null +++ b/internal/polkavm/instructions_test.go @@ -0,0 +1,152 @@ +package polkavm + +import ( + "errors" + "slices" + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" +) + +func TestInstruction_Mutate(t *testing.T) { + allInstrOpcodes := slices.Concat( + instrImm, instrNone, instrImm, + instrRegImmExt, instrImm2, instrOffset, + instrRegImm, instrRegImm2, instrRegImmOffset, + instrRegReg, instrReg2Imm, instrReg2Offset, + instrReg2Imm2, instrReg3) + + ctrl := gomock.NewController(t) + mutator := NewMockMutator(ctrl) + + mutator.EXPECT().Trap().Times(1) + mutator.EXPECT().Fallthrough().Return().Times(1) + mutator.EXPECT().Sbrk(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().MoveReg(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().BranchEq(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().BranchEqImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().BranchNotEq(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().BranchNotEqImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().BranchLessUnsigned(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().BranchLessUnsignedImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().BranchLessSigned(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().BranchLessSignedImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().BranchGreaterOrEqualUnsigned(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().BranchGreaterOrEqualUnsignedImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().BranchGreaterOrEqualSigned(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().BranchGreaterOrEqualSignedImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().BranchLessOrEqualUnsignedImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().BranchLessOrEqualSignedImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().BranchGreaterUnsignedImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().BranchGreaterSignedImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().SetLessThanUnsignedImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().SetLessThanSignedImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftLogicalLeftImm32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftLogicalLeftImm64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftArithmeticRightImm32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftArithmeticRightImm64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftArithmeticRightImmAlt32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftArithmeticRightImmAlt64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().NegateAndAddImm32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().NegateAndAddImm64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().SetGreaterThanUnsignedImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().SetGreaterThanSignedImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftLogicalRightImmAlt32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftLogicalRightImmAlt64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftLogicalLeftImmAlt32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftLogicalLeftImmAlt64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().Add32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().Add64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().AddImm32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().AddImm64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().Sub32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().Sub64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().And(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().AndImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().Xor(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().XorImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().Or(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().OrImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().Mul32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().Mul64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().MulImm32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().MulImm64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().MulUpperSignedSigned(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().MulUpperUnsignedUnsigned(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().MulUpperSignedUnsigned(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().SetLessThanUnsigned(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().SetLessThanSigned(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftLogicalLeft32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftLogicalLeft64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftLogicalRight32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftLogicalRight64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftLogicalRightImm32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftLogicalRightImm64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftArithmeticRight32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().ShiftArithmeticRight64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().DivUnsigned32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().DivUnsigned64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().DivSigned32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().DivSigned64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().RemUnsigned32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().RemUnsigned64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().RemSigned32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().RemSigned64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().CmovIfZero(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().CmovIfZeroImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().CmovIfNotZero(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().CmovIfNotZeroImm(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().StoreU8(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().StoreU16(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().StoreU32(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().StoreU64(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().StoreImmU8(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().StoreImmU16(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().StoreImmU32(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().StoreImmU64(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().StoreImmIndirectU8(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().StoreImmIndirectU16(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().StoreImmIndirectU32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().StoreImmIndirectU64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().StoreIndirectU8(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().StoreIndirectU16(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().StoreIndirectU32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().StoreIndirectU64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadU8(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadI8(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadU16(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadI16(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadU32(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadI32(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadU64(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadIndirectU8(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadIndirectI8(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadIndirectU16(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadIndirectI16(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadIndirectU32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadIndirectI32(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadIndirectU64(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadImm(gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadImmAndJump(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + mutator.EXPECT().LoadImmAndJumpIndirect(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + 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) + for _, opcode := range allInstrOpcodes { + instr := Instruction{ + Opcode: opcode, + Imm: []uint32{0, 0, 0}, + ExtImm: 0, + Reg: []Reg{RA, SP, T0}, + Offset: 0, + Length: 0, + } + + _, err := instr.Mutate(mutator) + if !errors.Is(err, ErrHostCall) { + assert.NoError(t, err) + } + } + ctrl.Finish() +} diff --git a/internal/polkavm/interpreter/instance.go b/internal/polkavm/interpreter/instance.go index 36d0f27..cddc6c3 100644 --- a/internal/polkavm/interpreter/instance.go +++ b/internal/polkavm/interpreter/instance.go @@ -10,7 +10,7 @@ func InitRegs(args []byte) polkavm.Registers { regs[polkavm.RA] = 1<<32 - 1<<16 regs[polkavm.SP] = 1<<32 - 2*(1<<16) - 2<<24 regs[polkavm.A0] = 1<<32 - 1<<16 - 2<<24 - regs[polkavm.A1] = uint32(len(args)) + regs[polkavm.A1] = uint64(len(args)) return regs } diff --git a/internal/polkavm/interpreter/interpreter_test.go b/internal/polkavm/interpreter/interpreter_test.go index af74cff..14b3329 100644 --- a/internal/polkavm/interpreter/interpreter_test.go +++ b/internal/polkavm/interpreter/interpreter_test.go @@ -15,15 +15,15 @@ func TestInstance_Execute(t *testing.T) { RWDataSize: 0, StackSize: 4096, Instructions: []polkavm.Instruction{ - {Opcode: polkavm.AddImm, Imm: []uint32{4294967288}, Reg: []polkavm.Reg{polkavm.SP, polkavm.SP}, Offset: 0, Length: 3}, + {Opcode: polkavm.AddImm32, Imm: []uint32{4294967288}, Reg: []polkavm.Reg{polkavm.SP, polkavm.SP}, Offset: 0, Length: 3}, {Opcode: polkavm.StoreIndirectU32, Imm: []uint32{4}, Reg: []polkavm.Reg{polkavm.RA, polkavm.SP}, Offset: 3, Length: 3}, {Opcode: polkavm.StoreIndirectU32, Imm: []uint32{0}, Reg: []polkavm.Reg{polkavm.S0, polkavm.SP}, Offset: 6, Length: 2}, - {Opcode: polkavm.Add, Reg: []polkavm.Reg{polkavm.S0, polkavm.A1, polkavm.A0}, Offset: 8, Length: 3}, + {Opcode: polkavm.Add32, Reg: []polkavm.Reg{polkavm.S0, polkavm.A1, polkavm.A0}, Offset: 8, Length: 3}, {Opcode: polkavm.Ecalli, Imm: []uint32{0}, Offset: 11, Length: 1}, - {Opcode: polkavm.Add, Imm: nil, Reg: []polkavm.Reg{polkavm.A0, polkavm.A0, polkavm.S0}, Offset: 12, Length: 3}, + {Opcode: polkavm.Add32, Imm: nil, Reg: []polkavm.Reg{polkavm.A0, polkavm.A0, polkavm.S0}, Offset: 12, Length: 3}, {Opcode: polkavm.LoadIndirectU32, Imm: []uint32{4}, Reg: []polkavm.Reg{polkavm.RA, polkavm.SP}, Offset: 15, Length: 3}, {Opcode: polkavm.LoadIndirectU32, Imm: []uint32{0}, Reg: []polkavm.Reg{polkavm.S0, polkavm.SP}, Offset: 18, Length: 2}, - {Opcode: polkavm.AddImm, Imm: []uint32{8}, Reg: []polkavm.Reg{polkavm.SP, polkavm.SP}, Offset: 20, Length: 3}, + {Opcode: polkavm.AddImm32, Imm: []uint32{8}, Reg: []polkavm.Reg{polkavm.SP, polkavm.SP}, Offset: 20, Length: 3}, {Opcode: polkavm.JumpIndirect, Imm: []uint32{0}, Reg: []polkavm.Reg{polkavm.RA}, Offset: 23, Length: 2}, }, Imports: []string{"get_third_number"}, @@ -41,7 +41,7 @@ func TestInstance_Execute(t *testing.T) { entryPoint := pp.Exports[i].TargetCodeOffset initialRegs := polkavm.Registers{ polkavm.RA: polkavm.VmAddressReturnToHost, - polkavm.SP: memoryMap.StackAddressHigh, + polkavm.SP: uint64(memoryMap.StackAddressHigh), polkavm.A0: 1, polkavm.A1: 10, } @@ -57,7 +57,7 @@ func TestInstance_Execute(t *testing.T) { gas, regs, _, _, err := InvokeHostCall(pp, memoryMap, entryPoint, gasLimit, initialRegs, memory, hostCall, nothing{}) require.ErrorIs(t, err, polkavm.ErrHalt) - assert.Equal(t, uint32(111), regs[polkavm.A0]) + assert.Equal(t, uint64(111), regs[polkavm.A0]) assert.Equal(t, polkavm.Gas(gasLimit)-polkavm.Gas(len(pp.Instructions)), gas) }) diff --git a/internal/polkavm/interpreter/mutator.go b/internal/polkavm/interpreter/mutator.go index 103ff3d..9ffcb5d 100644 --- a/internal/polkavm/interpreter/mutator.go +++ b/internal/polkavm/interpreter/mutator.go @@ -47,7 +47,7 @@ func (m *Mutator) branch(condition bool, target uint32) { func (m *Mutator) load(memLen int, signed bool, dst polkavm.Reg, base polkavm.Reg, offset uint32) error { var address uint32 = 0 if base != 0 { - address = m.get(base) + address = m.get32(base) } address += offset slice := make([]byte, memLen) @@ -60,14 +60,14 @@ func (m *Mutator) load(memLen int, signed bool, dst polkavm.Reg, base polkavm.Re if err != nil { return err } - m.setNext(dst, toSigned(value, memLen, signed)) + m.setNext32(dst, toSigned(value, memLen, signed)) return nil } func (m *Mutator) store(memLen int, signed bool, src uint32, base polkavm.Reg, offset uint32) error { var address uint32 = 0 if base != 0 { - address = m.get(base) + address = m.get32(base) } address += offset data, err := leEncode(memLen, toSigned(src, memLen, signed)) @@ -135,16 +135,28 @@ func (m *Mutator) djump(target uint32) error { return nil } -func (m *Mutator) get(vv polkavm.Reg) uint32 { +func (m *Mutator) get32(vv polkavm.Reg) uint32 { + return uint32(m.instance.regs[vv]) +} + +func (m *Mutator) get64(vv polkavm.Reg) uint64 { return m.instance.regs[vv] } -func (m *Mutator) set(dst polkavm.Reg, value uint32) { +func (m *Mutator) set32(dst polkavm.Reg, value uint32) { + m.instance.regs[dst] = uint64(value) +} + +func (m *Mutator) set64(dst polkavm.Reg, value uint64) { m.instance.regs[dst] = value } -func (m *Mutator) setNext(dst polkavm.Reg, value uint32) { - m.set(dst, value) +func (m *Mutator) setNext32(dst polkavm.Reg, value uint32) { + m.set32(dst, value) + m.instance.NextOffsets() +} +func (m *Mutator) setNext64(dst polkavm.Reg, value uint64) { + m.set64(dst, value) m.instance.NextOffsets() } func (m *Mutator) Trap() error { @@ -155,10 +167,10 @@ func (m *Mutator) Fallthrough() { m.instance.startBasicBlock(m.program) } func (m *Mutator) Sbrk(dst polkavm.Reg, sizeReg polkavm.Reg) error { - size := m.get(sizeReg) + size := m.get32(sizeReg) if size == 0 { // The guest wants to know the current heap pointer. - m.setNext(dst, m.instance.heapSize) + m.setNext32(dst, m.instance.heapSize) return nil } @@ -173,207 +185,267 @@ func (m *Mutator) Sbrk(dst polkavm.Reg, sizeReg polkavm.Reg) error { return polkavm.ErrPanicf(err.Error()) } - m.setNext(dst, uint32(heapTop)) + m.setNext32(dst, uint32(heapTop)) return nil } func (m *Mutator) MoveReg(d polkavm.Reg, s polkavm.Reg) { - m.setNext(d, m.get(s)) + m.setNext32(d, m.get32(s)) } func (m *Mutator) BranchEq(s1 polkavm.Reg, s2 polkavm.Reg, target uint32) { - m.branch(m.get(s1) == m.get(s2), target) + m.branch(m.get32(s1) == m.get32(s2), target) } func (m *Mutator) BranchEqImm(s1 polkavm.Reg, s2 uint32, target uint32) { - m.branch(m.get(s1) == s2, target) + m.branch(m.get32(s1) == s2, target) } func (m *Mutator) BranchNotEq(s1 polkavm.Reg, s2 polkavm.Reg, target uint32) { - m.branch(m.get(s1) != m.get(s2), target) + m.branch(m.get32(s1) != m.get32(s2), target) } func (m *Mutator) BranchNotEqImm(s1 polkavm.Reg, s2 uint32, target uint32) { - m.branch(m.get(s1) != s2, target) + m.branch(m.get32(s1) != s2, target) } func (m *Mutator) BranchLessUnsigned(s1 polkavm.Reg, s2 polkavm.Reg, target uint32) { - m.branch(m.get(s1) < m.get(s2), target) + m.branch(m.get32(s1) < m.get32(s2), target) } func (m *Mutator) BranchLessUnsignedImm(s1 polkavm.Reg, s2 uint32, target uint32) { - m.branch(m.get(s1) < s2, target) + m.branch(m.get32(s1) < s2, target) } func (m *Mutator) BranchLessSigned(s1 polkavm.Reg, s2 polkavm.Reg, target uint32) { - m.branch(int32(m.get(s1)) < int32(m.get(s2)), target) + m.branch(int32(m.get32(s1)) < int32(m.get32(s2)), target) } func (m *Mutator) BranchLessSignedImm(s1 polkavm.Reg, s2 uint32, target uint32) { - m.branch(int32(m.get(s1)) < int32(s2), target) + m.branch(int32(m.get32(s1)) < int32(s2), target) } func (m *Mutator) BranchGreaterOrEqualUnsigned(s1 polkavm.Reg, s2 polkavm.Reg, target uint32) { - m.branch(m.get(s1) >= m.get(s2), target) + m.branch(m.get32(s1) >= m.get32(s2), target) } func (m *Mutator) BranchGreaterOrEqualUnsignedImm(s1 polkavm.Reg, s2 uint32, target uint32) { - m.branch(m.get(s1) >= s2, target) + m.branch(m.get32(s1) >= s2, target) } func (m *Mutator) BranchGreaterOrEqualSigned(s1 polkavm.Reg, s2 polkavm.Reg, target uint32) { - m.branch(int32(m.get(s1)) >= int32(m.get(s2)), target) + m.branch(int32(m.get32(s1)) >= int32(m.get32(s2)), target) } func (m *Mutator) BranchGreaterOrEqualSignedImm(s1 polkavm.Reg, s2 uint32, target uint32) { - m.branch(int32(m.get(s1)) >= int32(s2), target) + m.branch(int32(m.get32(s1)) >= int32(s2), target) } func (m *Mutator) BranchLessOrEqualUnsignedImm(s1 polkavm.Reg, s2 uint32, target uint32) { - m.branch(m.get(s1) <= s2, target) + m.branch(m.get32(s1) <= s2, target) } func (m *Mutator) BranchLessOrEqualSignedImm(s1 polkavm.Reg, s2 uint32, target uint32) { - m.branch(int32(m.get(s1)) <= int32(s2), target) + m.branch(int32(m.get32(s1)) <= int32(s2), target) } func (m *Mutator) BranchGreaterUnsignedImm(s1 polkavm.Reg, s2 uint32, target uint32) { - m.branch(m.get(s1) > s2, target) + m.branch(m.get32(s1) > s2, target) } func (m *Mutator) BranchGreaterSignedImm(s1 polkavm.Reg, s2 uint32, target uint32) { - m.branch(int32(m.get(s1)) > int32(s2), target) + m.branch(int32(m.get32(s1)) > int32(s2), target) } func (m *Mutator) SetLessThanUnsignedImm(d polkavm.Reg, s1 polkavm.Reg, s2 uint32) { - m.setNext(d, bool2uint32(m.get(s1) < s2)) + m.setNext32(d, bool2uint32(m.get32(s1) < s2)) } func (m *Mutator) SetLessThanSignedImm(d polkavm.Reg, s1 polkavm.Reg, s2 uint32) { - m.setNext(d, bool2uint32(int32(m.get(s1)) < int32(s2))) + m.setNext32(d, bool2uint32(int32(m.get32(s1)) < int32(s2))) +} +func (m *Mutator) ShiftLogicalLeftImm32(d polkavm.Reg, s1 polkavm.Reg, s2 uint32) { + m.setNext32(d, m.get32(s1)<>s2)) } -func (m *Mutator) ShiftLogicalLeftImm(d polkavm.Reg, s1 polkavm.Reg, s2 uint32) { - m.setNext(d, m.get(s1)<>s2)) } -func (m *Mutator) ShiftArithmeticRightImm(d polkavm.Reg, s1 polkavm.Reg, s2 uint32) { - m.setNext(d, uint32(int32(m.get(s1))>>s2)) +func (m *Mutator) ShiftArithmeticRightImmAlt32(d polkavm.Reg, s2 polkavm.Reg, s1 uint32) { + m.setNext32(d, uint32(int32(s1)>>m.get32(s2))) } -func (m *Mutator) ShiftArithmeticRightImmAlt(d polkavm.Reg, s2 polkavm.Reg, s1 uint32) { - m.setNext(d, uint32(int32(s1)>>m.get(s2))) +func (m *Mutator) ShiftArithmeticRightImmAlt64(d polkavm.Reg, s2 polkavm.Reg, s1 uint32) { + m.setNext64(d, uint64(int64(s1)>>m.get64(s2))) } -func (m *Mutator) NegateAndAddImm(d polkavm.Reg, s1 polkavm.Reg, s2 uint32) { - m.setNext(d, s2-m.get(s1)) +func (m *Mutator) NegateAndAddImm32(d polkavm.Reg, s1 polkavm.Reg, s2 uint32) { + m.setNext32(d, s2-m.get32(s1)) +} +func (m *Mutator) NegateAndAddImm64(d polkavm.Reg, s1 polkavm.Reg, s2 uint32) { + m.setNext64(d, uint64(s2)-m.get64(s1)) } func (m *Mutator) SetGreaterThanUnsignedImm(d polkavm.Reg, s1 polkavm.Reg, s2 uint32) { - m.setNext(d, bool2uint32(m.get(s1) > s2)) + m.setNext32(d, bool2uint32(m.get32(s1) > s2)) } func (m *Mutator) SetGreaterThanSignedImm(d polkavm.Reg, s1 polkavm.Reg, s2 uint32) { - m.setNext(d, bool2uint32(int32(m.get(s1)) > int32(s2))) + 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)) +} +func (m *Mutator) ShiftLogicalRightImmAlt64(d polkavm.Reg, s2 polkavm.Reg, s1 uint32) { + m.setNext32(d, s1>>m.get32(s2)) +} +func (m *Mutator) ShiftLogicalLeftImmAlt32(d polkavm.Reg, s2 polkavm.Reg, s1 uint32) { + m.setNext32(d, s1<>m.get(s2)) +func (m *Mutator) ShiftLogicalLeftImmAlt64(d polkavm.Reg, s2 polkavm.Reg, s1 uint32) { + m.setNext32(d, s1<>32))) + m.setNext32(d, uint32(int32((int64(m.get32(s1))*int64(m.get32(s2)))>>32))) } func (m *Mutator) MulUpperSignedSignedImm(d polkavm.Reg, s1 polkavm.Reg, s2 uint32) { - m.setNext(d, uint32(int32((int64(m.get(s1))*int64(s2))>>32))) + m.setNext32(d, uint32(int32((int64(m.get32(s1))*int64(s2))>>32))) } func (m *Mutator) MulUpperUnsignedUnsigned(d polkavm.Reg, s1, s2 polkavm.Reg) { - m.setNext(d, uint32(int32((int64(m.get(s1))*int64(m.get(s2)))>>32))) + m.setNext32(d, uint32(int32((int64(m.get32(s1))*int64(m.get32(s2)))>>32))) } func (m *Mutator) MulUpperUnsignedUnsignedImm(d polkavm.Reg, s1 polkavm.Reg, s2 uint32) { - m.setNext(d, uint32(int32((int64(m.get(s1))*int64(s2))>>32))) + m.setNext32(d, uint32(int32((int64(m.get32(s1))*int64(s2))>>32))) } func (m *Mutator) MulUpperSignedUnsigned(d polkavm.Reg, s1, s2 polkavm.Reg) { - m.setNext(d, uint32((int64(m.get(s1))*int64(m.get(s2)))>>32)) + m.setNext32(d, uint32((int64(m.get32(s1))*int64(m.get32(s2)))>>32)) } func (m *Mutator) SetLessThanUnsigned(d polkavm.Reg, s1, s2 polkavm.Reg) { - m.setNext(d, bool2uint32(m.get(s1) < m.get(s2))) + m.setNext32(d, bool2uint32(m.get32(s1) < m.get32(s2))) } func (m *Mutator) SetLessThanSigned(d polkavm.Reg, s1, s2 polkavm.Reg) { - m.setNext(d, bool2uint32(int32(m.get(s1)) < int32(m.get(s2)))) + m.setNext32(d, bool2uint32(int32(m.get32(s1)) < int32(m.get32(s2)))) } -func (m *Mutator) ShiftLogicalLeft(d polkavm.Reg, s1, s2 polkavm.Reg) { - shiftAmount := m.get(s2) % 32 - shiftedValue := m.get(s1) << shiftAmount - m.setNext(d, shiftedValue) +func (m *Mutator) ShiftLogicalLeft32(d polkavm.Reg, s1, s2 polkavm.Reg) { + shiftAmount := m.get32(s2) % 32 + shiftedValue := m.get32(s1) << shiftAmount + m.setNext32(d, shiftedValue) } -func (m *Mutator) ShiftLogicalRight(d polkavm.Reg, s1, s2 polkavm.Reg) { - m.setNext(d, m.get(s1)>>(m.get(s2)%32)) +func (m *Mutator) ShiftLogicalLeft64(d polkavm.Reg, s1, s2 polkavm.Reg) { + panic("implement me") } -func (m *Mutator) ShiftLogicalRightImm(d polkavm.Reg, s1 polkavm.Reg, s2 uint32) { - m.setNext(d, m.get(s1)>>s2) +func (m *Mutator) ShiftLogicalRight32(d polkavm.Reg, s1, s2 polkavm.Reg) { + m.setNext32(d, m.get32(s1)>>(m.get32(s2)%32)) } -func (m *Mutator) ShiftArithmeticRight(d polkavm.Reg, s1, s2 polkavm.Reg) { - shiftAmount := m.get(s2) % 32 - shiftedValue := int32(m.get(s1)) >> shiftAmount - m.setNext(d, uint32(shiftedValue)) +func (m *Mutator) ShiftLogicalRight64(d polkavm.Reg, s1, s2 polkavm.Reg) { + panic("implement me") } -func (m *Mutator) DivUnsigned(d polkavm.Reg, s1, s2 polkavm.Reg) { - m.setNext(d, divUnsigned(m.get(s1), m.get(s2))) +func (m *Mutator) ShiftLogicalRightImm32(d polkavm.Reg, s1 polkavm.Reg, s2 uint32) { + m.setNext32(d, m.get32(s1)>>s2) } -func (m *Mutator) DivSigned(d polkavm.Reg, s1, s2 polkavm.Reg) { - m.setNext(d, uint32(div(int32(m.get(s1)), int32(m.get(s2))))) +func (m *Mutator) ShiftLogicalRightImm64(d polkavm.Reg, s1 polkavm.Reg, s2 uint32) { + panic("implement me") } -func (m *Mutator) RemUnsigned(d polkavm.Reg, s1, s2 polkavm.Reg) { - m.setNext(d, remUnsigned(m.get(s1), m.get(s2))) +func (m *Mutator) ShiftArithmeticRight32(d polkavm.Reg, s1, s2 polkavm.Reg) { + shiftAmount := m.get32(s2) % 32 + shiftedValue := int32(m.get32(s1)) >> shiftAmount + m.setNext32(d, uint32(shiftedValue)) } -func (m *Mutator) RemSigned(d polkavm.Reg, s1, s2 polkavm.Reg) { - m.setNext(d, uint32(rem(int32(m.get(s1)), int32(m.get(s2))))) +func (m *Mutator) ShiftArithmeticRight64(d polkavm.Reg, s1, s2 polkavm.Reg) { + panic("implement me") +} +func (m *Mutator) DivUnsigned32(d polkavm.Reg, s1, s2 polkavm.Reg) { + m.setNext32(d, divUnsigned(m.get32(s1), m.get32(s2))) +} +func (m *Mutator) DivUnsigned64(d polkavm.Reg, s1, s2 polkavm.Reg) { + panic("implement me") +} +func (m *Mutator) DivSigned32(d polkavm.Reg, s1, s2 polkavm.Reg) { + m.setNext32(d, uint32(div(int32(m.get32(s1)), int32(m.get32(s2))))) +} +func (m *Mutator) DivSigned64(d polkavm.Reg, s1, s2 polkavm.Reg) { + panic("implement me") +} +func (m *Mutator) RemUnsigned32(d polkavm.Reg, s1, s2 polkavm.Reg) { + m.setNext32(d, remUnsigned(m.get32(s1), m.get32(s2))) +} +func (m *Mutator) RemUnsigned64(d polkavm.Reg, s1, s2 polkavm.Reg) { + panic("implement me") +} +func (m *Mutator) RemSigned32(d polkavm.Reg, s1, s2 polkavm.Reg) { + m.setNext32(d, uint32(rem(int32(m.get32(s1)), int32(m.get32(s2))))) +} +func (m *Mutator) RemSigned64(d polkavm.Reg, s1, s2 polkavm.Reg) { + panic("implement me") } func (m *Mutator) CmovIfZero(d polkavm.Reg, s, c polkavm.Reg) { - if m.get(c) == 0 { - m.set(d, m.get(s)) + if m.get32(c) == 0 { + m.set32(d, m.get32(s)) } m.instance.NextOffsets() } func (m *Mutator) CmovIfZeroImm(d polkavm.Reg, c polkavm.Reg, s uint32) { - if m.get(c) == 0 { - m.set(d, s) + if m.get32(c) == 0 { + m.set32(d, s) } m.instance.NextOffsets() } func (m *Mutator) CmovIfNotZero(d polkavm.Reg, s, c polkavm.Reg) { - if m.get(c) != 0 { - m.set(d, m.get(s)) + if m.get32(c) != 0 { + m.set32(d, m.get32(s)) } m.instance.NextOffsets() } func (m *Mutator) CmovIfNotZeroImm(d polkavm.Reg, c polkavm.Reg, s uint32) { - if m.get(c) != 0 { - m.set(d, s) + if m.get32(c) != 0 { + m.set32(d, s) } m.instance.NextOffsets() } func (m *Mutator) StoreU8(src polkavm.Reg, offset uint32) error { - return m.store(x8, unsigned, m.get(src), 0, offset) + return m.store(x8, unsigned, m.get32(src), 0, offset) } func (m *Mutator) StoreU16(src polkavm.Reg, offset uint32) error { - return m.store(x16, unsigned, m.get(src), 0, offset) + return m.store(x16, unsigned, m.get32(src), 0, offset) } func (m *Mutator) StoreU32(src polkavm.Reg, offset uint32) error { - return m.store(x32, unsigned, m.get(src), 0, offset) + return m.store(x32, unsigned, m.get32(src), 0, offset) +} +func (m *Mutator) StoreU64(src polkavm.Reg, offset uint32) error { + panic("implement me") } func (m *Mutator) StoreImmU8(offset uint32, value uint32) error { return m.store(x8, unsigned, value, 0, offset) @@ -384,6 +456,9 @@ func (m *Mutator) StoreImmU16(offset uint32, value uint32) error { func (m *Mutator) StoreImmU32(offset uint32, value uint32) error { return m.store(x32, unsigned, value, 0, offset) } +func (m *Mutator) StoreImmU64(offset uint32, value uint32) error { + panic("implement me") +} func (m *Mutator) StoreImmIndirectU8(base polkavm.Reg, offset uint32, value uint32) error { return m.store(x8, unsigned, value, base, offset) } @@ -393,14 +468,20 @@ func (m *Mutator) StoreImmIndirectU16(base polkavm.Reg, offset uint32, value uin func (m *Mutator) StoreImmIndirectU32(base polkavm.Reg, offset uint32, value uint32) error { return m.store(x32, unsigned, value, base, offset) } +func (m *Mutator) StoreImmIndirectU64(base polkavm.Reg, offset uint32, value uint32) error { + panic("implement me") +} func (m *Mutator) StoreIndirectU8(src polkavm.Reg, base polkavm.Reg, offset uint32) error { - return m.store(x8, unsigned, m.get(src), base, offset) + return m.store(x8, unsigned, m.get32(src), base, offset) } func (m *Mutator) StoreIndirectU16(src polkavm.Reg, base polkavm.Reg, offset uint32) error { - return m.store(x16, unsigned, m.get(src), base, offset) + return m.store(x16, unsigned, m.get32(src), base, offset) } func (m *Mutator) StoreIndirectU32(src polkavm.Reg, base polkavm.Reg, offset uint32) error { - return m.store(x32, unsigned, m.get(src), base, offset) + return m.store(x32, unsigned, m.get32(src), base, offset) +} +func (m *Mutator) StoreIndirectU64(src polkavm.Reg, base polkavm.Reg, offset uint32) error { + panic("implement me") } func (m *Mutator) LoadU8(dst polkavm.Reg, offset uint32) error { return m.load(x8, unsigned, dst, 0, offset) @@ -414,9 +495,15 @@ func (m *Mutator) LoadU16(dst polkavm.Reg, offset uint32) error { func (m *Mutator) LoadI16(dst polkavm.Reg, offset uint32) error { return m.load(x16, signed, dst, 0, offset) } +func (m *Mutator) LoadI32(dst polkavm.Reg, offset uint32) error { + panic("implement me") +} func (m *Mutator) LoadU32(dst polkavm.Reg, offset uint32) error { return m.load(x32, unsigned, dst, 0, offset) } +func (m *Mutator) LoadU64(dst polkavm.Reg, offset uint32) error { + panic("implement me") +} func (m *Mutator) LoadIndirectU8(dst polkavm.Reg, base polkavm.Reg, offset uint32) error { return m.load(x8, unsigned, dst, base, offset) } @@ -429,19 +516,28 @@ func (m *Mutator) LoadIndirectU16(dst polkavm.Reg, base polkavm.Reg, offset uint func (m *Mutator) LoadIndirectI16(dst polkavm.Reg, base polkavm.Reg, offset uint32) error { return m.load(x16, signed, dst, base, offset) } +func (m *Mutator) LoadIndirectI32(dst polkavm.Reg, base polkavm.Reg, offset uint32) error { + panic("implement me") +} func (m *Mutator) LoadIndirectU32(dst polkavm.Reg, base polkavm.Reg, offset uint32) error { return m.load(x32, unsigned, dst, base, offset) } +func (m *Mutator) LoadIndirectU64(dst polkavm.Reg, base polkavm.Reg, offset uint32) error { + panic("implement me") +} func (m *Mutator) LoadImm(dst polkavm.Reg, imm uint32) { - m.setNext(dst, imm) + m.setNext32(dst, imm) +} +func (m *Mutator) LoadImm64(dst polkavm.Reg, imm uint64) { + m.setNext64(dst, imm) } func (m *Mutator) LoadImmAndJump(ra polkavm.Reg, value uint32, target uint32) { m.LoadImm(ra, value) m.Jump(target) } func (m *Mutator) LoadImmAndJumpIndirect(ra polkavm.Reg, base polkavm.Reg, value, offset uint32) error { - target := m.get(base) + offset - m.set(ra, value) + target := m.get32(base) + offset + m.set32(ra, value) return m.djump(target) } func (m *Mutator) Jump(target uint32) { @@ -450,7 +546,7 @@ func (m *Mutator) Jump(target uint32) { } func (m *Mutator) JumpIndirect(base polkavm.Reg, offset uint32) error { - return m.djump(m.get(base) + offset) + return m.djump(m.get32(base) + offset) } func divUnsigned(lhs uint32, rhs uint32) uint32 { diff --git a/internal/polkavm/interpreter/utils.go b/internal/polkavm/interpreter/utils.go index 423a382..9ec9b60 100644 --- a/internal/polkavm/interpreter/utils.go +++ b/internal/polkavm/interpreter/utils.go @@ -30,7 +30,7 @@ func InvokeWholeProgram[X any](p []byte, entryPoint uint32, gas uint64, args []b } result := make([]byte, regs[polkavm.A4]) - if err := memory1.Read(regs[polkavm.A3], result); err != nil { + if err := memory1.Read(uint32(regs[polkavm.A3]), result); err != nil { return 0, nil, x, err } diff --git a/internal/polkavm/mutator_mock.go b/internal/polkavm/mutator_mock.go new file mode 100644 index 0000000..3718171 --- /dev/null +++ b/internal/polkavm/mutator_mock.go @@ -0,0 +1,1458 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/eigerco/strawberry/internal/polkavm (interfaces: Mutator) + +// Package polkavm is a generated GoMock package. +package polkavm + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" +) + +// MockMutator is a mock of Mutator interface. +type MockMutator struct { + ctrl *gomock.Controller + recorder *MockMutatorMockRecorder +} + +// MockMutatorMockRecorder is the mock recorder for MockMutator. +type MockMutatorMockRecorder struct { + mock *MockMutator +} + +// NewMockMutator creates a new mock instance. +func NewMockMutator(ctrl *gomock.Controller) *MockMutator { + mock := &MockMutator{ctrl: ctrl} + mock.recorder = &MockMutatorMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockMutator) EXPECT() *MockMutatorMockRecorder { + return m.recorder +} + +// Add32 mocks base method. +func (m *MockMutator) Add32(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Add32", arg0, arg1, arg2) +} + +// Add32 indicates an expected call of Add32. +func (mr *MockMutatorMockRecorder) Add32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add32", reflect.TypeOf((*MockMutator)(nil).Add32), arg0, arg1, arg2) +} + +// Add64 mocks base method. +func (m *MockMutator) Add64(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Add64", arg0, arg1, arg2) +} + +// Add64 indicates an expected call of Add64. +func (mr *MockMutatorMockRecorder) Add64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add64", reflect.TypeOf((*MockMutator)(nil).Add64), arg0, arg1, arg2) +} + +// AddImm32 mocks base method. +func (m *MockMutator) AddImm32(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AddImm32", arg0, arg1, arg2) +} + +// AddImm32 indicates an expected call of AddImm32. +func (mr *MockMutatorMockRecorder) AddImm32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddImm32", reflect.TypeOf((*MockMutator)(nil).AddImm32), arg0, arg1, arg2) +} + +// AddImm64 mocks base method. +func (m *MockMutator) AddImm64(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AddImm64", arg0, arg1, arg2) +} + +// AddImm64 indicates an expected call of AddImm64. +func (mr *MockMutatorMockRecorder) AddImm64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddImm64", reflect.TypeOf((*MockMutator)(nil).AddImm64), arg0, arg1, arg2) +} + +// And mocks base method. +func (m *MockMutator) And(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "And", arg0, arg1, arg2) +} + +// And indicates an expected call of And. +func (mr *MockMutatorMockRecorder) And(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "And", reflect.TypeOf((*MockMutator)(nil).And), arg0, arg1, arg2) +} + +// AndImm mocks base method. +func (m *MockMutator) AndImm(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AndImm", arg0, arg1, arg2) +} + +// AndImm indicates an expected call of AndImm. +func (mr *MockMutatorMockRecorder) AndImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AndImm", reflect.TypeOf((*MockMutator)(nil).AndImm), arg0, arg1, arg2) +} + +// BranchEq mocks base method. +func (m *MockMutator) BranchEq(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BranchEq", arg0, arg1, arg2) +} + +// BranchEq indicates an expected call of BranchEq. +func (mr *MockMutatorMockRecorder) BranchEq(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BranchEq", reflect.TypeOf((*MockMutator)(nil).BranchEq), arg0, arg1, arg2) +} + +// BranchEqImm mocks base method. +func (m *MockMutator) BranchEqImm(arg0 Reg, arg1, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BranchEqImm", arg0, arg1, arg2) +} + +// BranchEqImm indicates an expected call of BranchEqImm. +func (mr *MockMutatorMockRecorder) BranchEqImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BranchEqImm", reflect.TypeOf((*MockMutator)(nil).BranchEqImm), arg0, arg1, arg2) +} + +// BranchGreaterOrEqualSigned mocks base method. +func (m *MockMutator) BranchGreaterOrEqualSigned(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BranchGreaterOrEqualSigned", arg0, arg1, arg2) +} + +// BranchGreaterOrEqualSigned indicates an expected call of BranchGreaterOrEqualSigned. +func (mr *MockMutatorMockRecorder) BranchGreaterOrEqualSigned(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BranchGreaterOrEqualSigned", reflect.TypeOf((*MockMutator)(nil).BranchGreaterOrEqualSigned), arg0, arg1, arg2) +} + +// BranchGreaterOrEqualSignedImm mocks base method. +func (m *MockMutator) BranchGreaterOrEqualSignedImm(arg0 Reg, arg1, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BranchGreaterOrEqualSignedImm", arg0, arg1, arg2) +} + +// BranchGreaterOrEqualSignedImm indicates an expected call of BranchGreaterOrEqualSignedImm. +func (mr *MockMutatorMockRecorder) BranchGreaterOrEqualSignedImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BranchGreaterOrEqualSignedImm", reflect.TypeOf((*MockMutator)(nil).BranchGreaterOrEqualSignedImm), arg0, arg1, arg2) +} + +// BranchGreaterOrEqualUnsigned mocks base method. +func (m *MockMutator) BranchGreaterOrEqualUnsigned(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BranchGreaterOrEqualUnsigned", arg0, arg1, arg2) +} + +// BranchGreaterOrEqualUnsigned indicates an expected call of BranchGreaterOrEqualUnsigned. +func (mr *MockMutatorMockRecorder) BranchGreaterOrEqualUnsigned(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BranchGreaterOrEqualUnsigned", reflect.TypeOf((*MockMutator)(nil).BranchGreaterOrEqualUnsigned), arg0, arg1, arg2) +} + +// BranchGreaterOrEqualUnsignedImm mocks base method. +func (m *MockMutator) BranchGreaterOrEqualUnsignedImm(arg0 Reg, arg1, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BranchGreaterOrEqualUnsignedImm", arg0, arg1, arg2) +} + +// BranchGreaterOrEqualUnsignedImm indicates an expected call of BranchGreaterOrEqualUnsignedImm. +func (mr *MockMutatorMockRecorder) BranchGreaterOrEqualUnsignedImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BranchGreaterOrEqualUnsignedImm", reflect.TypeOf((*MockMutator)(nil).BranchGreaterOrEqualUnsignedImm), arg0, arg1, arg2) +} + +// BranchGreaterSignedImm mocks base method. +func (m *MockMutator) BranchGreaterSignedImm(arg0 Reg, arg1, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BranchGreaterSignedImm", arg0, arg1, arg2) +} + +// BranchGreaterSignedImm indicates an expected call of BranchGreaterSignedImm. +func (mr *MockMutatorMockRecorder) BranchGreaterSignedImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BranchGreaterSignedImm", reflect.TypeOf((*MockMutator)(nil).BranchGreaterSignedImm), arg0, arg1, arg2) +} + +// BranchGreaterUnsignedImm mocks base method. +func (m *MockMutator) BranchGreaterUnsignedImm(arg0 Reg, arg1, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BranchGreaterUnsignedImm", arg0, arg1, arg2) +} + +// BranchGreaterUnsignedImm indicates an expected call of BranchGreaterUnsignedImm. +func (mr *MockMutatorMockRecorder) BranchGreaterUnsignedImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BranchGreaterUnsignedImm", reflect.TypeOf((*MockMutator)(nil).BranchGreaterUnsignedImm), arg0, arg1, arg2) +} + +// BranchLessOrEqualSignedImm mocks base method. +func (m *MockMutator) BranchLessOrEqualSignedImm(arg0 Reg, arg1, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BranchLessOrEqualSignedImm", arg0, arg1, arg2) +} + +// BranchLessOrEqualSignedImm indicates an expected call of BranchLessOrEqualSignedImm. +func (mr *MockMutatorMockRecorder) BranchLessOrEqualSignedImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BranchLessOrEqualSignedImm", reflect.TypeOf((*MockMutator)(nil).BranchLessOrEqualSignedImm), arg0, arg1, arg2) +} + +// BranchLessOrEqualUnsignedImm mocks base method. +func (m *MockMutator) BranchLessOrEqualUnsignedImm(arg0 Reg, arg1, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BranchLessOrEqualUnsignedImm", arg0, arg1, arg2) +} + +// BranchLessOrEqualUnsignedImm indicates an expected call of BranchLessOrEqualUnsignedImm. +func (mr *MockMutatorMockRecorder) BranchLessOrEqualUnsignedImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BranchLessOrEqualUnsignedImm", reflect.TypeOf((*MockMutator)(nil).BranchLessOrEqualUnsignedImm), arg0, arg1, arg2) +} + +// BranchLessSigned mocks base method. +func (m *MockMutator) BranchLessSigned(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BranchLessSigned", arg0, arg1, arg2) +} + +// BranchLessSigned indicates an expected call of BranchLessSigned. +func (mr *MockMutatorMockRecorder) BranchLessSigned(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BranchLessSigned", reflect.TypeOf((*MockMutator)(nil).BranchLessSigned), arg0, arg1, arg2) +} + +// BranchLessSignedImm mocks base method. +func (m *MockMutator) BranchLessSignedImm(arg0 Reg, arg1, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BranchLessSignedImm", arg0, arg1, arg2) +} + +// BranchLessSignedImm indicates an expected call of BranchLessSignedImm. +func (mr *MockMutatorMockRecorder) BranchLessSignedImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BranchLessSignedImm", reflect.TypeOf((*MockMutator)(nil).BranchLessSignedImm), arg0, arg1, arg2) +} + +// BranchLessUnsigned mocks base method. +func (m *MockMutator) BranchLessUnsigned(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BranchLessUnsigned", arg0, arg1, arg2) +} + +// BranchLessUnsigned indicates an expected call of BranchLessUnsigned. +func (mr *MockMutatorMockRecorder) BranchLessUnsigned(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BranchLessUnsigned", reflect.TypeOf((*MockMutator)(nil).BranchLessUnsigned), arg0, arg1, arg2) +} + +// BranchLessUnsignedImm mocks base method. +func (m *MockMutator) BranchLessUnsignedImm(arg0 Reg, arg1, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BranchLessUnsignedImm", arg0, arg1, arg2) +} + +// BranchLessUnsignedImm indicates an expected call of BranchLessUnsignedImm. +func (mr *MockMutatorMockRecorder) BranchLessUnsignedImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BranchLessUnsignedImm", reflect.TypeOf((*MockMutator)(nil).BranchLessUnsignedImm), arg0, arg1, arg2) +} + +// BranchNotEq mocks base method. +func (m *MockMutator) BranchNotEq(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BranchNotEq", arg0, arg1, arg2) +} + +// BranchNotEq indicates an expected call of BranchNotEq. +func (mr *MockMutatorMockRecorder) BranchNotEq(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BranchNotEq", reflect.TypeOf((*MockMutator)(nil).BranchNotEq), arg0, arg1, arg2) +} + +// BranchNotEqImm mocks base method. +func (m *MockMutator) BranchNotEqImm(arg0 Reg, arg1, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BranchNotEqImm", arg0, arg1, arg2) +} + +// BranchNotEqImm indicates an expected call of BranchNotEqImm. +func (mr *MockMutatorMockRecorder) BranchNotEqImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BranchNotEqImm", reflect.TypeOf((*MockMutator)(nil).BranchNotEqImm), arg0, arg1, arg2) +} + +// CmovIfNotZero mocks base method. +func (m *MockMutator) CmovIfNotZero(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "CmovIfNotZero", arg0, arg1, arg2) +} + +// CmovIfNotZero indicates an expected call of CmovIfNotZero. +func (mr *MockMutatorMockRecorder) CmovIfNotZero(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CmovIfNotZero", reflect.TypeOf((*MockMutator)(nil).CmovIfNotZero), arg0, arg1, arg2) +} + +// CmovIfNotZeroImm mocks base method. +func (m *MockMutator) CmovIfNotZeroImm(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "CmovIfNotZeroImm", arg0, arg1, arg2) +} + +// CmovIfNotZeroImm indicates an expected call of CmovIfNotZeroImm. +func (mr *MockMutatorMockRecorder) CmovIfNotZeroImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CmovIfNotZeroImm", reflect.TypeOf((*MockMutator)(nil).CmovIfNotZeroImm), arg0, arg1, arg2) +} + +// CmovIfZero mocks base method. +func (m *MockMutator) CmovIfZero(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "CmovIfZero", arg0, arg1, arg2) +} + +// CmovIfZero indicates an expected call of CmovIfZero. +func (mr *MockMutatorMockRecorder) CmovIfZero(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CmovIfZero", reflect.TypeOf((*MockMutator)(nil).CmovIfZero), arg0, arg1, arg2) +} + +// CmovIfZeroImm mocks base method. +func (m *MockMutator) CmovIfZeroImm(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "CmovIfZeroImm", arg0, arg1, arg2) +} + +// CmovIfZeroImm indicates an expected call of CmovIfZeroImm. +func (mr *MockMutatorMockRecorder) CmovIfZeroImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CmovIfZeroImm", reflect.TypeOf((*MockMutator)(nil).CmovIfZeroImm), arg0, arg1, arg2) +} + +// DivSigned32 mocks base method. +func (m *MockMutator) DivSigned32(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "DivSigned32", arg0, arg1, arg2) +} + +// DivSigned32 indicates an expected call of DivSigned32. +func (mr *MockMutatorMockRecorder) DivSigned32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DivSigned32", reflect.TypeOf((*MockMutator)(nil).DivSigned32), arg0, arg1, arg2) +} + +// DivSigned64 mocks base method. +func (m *MockMutator) DivSigned64(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "DivSigned64", arg0, arg1, arg2) +} + +// DivSigned64 indicates an expected call of DivSigned64. +func (mr *MockMutatorMockRecorder) DivSigned64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DivSigned64", reflect.TypeOf((*MockMutator)(nil).DivSigned64), arg0, arg1, arg2) +} + +// DivUnsigned32 mocks base method. +func (m *MockMutator) DivUnsigned32(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "DivUnsigned32", arg0, arg1, arg2) +} + +// DivUnsigned32 indicates an expected call of DivUnsigned32. +func (mr *MockMutatorMockRecorder) DivUnsigned32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DivUnsigned32", reflect.TypeOf((*MockMutator)(nil).DivUnsigned32), arg0, arg1, arg2) +} + +// DivUnsigned64 mocks base method. +func (m *MockMutator) DivUnsigned64(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "DivUnsigned64", arg0, arg1, arg2) +} + +// DivUnsigned64 indicates an expected call of DivUnsigned64. +func (mr *MockMutatorMockRecorder) DivUnsigned64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DivUnsigned64", reflect.TypeOf((*MockMutator)(nil).DivUnsigned64), arg0, arg1, arg2) +} + +// Fallthrough mocks base method. +func (m *MockMutator) Fallthrough() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Fallthrough") +} + +// Fallthrough indicates an expected call of Fallthrough. +func (mr *MockMutatorMockRecorder) Fallthrough() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fallthrough", reflect.TypeOf((*MockMutator)(nil).Fallthrough)) +} + +// Jump mocks base method. +func (m *MockMutator) Jump(arg0 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Jump", arg0) +} + +// Jump indicates an expected call of Jump. +func (mr *MockMutatorMockRecorder) Jump(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Jump", reflect.TypeOf((*MockMutator)(nil).Jump), arg0) +} + +// JumpIndirect mocks base method. +func (m *MockMutator) JumpIndirect(arg0 Reg, arg1 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "JumpIndirect", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// JumpIndirect indicates an expected call of JumpIndirect. +func (mr *MockMutatorMockRecorder) JumpIndirect(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "JumpIndirect", reflect.TypeOf((*MockMutator)(nil).JumpIndirect), arg0, arg1) +} + +// LoadI16 mocks base method. +func (m *MockMutator) LoadI16(arg0 Reg, arg1 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadI16", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadI16 indicates an expected call of LoadI16. +func (mr *MockMutatorMockRecorder) LoadI16(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadI16", reflect.TypeOf((*MockMutator)(nil).LoadI16), arg0, arg1) +} + +// LoadI32 mocks base method. +func (m *MockMutator) LoadI32(arg0 Reg, arg1 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadI32", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadI32 indicates an expected call of LoadI32. +func (mr *MockMutatorMockRecorder) LoadI32(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadI32", reflect.TypeOf((*MockMutator)(nil).LoadI32), arg0, arg1) +} + +// LoadI8 mocks base method. +func (m *MockMutator) LoadI8(arg0 Reg, arg1 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadI8", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadI8 indicates an expected call of LoadI8. +func (mr *MockMutatorMockRecorder) LoadI8(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadI8", reflect.TypeOf((*MockMutator)(nil).LoadI8), arg0, arg1) +} + +// LoadImm mocks base method. +func (m *MockMutator) LoadImm(arg0 Reg, arg1 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "LoadImm", arg0, arg1) +} + +// LoadImm indicates an expected call of LoadImm. +func (mr *MockMutatorMockRecorder) LoadImm(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadImm", reflect.TypeOf((*MockMutator)(nil).LoadImm), arg0, arg1) +} + +// LoadImm64 mocks base method. +func (m *MockMutator) LoadImm64(arg0 Reg, arg1 uint64) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "LoadImm64", arg0, arg1) +} + +// LoadImm64 indicates an expected call of LoadImm64. +func (mr *MockMutatorMockRecorder) LoadImm64(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadImm64", reflect.TypeOf((*MockMutator)(nil).LoadImm64), arg0, arg1) +} + +// LoadImmAndJump mocks base method. +func (m *MockMutator) LoadImmAndJump(arg0 Reg, arg1, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "LoadImmAndJump", arg0, arg1, arg2) +} + +// LoadImmAndJump indicates an expected call of LoadImmAndJump. +func (mr *MockMutatorMockRecorder) LoadImmAndJump(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadImmAndJump", reflect.TypeOf((*MockMutator)(nil).LoadImmAndJump), arg0, arg1, arg2) +} + +// LoadImmAndJumpIndirect mocks base method. +func (m *MockMutator) LoadImmAndJumpIndirect(arg0, arg1 Reg, arg2, arg3 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadImmAndJumpIndirect", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadImmAndJumpIndirect indicates an expected call of LoadImmAndJumpIndirect. +func (mr *MockMutatorMockRecorder) LoadImmAndJumpIndirect(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadImmAndJumpIndirect", reflect.TypeOf((*MockMutator)(nil).LoadImmAndJumpIndirect), arg0, arg1, arg2, arg3) +} + +// LoadIndirectI16 mocks base method. +func (m *MockMutator) LoadIndirectI16(arg0, arg1 Reg, arg2 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadIndirectI16", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadIndirectI16 indicates an expected call of LoadIndirectI16. +func (mr *MockMutatorMockRecorder) LoadIndirectI16(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadIndirectI16", reflect.TypeOf((*MockMutator)(nil).LoadIndirectI16), arg0, arg1, arg2) +} + +// LoadIndirectI32 mocks base method. +func (m *MockMutator) LoadIndirectI32(arg0, arg1 Reg, arg2 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadIndirectI32", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadIndirectI32 indicates an expected call of LoadIndirectI32. +func (mr *MockMutatorMockRecorder) LoadIndirectI32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadIndirectI32", reflect.TypeOf((*MockMutator)(nil).LoadIndirectI32), arg0, arg1, arg2) +} + +// LoadIndirectI8 mocks base method. +func (m *MockMutator) LoadIndirectI8(arg0, arg1 Reg, arg2 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadIndirectI8", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadIndirectI8 indicates an expected call of LoadIndirectI8. +func (mr *MockMutatorMockRecorder) LoadIndirectI8(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadIndirectI8", reflect.TypeOf((*MockMutator)(nil).LoadIndirectI8), arg0, arg1, arg2) +} + +// LoadIndirectU16 mocks base method. +func (m *MockMutator) LoadIndirectU16(arg0, arg1 Reg, arg2 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadIndirectU16", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadIndirectU16 indicates an expected call of LoadIndirectU16. +func (mr *MockMutatorMockRecorder) LoadIndirectU16(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadIndirectU16", reflect.TypeOf((*MockMutator)(nil).LoadIndirectU16), arg0, arg1, arg2) +} + +// LoadIndirectU32 mocks base method. +func (m *MockMutator) LoadIndirectU32(arg0, arg1 Reg, arg2 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadIndirectU32", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadIndirectU32 indicates an expected call of LoadIndirectU32. +func (mr *MockMutatorMockRecorder) LoadIndirectU32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadIndirectU32", reflect.TypeOf((*MockMutator)(nil).LoadIndirectU32), arg0, arg1, arg2) +} + +// LoadIndirectU64 mocks base method. +func (m *MockMutator) LoadIndirectU64(arg0, arg1 Reg, arg2 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadIndirectU64", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadIndirectU64 indicates an expected call of LoadIndirectU64. +func (mr *MockMutatorMockRecorder) LoadIndirectU64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadIndirectU64", reflect.TypeOf((*MockMutator)(nil).LoadIndirectU64), arg0, arg1, arg2) +} + +// LoadIndirectU8 mocks base method. +func (m *MockMutator) LoadIndirectU8(arg0, arg1 Reg, arg2 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadIndirectU8", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadIndirectU8 indicates an expected call of LoadIndirectU8. +func (mr *MockMutatorMockRecorder) LoadIndirectU8(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadIndirectU8", reflect.TypeOf((*MockMutator)(nil).LoadIndirectU8), arg0, arg1, arg2) +} + +// LoadU16 mocks base method. +func (m *MockMutator) LoadU16(arg0 Reg, arg1 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadU16", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadU16 indicates an expected call of LoadU16. +func (mr *MockMutatorMockRecorder) LoadU16(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadU16", reflect.TypeOf((*MockMutator)(nil).LoadU16), arg0, arg1) +} + +// LoadU32 mocks base method. +func (m *MockMutator) LoadU32(arg0 Reg, arg1 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadU32", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadU32 indicates an expected call of LoadU32. +func (mr *MockMutatorMockRecorder) LoadU32(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadU32", reflect.TypeOf((*MockMutator)(nil).LoadU32), arg0, arg1) +} + +// LoadU64 mocks base method. +func (m *MockMutator) LoadU64(arg0 Reg, arg1 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadU64", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadU64 indicates an expected call of LoadU64. +func (mr *MockMutatorMockRecorder) LoadU64(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadU64", reflect.TypeOf((*MockMutator)(nil).LoadU64), arg0, arg1) +} + +// LoadU8 mocks base method. +func (m *MockMutator) LoadU8(arg0 Reg, arg1 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadU8", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadU8 indicates an expected call of LoadU8. +func (mr *MockMutatorMockRecorder) LoadU8(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadU8", reflect.TypeOf((*MockMutator)(nil).LoadU8), arg0, arg1) +} + +// MoveReg mocks base method. +func (m *MockMutator) MoveReg(arg0, arg1 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "MoveReg", arg0, arg1) +} + +// MoveReg indicates an expected call of MoveReg. +func (mr *MockMutatorMockRecorder) MoveReg(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MoveReg", reflect.TypeOf((*MockMutator)(nil).MoveReg), arg0, arg1) +} + +// Mul32 mocks base method. +func (m *MockMutator) Mul32(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Mul32", arg0, arg1, arg2) +} + +// Mul32 indicates an expected call of Mul32. +func (mr *MockMutatorMockRecorder) Mul32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Mul32", reflect.TypeOf((*MockMutator)(nil).Mul32), arg0, arg1, arg2) +} + +// Mul64 mocks base method. +func (m *MockMutator) Mul64(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Mul64", arg0, arg1, arg2) +} + +// Mul64 indicates an expected call of Mul64. +func (mr *MockMutatorMockRecorder) Mul64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Mul64", reflect.TypeOf((*MockMutator)(nil).Mul64), arg0, arg1, arg2) +} + +// MulImm32 mocks base method. +func (m *MockMutator) MulImm32(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "MulImm32", arg0, arg1, arg2) +} + +// MulImm32 indicates an expected call of MulImm32. +func (mr *MockMutatorMockRecorder) MulImm32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MulImm32", reflect.TypeOf((*MockMutator)(nil).MulImm32), arg0, arg1, arg2) +} + +// MulImm64 mocks base method. +func (m *MockMutator) MulImm64(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "MulImm64", arg0, arg1, arg2) +} + +// MulImm64 indicates an expected call of MulImm64. +func (mr *MockMutatorMockRecorder) MulImm64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MulImm64", reflect.TypeOf((*MockMutator)(nil).MulImm64), arg0, arg1, arg2) +} + +// MulUpperSignedSigned mocks base method. +func (m *MockMutator) MulUpperSignedSigned(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "MulUpperSignedSigned", arg0, arg1, arg2) +} + +// MulUpperSignedSigned indicates an expected call of MulUpperSignedSigned. +func (mr *MockMutatorMockRecorder) MulUpperSignedSigned(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MulUpperSignedSigned", reflect.TypeOf((*MockMutator)(nil).MulUpperSignedSigned), arg0, arg1, arg2) +} + +// MulUpperSignedUnsigned mocks base method. +func (m *MockMutator) MulUpperSignedUnsigned(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "MulUpperSignedUnsigned", arg0, arg1, arg2) +} + +// MulUpperSignedUnsigned indicates an expected call of MulUpperSignedUnsigned. +func (mr *MockMutatorMockRecorder) MulUpperSignedUnsigned(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MulUpperSignedUnsigned", reflect.TypeOf((*MockMutator)(nil).MulUpperSignedUnsigned), arg0, arg1, arg2) +} + +// MulUpperUnsignedUnsigned mocks base method. +func (m *MockMutator) MulUpperUnsignedUnsigned(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "MulUpperUnsignedUnsigned", arg0, arg1, arg2) +} + +// MulUpperUnsignedUnsigned indicates an expected call of MulUpperUnsignedUnsigned. +func (mr *MockMutatorMockRecorder) MulUpperUnsignedUnsigned(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MulUpperUnsignedUnsigned", reflect.TypeOf((*MockMutator)(nil).MulUpperUnsignedUnsigned), arg0, arg1, arg2) +} + +// NegateAndAddImm32 mocks base method. +func (m *MockMutator) NegateAndAddImm32(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "NegateAndAddImm32", arg0, arg1, arg2) +} + +// NegateAndAddImm32 indicates an expected call of NegateAndAddImm32. +func (mr *MockMutatorMockRecorder) NegateAndAddImm32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NegateAndAddImm32", reflect.TypeOf((*MockMutator)(nil).NegateAndAddImm32), arg0, arg1, arg2) +} + +// NegateAndAddImm64 mocks base method. +func (m *MockMutator) NegateAndAddImm64(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "NegateAndAddImm64", arg0, arg1, arg2) +} + +// NegateAndAddImm64 indicates an expected call of NegateAndAddImm64. +func (mr *MockMutatorMockRecorder) NegateAndAddImm64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NegateAndAddImm64", reflect.TypeOf((*MockMutator)(nil).NegateAndAddImm64), arg0, arg1, arg2) +} + +// Or mocks base method. +func (m *MockMutator) Or(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Or", arg0, arg1, arg2) +} + +// Or indicates an expected call of Or. +func (mr *MockMutatorMockRecorder) Or(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Or", reflect.TypeOf((*MockMutator)(nil).Or), arg0, arg1, arg2) +} + +// OrImm mocks base method. +func (m *MockMutator) OrImm(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "OrImm", arg0, arg1, arg2) +} + +// OrImm indicates an expected call of OrImm. +func (mr *MockMutatorMockRecorder) OrImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OrImm", reflect.TypeOf((*MockMutator)(nil).OrImm), arg0, arg1, arg2) +} + +// RemSigned32 mocks base method. +func (m *MockMutator) RemSigned32(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RemSigned32", arg0, arg1, arg2) +} + +// RemSigned32 indicates an expected call of RemSigned32. +func (mr *MockMutatorMockRecorder) RemSigned32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemSigned32", reflect.TypeOf((*MockMutator)(nil).RemSigned32), arg0, arg1, arg2) +} + +// RemSigned64 mocks base method. +func (m *MockMutator) RemSigned64(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RemSigned64", arg0, arg1, arg2) +} + +// RemSigned64 indicates an expected call of RemSigned64. +func (mr *MockMutatorMockRecorder) RemSigned64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemSigned64", reflect.TypeOf((*MockMutator)(nil).RemSigned64), arg0, arg1, arg2) +} + +// RemUnsigned32 mocks base method. +func (m *MockMutator) RemUnsigned32(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RemUnsigned32", arg0, arg1, arg2) +} + +// RemUnsigned32 indicates an expected call of RemUnsigned32. +func (mr *MockMutatorMockRecorder) RemUnsigned32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemUnsigned32", reflect.TypeOf((*MockMutator)(nil).RemUnsigned32), arg0, arg1, arg2) +} + +// RemUnsigned64 mocks base method. +func (m *MockMutator) RemUnsigned64(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RemUnsigned64", arg0, arg1, arg2) +} + +// RemUnsigned64 indicates an expected call of RemUnsigned64. +func (mr *MockMutatorMockRecorder) RemUnsigned64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemUnsigned64", reflect.TypeOf((*MockMutator)(nil).RemUnsigned64), arg0, arg1, arg2) +} + +// Sbrk mocks base method. +func (m *MockMutator) Sbrk(arg0, arg1 Reg) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Sbrk", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// Sbrk indicates an expected call of Sbrk. +func (mr *MockMutatorMockRecorder) Sbrk(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Sbrk", reflect.TypeOf((*MockMutator)(nil).Sbrk), arg0, arg1) +} + +// SetGreaterThanSignedImm mocks base method. +func (m *MockMutator) SetGreaterThanSignedImm(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetGreaterThanSignedImm", arg0, arg1, arg2) +} + +// SetGreaterThanSignedImm indicates an expected call of SetGreaterThanSignedImm. +func (mr *MockMutatorMockRecorder) SetGreaterThanSignedImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetGreaterThanSignedImm", reflect.TypeOf((*MockMutator)(nil).SetGreaterThanSignedImm), arg0, arg1, arg2) +} + +// SetGreaterThanUnsignedImm mocks base method. +func (m *MockMutator) SetGreaterThanUnsignedImm(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetGreaterThanUnsignedImm", arg0, arg1, arg2) +} + +// SetGreaterThanUnsignedImm indicates an expected call of SetGreaterThanUnsignedImm. +func (mr *MockMutatorMockRecorder) SetGreaterThanUnsignedImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetGreaterThanUnsignedImm", reflect.TypeOf((*MockMutator)(nil).SetGreaterThanUnsignedImm), arg0, arg1, arg2) +} + +// SetLessThanSigned mocks base method. +func (m *MockMutator) SetLessThanSigned(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetLessThanSigned", arg0, arg1, arg2) +} + +// SetLessThanSigned indicates an expected call of SetLessThanSigned. +func (mr *MockMutatorMockRecorder) SetLessThanSigned(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLessThanSigned", reflect.TypeOf((*MockMutator)(nil).SetLessThanSigned), arg0, arg1, arg2) +} + +// SetLessThanSignedImm mocks base method. +func (m *MockMutator) SetLessThanSignedImm(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetLessThanSignedImm", arg0, arg1, arg2) +} + +// SetLessThanSignedImm indicates an expected call of SetLessThanSignedImm. +func (mr *MockMutatorMockRecorder) SetLessThanSignedImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLessThanSignedImm", reflect.TypeOf((*MockMutator)(nil).SetLessThanSignedImm), arg0, arg1, arg2) +} + +// SetLessThanUnsigned mocks base method. +func (m *MockMutator) SetLessThanUnsigned(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetLessThanUnsigned", arg0, arg1, arg2) +} + +// SetLessThanUnsigned indicates an expected call of SetLessThanUnsigned. +func (mr *MockMutatorMockRecorder) SetLessThanUnsigned(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLessThanUnsigned", reflect.TypeOf((*MockMutator)(nil).SetLessThanUnsigned), arg0, arg1, arg2) +} + +// SetLessThanUnsignedImm mocks base method. +func (m *MockMutator) SetLessThanUnsignedImm(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetLessThanUnsignedImm", arg0, arg1, arg2) +} + +// SetLessThanUnsignedImm indicates an expected call of SetLessThanUnsignedImm. +func (mr *MockMutatorMockRecorder) SetLessThanUnsignedImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLessThanUnsignedImm", reflect.TypeOf((*MockMutator)(nil).SetLessThanUnsignedImm), arg0, arg1, arg2) +} + +// ShiftArithmeticRight32 mocks base method. +func (m *MockMutator) ShiftArithmeticRight32(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftArithmeticRight32", arg0, arg1, arg2) +} + +// ShiftArithmeticRight32 indicates an expected call of ShiftArithmeticRight32. +func (mr *MockMutatorMockRecorder) ShiftArithmeticRight32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftArithmeticRight32", reflect.TypeOf((*MockMutator)(nil).ShiftArithmeticRight32), arg0, arg1, arg2) +} + +// ShiftArithmeticRight64 mocks base method. +func (m *MockMutator) ShiftArithmeticRight64(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftArithmeticRight64", arg0, arg1, arg2) +} + +// ShiftArithmeticRight64 indicates an expected call of ShiftArithmeticRight64. +func (mr *MockMutatorMockRecorder) ShiftArithmeticRight64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftArithmeticRight64", reflect.TypeOf((*MockMutator)(nil).ShiftArithmeticRight64), arg0, arg1, arg2) +} + +// ShiftArithmeticRightImm32 mocks base method. +func (m *MockMutator) ShiftArithmeticRightImm32(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftArithmeticRightImm32", arg0, arg1, arg2) +} + +// ShiftArithmeticRightImm32 indicates an expected call of ShiftArithmeticRightImm32. +func (mr *MockMutatorMockRecorder) ShiftArithmeticRightImm32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftArithmeticRightImm32", reflect.TypeOf((*MockMutator)(nil).ShiftArithmeticRightImm32), arg0, arg1, arg2) +} + +// ShiftArithmeticRightImm64 mocks base method. +func (m *MockMutator) ShiftArithmeticRightImm64(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftArithmeticRightImm64", arg0, arg1, arg2) +} + +// ShiftArithmeticRightImm64 indicates an expected call of ShiftArithmeticRightImm64. +func (mr *MockMutatorMockRecorder) ShiftArithmeticRightImm64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftArithmeticRightImm64", reflect.TypeOf((*MockMutator)(nil).ShiftArithmeticRightImm64), arg0, arg1, arg2) +} + +// ShiftArithmeticRightImmAlt32 mocks base method. +func (m *MockMutator) ShiftArithmeticRightImmAlt32(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftArithmeticRightImmAlt32", arg0, arg1, arg2) +} + +// ShiftArithmeticRightImmAlt32 indicates an expected call of ShiftArithmeticRightImmAlt32. +func (mr *MockMutatorMockRecorder) ShiftArithmeticRightImmAlt32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftArithmeticRightImmAlt32", reflect.TypeOf((*MockMutator)(nil).ShiftArithmeticRightImmAlt32), arg0, arg1, arg2) +} + +// ShiftArithmeticRightImmAlt64 mocks base method. +func (m *MockMutator) ShiftArithmeticRightImmAlt64(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftArithmeticRightImmAlt64", arg0, arg1, arg2) +} + +// ShiftArithmeticRightImmAlt64 indicates an expected call of ShiftArithmeticRightImmAlt64. +func (mr *MockMutatorMockRecorder) ShiftArithmeticRightImmAlt64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftArithmeticRightImmAlt64", reflect.TypeOf((*MockMutator)(nil).ShiftArithmeticRightImmAlt64), arg0, arg1, arg2) +} + +// ShiftLogicalLeft32 mocks base method. +func (m *MockMutator) ShiftLogicalLeft32(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftLogicalLeft32", arg0, arg1, arg2) +} + +// ShiftLogicalLeft32 indicates an expected call of ShiftLogicalLeft32. +func (mr *MockMutatorMockRecorder) ShiftLogicalLeft32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftLogicalLeft32", reflect.TypeOf((*MockMutator)(nil).ShiftLogicalLeft32), arg0, arg1, arg2) +} + +// ShiftLogicalLeft64 mocks base method. +func (m *MockMutator) ShiftLogicalLeft64(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftLogicalLeft64", arg0, arg1, arg2) +} + +// ShiftLogicalLeft64 indicates an expected call of ShiftLogicalLeft64. +func (mr *MockMutatorMockRecorder) ShiftLogicalLeft64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftLogicalLeft64", reflect.TypeOf((*MockMutator)(nil).ShiftLogicalLeft64), arg0, arg1, arg2) +} + +// ShiftLogicalLeftImm32 mocks base method. +func (m *MockMutator) ShiftLogicalLeftImm32(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftLogicalLeftImm32", arg0, arg1, arg2) +} + +// ShiftLogicalLeftImm32 indicates an expected call of ShiftLogicalLeftImm32. +func (mr *MockMutatorMockRecorder) ShiftLogicalLeftImm32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftLogicalLeftImm32", reflect.TypeOf((*MockMutator)(nil).ShiftLogicalLeftImm32), arg0, arg1, arg2) +} + +// ShiftLogicalLeftImm64 mocks base method. +func (m *MockMutator) ShiftLogicalLeftImm64(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftLogicalLeftImm64", arg0, arg1, arg2) +} + +// ShiftLogicalLeftImm64 indicates an expected call of ShiftLogicalLeftImm64. +func (mr *MockMutatorMockRecorder) ShiftLogicalLeftImm64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftLogicalLeftImm64", reflect.TypeOf((*MockMutator)(nil).ShiftLogicalLeftImm64), arg0, arg1, arg2) +} + +// ShiftLogicalLeftImmAlt32 mocks base method. +func (m *MockMutator) ShiftLogicalLeftImmAlt32(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftLogicalLeftImmAlt32", arg0, arg1, arg2) +} + +// ShiftLogicalLeftImmAlt32 indicates an expected call of ShiftLogicalLeftImmAlt32. +func (mr *MockMutatorMockRecorder) ShiftLogicalLeftImmAlt32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftLogicalLeftImmAlt32", reflect.TypeOf((*MockMutator)(nil).ShiftLogicalLeftImmAlt32), arg0, arg1, arg2) +} + +// ShiftLogicalLeftImmAlt64 mocks base method. +func (m *MockMutator) ShiftLogicalLeftImmAlt64(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftLogicalLeftImmAlt64", arg0, arg1, arg2) +} + +// ShiftLogicalLeftImmAlt64 indicates an expected call of ShiftLogicalLeftImmAlt64. +func (mr *MockMutatorMockRecorder) ShiftLogicalLeftImmAlt64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftLogicalLeftImmAlt64", reflect.TypeOf((*MockMutator)(nil).ShiftLogicalLeftImmAlt64), arg0, arg1, arg2) +} + +// ShiftLogicalRight32 mocks base method. +func (m *MockMutator) ShiftLogicalRight32(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftLogicalRight32", arg0, arg1, arg2) +} + +// ShiftLogicalRight32 indicates an expected call of ShiftLogicalRight32. +func (mr *MockMutatorMockRecorder) ShiftLogicalRight32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftLogicalRight32", reflect.TypeOf((*MockMutator)(nil).ShiftLogicalRight32), arg0, arg1, arg2) +} + +// ShiftLogicalRight64 mocks base method. +func (m *MockMutator) ShiftLogicalRight64(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftLogicalRight64", arg0, arg1, arg2) +} + +// ShiftLogicalRight64 indicates an expected call of ShiftLogicalRight64. +func (mr *MockMutatorMockRecorder) ShiftLogicalRight64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftLogicalRight64", reflect.TypeOf((*MockMutator)(nil).ShiftLogicalRight64), arg0, arg1, arg2) +} + +// ShiftLogicalRightImm32 mocks base method. +func (m *MockMutator) ShiftLogicalRightImm32(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftLogicalRightImm32", arg0, arg1, arg2) +} + +// ShiftLogicalRightImm32 indicates an expected call of ShiftLogicalRightImm32. +func (mr *MockMutatorMockRecorder) ShiftLogicalRightImm32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftLogicalRightImm32", reflect.TypeOf((*MockMutator)(nil).ShiftLogicalRightImm32), arg0, arg1, arg2) +} + +// ShiftLogicalRightImm64 mocks base method. +func (m *MockMutator) ShiftLogicalRightImm64(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftLogicalRightImm64", arg0, arg1, arg2) +} + +// ShiftLogicalRightImm64 indicates an expected call of ShiftLogicalRightImm64. +func (mr *MockMutatorMockRecorder) ShiftLogicalRightImm64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftLogicalRightImm64", reflect.TypeOf((*MockMutator)(nil).ShiftLogicalRightImm64), arg0, arg1, arg2) +} + +// ShiftLogicalRightImmAlt32 mocks base method. +func (m *MockMutator) ShiftLogicalRightImmAlt32(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftLogicalRightImmAlt32", arg0, arg1, arg2) +} + +// ShiftLogicalRightImmAlt32 indicates an expected call of ShiftLogicalRightImmAlt32. +func (mr *MockMutatorMockRecorder) ShiftLogicalRightImmAlt32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftLogicalRightImmAlt32", reflect.TypeOf((*MockMutator)(nil).ShiftLogicalRightImmAlt32), arg0, arg1, arg2) +} + +// ShiftLogicalRightImmAlt64 mocks base method. +func (m *MockMutator) ShiftLogicalRightImmAlt64(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ShiftLogicalRightImmAlt64", arg0, arg1, arg2) +} + +// ShiftLogicalRightImmAlt64 indicates an expected call of ShiftLogicalRightImmAlt64. +func (mr *MockMutatorMockRecorder) ShiftLogicalRightImmAlt64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShiftLogicalRightImmAlt64", reflect.TypeOf((*MockMutator)(nil).ShiftLogicalRightImmAlt64), arg0, arg1, arg2) +} + +// StoreImmIndirectU16 mocks base method. +func (m *MockMutator) StoreImmIndirectU16(arg0 Reg, arg1, arg2 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StoreImmIndirectU16", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// StoreImmIndirectU16 indicates an expected call of StoreImmIndirectU16. +func (mr *MockMutatorMockRecorder) StoreImmIndirectU16(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreImmIndirectU16", reflect.TypeOf((*MockMutator)(nil).StoreImmIndirectU16), arg0, arg1, arg2) +} + +// StoreImmIndirectU32 mocks base method. +func (m *MockMutator) StoreImmIndirectU32(arg0 Reg, arg1, arg2 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StoreImmIndirectU32", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// StoreImmIndirectU32 indicates an expected call of StoreImmIndirectU32. +func (mr *MockMutatorMockRecorder) StoreImmIndirectU32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreImmIndirectU32", reflect.TypeOf((*MockMutator)(nil).StoreImmIndirectU32), arg0, arg1, arg2) +} + +// StoreImmIndirectU64 mocks base method. +func (m *MockMutator) StoreImmIndirectU64(arg0 Reg, arg1, arg2 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StoreImmIndirectU64", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// StoreImmIndirectU64 indicates an expected call of StoreImmIndirectU64. +func (mr *MockMutatorMockRecorder) StoreImmIndirectU64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreImmIndirectU64", reflect.TypeOf((*MockMutator)(nil).StoreImmIndirectU64), arg0, arg1, arg2) +} + +// StoreImmIndirectU8 mocks base method. +func (m *MockMutator) StoreImmIndirectU8(arg0 Reg, arg1, arg2 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StoreImmIndirectU8", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// StoreImmIndirectU8 indicates an expected call of StoreImmIndirectU8. +func (mr *MockMutatorMockRecorder) StoreImmIndirectU8(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreImmIndirectU8", reflect.TypeOf((*MockMutator)(nil).StoreImmIndirectU8), arg0, arg1, arg2) +} + +// StoreImmU16 mocks base method. +func (m *MockMutator) StoreImmU16(arg0, arg1 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StoreImmU16", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// StoreImmU16 indicates an expected call of StoreImmU16. +func (mr *MockMutatorMockRecorder) StoreImmU16(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreImmU16", reflect.TypeOf((*MockMutator)(nil).StoreImmU16), arg0, arg1) +} + +// StoreImmU32 mocks base method. +func (m *MockMutator) StoreImmU32(arg0, arg1 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StoreImmU32", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// StoreImmU32 indicates an expected call of StoreImmU32. +func (mr *MockMutatorMockRecorder) StoreImmU32(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreImmU32", reflect.TypeOf((*MockMutator)(nil).StoreImmU32), arg0, arg1) +} + +// StoreImmU64 mocks base method. +func (m *MockMutator) StoreImmU64(arg0, arg1 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StoreImmU64", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// StoreImmU64 indicates an expected call of StoreImmU64. +func (mr *MockMutatorMockRecorder) StoreImmU64(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreImmU64", reflect.TypeOf((*MockMutator)(nil).StoreImmU64), arg0, arg1) +} + +// StoreImmU8 mocks base method. +func (m *MockMutator) StoreImmU8(arg0, arg1 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StoreImmU8", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// StoreImmU8 indicates an expected call of StoreImmU8. +func (mr *MockMutatorMockRecorder) StoreImmU8(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreImmU8", reflect.TypeOf((*MockMutator)(nil).StoreImmU8), arg0, arg1) +} + +// StoreIndirectU16 mocks base method. +func (m *MockMutator) StoreIndirectU16(arg0, arg1 Reg, arg2 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StoreIndirectU16", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// StoreIndirectU16 indicates an expected call of StoreIndirectU16. +func (mr *MockMutatorMockRecorder) StoreIndirectU16(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreIndirectU16", reflect.TypeOf((*MockMutator)(nil).StoreIndirectU16), arg0, arg1, arg2) +} + +// StoreIndirectU32 mocks base method. +func (m *MockMutator) StoreIndirectU32(arg0, arg1 Reg, arg2 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StoreIndirectU32", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// StoreIndirectU32 indicates an expected call of StoreIndirectU32. +func (mr *MockMutatorMockRecorder) StoreIndirectU32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreIndirectU32", reflect.TypeOf((*MockMutator)(nil).StoreIndirectU32), arg0, arg1, arg2) +} + +// StoreIndirectU64 mocks base method. +func (m *MockMutator) StoreIndirectU64(arg0, arg1 Reg, arg2 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StoreIndirectU64", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// StoreIndirectU64 indicates an expected call of StoreIndirectU64. +func (mr *MockMutatorMockRecorder) StoreIndirectU64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreIndirectU64", reflect.TypeOf((*MockMutator)(nil).StoreIndirectU64), arg0, arg1, arg2) +} + +// StoreIndirectU8 mocks base method. +func (m *MockMutator) StoreIndirectU8(arg0, arg1 Reg, arg2 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StoreIndirectU8", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// StoreIndirectU8 indicates an expected call of StoreIndirectU8. +func (mr *MockMutatorMockRecorder) StoreIndirectU8(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreIndirectU8", reflect.TypeOf((*MockMutator)(nil).StoreIndirectU8), arg0, arg1, arg2) +} + +// StoreU16 mocks base method. +func (m *MockMutator) StoreU16(arg0 Reg, arg1 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StoreU16", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// StoreU16 indicates an expected call of StoreU16. +func (mr *MockMutatorMockRecorder) StoreU16(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreU16", reflect.TypeOf((*MockMutator)(nil).StoreU16), arg0, arg1) +} + +// StoreU32 mocks base method. +func (m *MockMutator) StoreU32(arg0 Reg, arg1 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StoreU32", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// StoreU32 indicates an expected call of StoreU32. +func (mr *MockMutatorMockRecorder) StoreU32(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreU32", reflect.TypeOf((*MockMutator)(nil).StoreU32), arg0, arg1) +} + +// StoreU64 mocks base method. +func (m *MockMutator) StoreU64(arg0 Reg, arg1 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StoreU64", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// StoreU64 indicates an expected call of StoreU64. +func (mr *MockMutatorMockRecorder) StoreU64(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreU64", reflect.TypeOf((*MockMutator)(nil).StoreU64), arg0, arg1) +} + +// StoreU8 mocks base method. +func (m *MockMutator) StoreU8(arg0 Reg, arg1 uint32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StoreU8", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// StoreU8 indicates an expected call of StoreU8. +func (mr *MockMutatorMockRecorder) StoreU8(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreU8", reflect.TypeOf((*MockMutator)(nil).StoreU8), arg0, arg1) +} + +// Sub32 mocks base method. +func (m *MockMutator) Sub32(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Sub32", arg0, arg1, arg2) +} + +// Sub32 indicates an expected call of Sub32. +func (mr *MockMutatorMockRecorder) Sub32(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Sub32", reflect.TypeOf((*MockMutator)(nil).Sub32), arg0, arg1, arg2) +} + +// Sub64 mocks base method. +func (m *MockMutator) Sub64(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Sub64", arg0, arg1, arg2) +} + +// Sub64 indicates an expected call of Sub64. +func (mr *MockMutatorMockRecorder) Sub64(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Sub64", reflect.TypeOf((*MockMutator)(nil).Sub64), arg0, arg1, arg2) +} + +// Trap mocks base method. +func (m *MockMutator) Trap() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Trap") + ret0, _ := ret[0].(error) + return ret0 +} + +// Trap indicates an expected call of Trap. +func (mr *MockMutatorMockRecorder) Trap() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Trap", reflect.TypeOf((*MockMutator)(nil).Trap)) +} + +// Xor mocks base method. +func (m *MockMutator) Xor(arg0, arg1, arg2 Reg) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Xor", arg0, arg1, arg2) +} + +// Xor indicates an expected call of Xor. +func (mr *MockMutatorMockRecorder) Xor(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Xor", reflect.TypeOf((*MockMutator)(nil).Xor), arg0, arg1, arg2) +} + +// XorImm mocks base method. +func (m *MockMutator) XorImm(arg0, arg1 Reg, arg2 uint32) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "XorImm", arg0, arg1, arg2) +} + +// XorImm indicates an expected call of XorImm. +func (mr *MockMutatorMockRecorder) XorImm(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "XorImm", reflect.TypeOf((*MockMutator)(nil).XorImm), arg0, arg1, arg2) +} diff --git a/internal/polkavm/program_test.go b/internal/polkavm/program_test.go index f1a5fc0..737b59e 100644 --- a/internal/polkavm/program_test.go +++ b/internal/polkavm/program_test.go @@ -26,7 +26,7 @@ func Test_ParseBlob(t *testing.T) { assert.Equal(t, uint32(4096), pp.StackSize) if assert.Equal(t, 10, len(pp.Instructions)) { assert.Equal(t, Instruction{ - Opcode: AddImm, + Opcode: AddImm32, Imm: []uint32{4294967288}, Reg: []Reg{SP, SP}, Offset: 0, Length: 3, @@ -47,7 +47,7 @@ func Test_ParseBlob(t *testing.T) { Length: 2, }, pp.Instructions[2]) assert.Equal(t, Instruction{ - Opcode: Add, + Opcode: Add32, Reg: []Reg{S0, A1, A0}, Offset: 8, Length: 3, @@ -59,7 +59,7 @@ func Test_ParseBlob(t *testing.T) { Length: 1, }, pp.Instructions[4]) assert.Equal(t, Instruction{ - Opcode: Add, + Opcode: Add32, Imm: nil, Reg: []Reg{A0, A0, S0}, Offset: 12, @@ -80,7 +80,7 @@ func Test_ParseBlob(t *testing.T) { Length: 2, }, pp.Instructions[7]) assert.Equal(t, Instruction{ - Opcode: AddImm, + Opcode: AddImm32, Imm: []uint32{8}, Reg: []Reg{SP, SP}, Offset: 20, diff --git a/internal/statetransition/accumulate.go b/internal/statetransition/accumulate.go index 97b4464..bc78ab7 100644 --- a/internal/statetransition/accumulate.go +++ b/internal/statetransition/accumulate.go @@ -102,7 +102,7 @@ func (a *Accumulator) InvokePVM(accState state.AccumulationState, serviceIndex b case host_call.ForgetID: gasCounter, regs, mem, ctx, err = host_call.Forget(gasCounter, regs, mem, ctx, a.header.TimeSlotIndex) default: - regs[polkavm.A0] = uint32(host_call.WHAT) + regs[polkavm.A0] = uint64(host_call.WHAT) gasCounter -= AccumulateCost } return gasCounter, regs, mem, ctx, err diff --git a/internal/statetransition/on_transfer.go b/internal/statetransition/on_transfer.go index dcf867f..a873f67 100644 --- a/internal/statetransition/on_transfer.go +++ b/internal/statetransition/on_transfer.go @@ -43,7 +43,7 @@ func InvokePVMOnTransfer(serviceState service.ServiceState, serviceIndex block.S case host_call.InfoID: gasCounter, regs, mem, err = host_call.Info(gasCounter, regs, mem, serviceIndex, serviceState) default: - regs[polkavm.A0] = uint32(host_call.WHAT) + regs[polkavm.A0] = uint64(host_call.WHAT) gasCounter -= OnTransferCost } return gasCounter, regs, mem, serviceAccount, err diff --git a/tests/integration/pvm_integration_test.go b/tests/integration/pvm_integration_test.go index a4b6bc1..0f56fa6 100644 --- a/tests/integration/pvm_integration_test.go +++ b/tests/integration/pvm_integration_test.go @@ -1,4 +1,4 @@ -//go:build integration +//go:build integration_pvm package integration_test