forked from TrueCloudLab/neoneo-go
Implemented SHL, SHR opcode (#250)
This commit is contained in:
parent
84b4b41288
commit
955bb373fc
3 changed files with 111 additions and 1 deletions
|
@ -5,6 +5,8 @@ import "github.com/CityOfZion/neo-go/pkg/vm/stack"
|
||||||
type stackInfo func(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error)
|
type stackInfo func(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error)
|
||||||
|
|
||||||
var opFunc = map[stack.Instruction]stackInfo{
|
var opFunc = map[stack.Instruction]stackInfo{
|
||||||
|
stack.SHR: Shr,
|
||||||
|
stack.SHL: Shl,
|
||||||
stack.INC: Inc,
|
stack.INC: Inc,
|
||||||
stack.DEC: Dec,
|
stack.DEC: Dec,
|
||||||
stack.DIV: Div,
|
stack.DIV: Div,
|
||||||
|
|
|
@ -260,6 +260,46 @@ func popTwoIntegers(ctx *stack.Context) (*stack.Int, *stack.Int, error) {
|
||||||
return operandA, operandB, nil
|
return operandA, operandB, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shl pops two integers, a and b, off of the stack and pushes an integer to the stack
|
||||||
|
// whose value is the b's value shift to the left by a's value bits.
|
||||||
|
// Returns an error if either items cannot be casted to an integer
|
||||||
|
// or if the left shift operation cannot per performed with the two integer's value.
|
||||||
|
func Shl(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
||||||
|
|
||||||
|
a, b, err := popTwoIntegers(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return FAULT, err
|
||||||
|
}
|
||||||
|
res, err := b.Lsh(a)
|
||||||
|
if err != nil {
|
||||||
|
return FAULT, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Estack.Push(res)
|
||||||
|
|
||||||
|
return NONE, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shr pops two integers, a and b, off of the stack and pushes an integer to the stack
|
||||||
|
// whose value is the b's value shift to the right by a's value bits.
|
||||||
|
// Returns an error if either items cannot be casted to an integer
|
||||||
|
// or if the right shift operation cannot per performed with the two integer's value.
|
||||||
|
func Shr(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
||||||
|
|
||||||
|
a, b, err := popTwoIntegers(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return FAULT, err
|
||||||
|
}
|
||||||
|
res, err := b.Rsh(a)
|
||||||
|
if err != nil {
|
||||||
|
return FAULT, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Estack.Push(res)
|
||||||
|
|
||||||
|
return NONE, nil
|
||||||
|
}
|
||||||
|
|
||||||
func popTwoByteArrays(ctx *stack.Context) (*stack.ByteArray, *stack.ByteArray, error) {
|
func popTwoByteArrays(ctx *stack.Context) (*stack.ByteArray, *stack.ByteArray, error) {
|
||||||
// Pop first stack item and cast as byte array
|
// Pop first stack item and cast as byte array
|
||||||
ba1, err := ctx.Estack.PopByteArray()
|
ba1, err := ctx.Estack.PopByteArray()
|
||||||
|
|
|
@ -143,7 +143,7 @@ func TestDivOp(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, int64(2), item.Value().Int64())
|
assert.Equal(t, int64(2), item.Value().Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,3 +326,71 @@ func TestNegateOp(t *testing.T) {
|
||||||
|
|
||||||
assert.Equal(t, int64(20), item.Value().Int64())
|
assert.Equal(t, int64(20), item.Value().Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestShlOp(t *testing.T) {
|
||||||
|
|
||||||
|
v := VM{}
|
||||||
|
|
||||||
|
a, err := stack.NewInt(big.NewInt(2))
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
b, err := stack.NewInt(big.NewInt(3))
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := stack.NewContext([]byte{})
|
||||||
|
ctx.Estack.Push(a).Push(b)
|
||||||
|
|
||||||
|
// b is the first item pop.
|
||||||
|
// a is the second item pop.
|
||||||
|
// we perform a.Lsh(b) and place
|
||||||
|
// the result on top of the evaluation
|
||||||
|
// stack
|
||||||
|
v.executeOp(stack.SHL, ctx)
|
||||||
|
|
||||||
|
// Stack should have one item
|
||||||
|
assert.Equal(t, 1, ctx.Estack.Len())
|
||||||
|
|
||||||
|
item, err := ctx.Estack.PopInt()
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, int64(16), item.Value().Int64())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestShrOp(t *testing.T) {
|
||||||
|
|
||||||
|
v := VM{}
|
||||||
|
|
||||||
|
a, err := stack.NewInt(big.NewInt(10))
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
b, err := stack.NewInt(big.NewInt(2))
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := stack.NewContext([]byte{})
|
||||||
|
ctx.Estack.Push(a).Push(b)
|
||||||
|
|
||||||
|
// b is the first item pop.
|
||||||
|
// a is the second item pop.
|
||||||
|
// we perform a.Rsh(b) and place
|
||||||
|
// the result on top of the evaluation
|
||||||
|
// stack
|
||||||
|
v.executeOp(stack.SHR, ctx)
|
||||||
|
|
||||||
|
// Stack should have one item
|
||||||
|
assert.Equal(t, 1, ctx.Estack.Len())
|
||||||
|
|
||||||
|
item, err := ctx.Estack.PopInt()
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, int64(2), item.Value().Int64())
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue