diff --git a/asm/opcodes.go b/asm/opcodes.go index f665dff..20e151b 100644 --- a/asm/opcodes.go +++ b/asm/opcodes.go @@ -24,6 +24,11 @@ var opCodeByName = map[string]vm.OpCodeType{ "or": vm.OpOr, "xor": vm.OpXor, + "shiftright": vm.OpShiftRight, + "shr": vm.OpShR, + "shiftleft": vm.OpShiftLeft, + "shl": vm.OpShL, + "isequal": vm.OpIsEqual, "eq": vm.OpEq, "islessthanunsigned": vm.OpIsLessThanUnsigned, @@ -89,6 +94,9 @@ var operandsByOpCode = map[vm.OpCodeType][]operandType{ vm.OpOr: []operandType{r, u}, vm.OpXor: []operandType{r, u}, + vm.OpShR: []operandType{r, u}, + vm.OpShL: []operandType{r, u}, + vm.OpEq: []operandType{us, us}, vm.OpLTU: []operandType{u, u}, vm.OpLTS: []operandType{s, s}, diff --git a/test/opcode_test.go b/test/opcode_test.go index bd66e0a..02ddbac 100644 --- a/test/opcode_test.go +++ b/test/opcode_test.go @@ -135,6 +135,26 @@ functions: expectGlobalMemory(t, state, 0, 21) } +func TestShR(t *testing.T) { + state := assembleAndExecute(t, ` +functions: +- - [mov, g0, 53] + - [shr, g0, 2] +`) + + expectGlobalMemory(t, state, 0, 13) +} + +func TestShL(t *testing.T) { + state := assembleAndExecute(t, ` +functions: +- - [mov, g0, 53] + - [shl, g0, 2] +`) + + expectGlobalMemory(t, state, 0, 212) +} + func TestEq(t *testing.T) { state := assembleAndExecute(t, ` functions: diff --git a/vm/opcode.go b/vm/opcode.go index ad97b71..20809b9 100644 --- a/vm/opcode.go +++ b/vm/opcode.go @@ -24,43 +24,48 @@ const ( OpOr = 0x00000302 OpXor = 0x00000303 - OpIsEqual = 0x00000400 + OpShiftRight = 0x00000400 + OpShR = OpShiftRight + OpShiftLeft = 0x00000401 + OpShL = OpShiftLeft + + OpIsEqual = 0x00000500 OpEq = OpIsEqual - OpIsLessThanUnsigned = 0x00000401 + OpIsLessThanUnsigned = 0x00000501 OpLTU = OpIsLessThanUnsigned - OpIsLessThanSigned = 0x00000402 + OpIsLessThanSigned = 0x00000502 OpLTS = OpIsLessThanSigned - OpIsGreaterThanUnsigned = 0x00000403 + OpIsGreaterThanUnsigned = 0x00000503 OpGTU = OpIsGreaterThanUnsigned - OpIsGreaterThanSigned = 0x00000404 + OpIsGreaterThanSigned = 0x00000504 OpGTS = OpIsGreaterThanSigned - OpIsLessThanOrEqualUnsigned = 0x00000405 + OpIsLessThanOrEqualUnsigned = 0x00000505 OpLTEU = OpIsLessThanOrEqualUnsigned - OpIsLessThanOrEqualSigned = 0x00000406 + OpIsLessThanOrEqualSigned = 0x00000506 OpLTES = OpIsLessThanOrEqualSigned - OpIsGreaterThanOrEqualUnsigned = 0x00000407 + OpIsGreaterThanOrEqualUnsigned = 0x00000507 OpGTEU = OpIsGreaterThanOrEqualUnsigned - OpIsGreaterThanOrEqualSigned = 0x00000408 + OpIsGreaterThanOrEqualSigned = 0x00000508 OpGTES = OpIsGreaterThanOrEqualSigned - OpJump = 0x00000500 + OpJump = 0x00000600 OpJmp = OpJump - OpJumpIfTrue = 0x00000501 + OpJumpIfTrue = 0x00000601 OpJmpT = OpJumpIfTrue - OpJumpIfFalse = 0x00000502 + OpJumpIfFalse = 0x00000602 OpJmpF = OpJumpIfFalse - OpCall = 0x00000600 + OpCall = 0x00000700 OpCal = OpCall - OpCallIfTrue = 0x00000601 + OpCallIfTrue = 0x00000701 OpCalT = OpCallIfTrue - OpCallIfFalse = 0x00000602 + OpCallIfFalse = 0x00000702 OpCalF = OpCallIfFalse - OpReturn = 0x00000700 + OpReturn = 0x00000800 OpRet = OpReturn - OpReturnIfTrue = 0x00000701 + OpReturnIfTrue = 0x00000801 OpRetT = OpReturnIfTrue - OpReturnIfFalse = 0x00000702 + OpReturnIfFalse = 0x00000802 OpRetF = OpReturnIfFalse ) diff --git a/vm/ophandler.go b/vm/ophandler.go index d58055f..e75a573 100644 --- a/vm/ophandler.go +++ b/vm/ophandler.go @@ -18,6 +18,9 @@ var opHandlers = map[OpCodeType]opHandler{ OpOr: (*State).handleOr, OpXor: (*State).handleXor, + OpShiftRight: (*State).handleShiftRight, + OpShiftLeft: (*State).handleShiftLeft, + OpIsEqual: (*State).handleIsEqual, OpIsLessThanUnsigned: (*State).handleIsLessThanUnsigned, OpIsLessThanSigned: (*State).handleIsLessThanSigned, @@ -102,6 +105,18 @@ func (state *State) handleXor(instr *Instruction) { state.writeUnsigned(&instr.Operand1, in1^in2) } +func (state *State) handleShiftRight(instr *Instruction) { + in1 := state.readUnsigned(&instr.Operand1) + in2 := state.readUnsigned(&instr.Operand2) + state.writeUnsigned(&instr.Operand1, in1>>in2) +} + +func (state *State) handleShiftLeft(instr *Instruction) { + in1 := state.readUnsigned(&instr.Operand1) + in2 := state.readUnsigned(&instr.Operand2) + state.writeUnsigned(&instr.Operand1, in1<