diff --git a/asm/opcodes.go b/asm/opcodes.go index c3a3b9e..af20a8f 100644 --- a/asm/opcodes.go +++ b/asm/opcodes.go @@ -68,6 +68,9 @@ var opCodeByName = map[string]vm.OpCodeType{ "rett": vm.OpRetT, "returniffalse": vm.OpReturnIfFalse, "retf": vm.OpRetF, + + "squareroot": vm.OpSquareRoot, + "sqrt": vm.OpSqrt, } var nameByOpCode = map[vm.OpCodeType]string{ @@ -110,4 +113,6 @@ var nameByOpCode = map[vm.OpCodeType]string{ vm.OpRet: "ret", vm.OpRetT: "rett", vm.OpRetF: "retf", + + vm.OpSqrt: "sqrt", } diff --git a/gen/opcode.go b/gen/opcode.go index 5f69977..c82e2c7 100644 --- a/gen/opcode.go +++ b/gen/opcode.go @@ -44,6 +44,8 @@ var opCodes = []vm.OpCodeType{ vm.OpRet, vm.OpRetT, vm.OpRetF, + + vm.OpSqrt, } func randOpCode() vm.OpCodeType { diff --git a/grow/defs/sqrt.yaml b/grow/defs/sqrt.yaml new file mode 100644 index 0000000..277fe70 --- /dev/null +++ b/grow/defs/sqrt.yaml @@ -0,0 +1,15 @@ +global_memory_size: 1 +function_memory_size: 1 +instruction_limit: 2 +samples: +- in: [0] + out: [0] + +- in: [4] + out: [2] + +- in: [144] + out: [12] + +- in: [175] + out: [13] diff --git a/test/opcode_test.go b/test/opcode_test.go index ac5d430..7a0af8f 100644 --- a/test/opcode_test.go +++ b/test/opcode_test.go @@ -519,3 +519,27 @@ functions: expectGlobalMemory(t, state, 0, 7) } + +func TestSqrt(t *testing.T) { + state := assembleAndExecute(t, ` +global_memory_size: 4 +function_memory_size: 4 +functions: +- - [mov, g0, 1] + - [sqrt, g0] + + - [mov, g1, 4] + - [sqrt, g1] + + - [mov, g2, 144] + - [sqrt, g2] + + - [mov, g3, 175] + - [sqrt, g3] +`) + + expectGlobalMemory(t, state, 0, 1) + expectGlobalMemory(t, state, 1, 2) + expectGlobalMemory(t, state, 2, 12) + expectGlobalMemory(t, state, 3, 13) +} diff --git a/vm/opcode.go b/vm/opcode.go index 1e7546b..8e9d3d9 100644 --- a/vm/opcode.go +++ b/vm/opcode.go @@ -68,6 +68,10 @@ const ( OpRetT = OpReturnIfTrue OpReturnIfFalse = 0x00000802 OpRetF = OpReturnIfFalse + + OpSquareRoot = 0x00000900 + OpSqRt = OpSquareRoot + OpSqrt = OpSquareRoot ) type OperandNumericType int @@ -118,4 +122,6 @@ var OperandsByOpCode = map[OpCodeType][]OperandNumericType{ OpRet: []OperandNumericType{}, OpRetT: []OperandNumericType{}, OpRetF: []OperandNumericType{}, + + OpSqrt: []OperandNumericType{OperandReference}, } diff --git a/vm/ophandler.go b/vm/ophandler.go index 0d0be00..6e1a494 100644 --- a/vm/ophandler.go +++ b/vm/ophandler.go @@ -1,5 +1,7 @@ package vm +import "math" + type opHandler func(*State, *Instruction) var opHandlers = map[OpCodeType]opHandler{ @@ -42,6 +44,8 @@ var opHandlers = map[OpCodeType]opHandler{ OpReturn: (*State).handleReturn, OpReturnIfTrue: (*State).handleReturnIfTrue, OpReturnIfFalse: (*State).handleReturnIfFalse, + + OpSqrt: (*State).handleSqrt, } func (state *State) handleNoOp(instr *Instruction) { @@ -232,3 +236,8 @@ func (state *State) handleReturnIfFalse(instr *Instruction) { state.handleReturn(instr) } } + +func (state *State) handleSqrt(instr *Instruction) { + in := state.readUnsigned(instr.Operands[0]) + state.writeUnsigned(instr.Operands[0], uint64(math.Round(math.Sqrt(float64(in))))) +}