diff --git a/asm/opcodes.go b/asm/opcodes.go index d0384e4..f665dff 100644 --- a/asm/opcodes.go +++ b/asm/opcodes.go @@ -19,6 +19,11 @@ var opCodeByName = map[string]vm.OpCodeType{ "dividesigned": vm.OpDivideSigned, "divs": vm.OpDivS, + "not": vm.OpNot, + "and": vm.OpAnd, + "or": vm.OpOr, + "xor": vm.OpXor, + "isequal": vm.OpIsEqual, "eq": vm.OpEq, "islessthanunsigned": vm.OpIsLessThanUnsigned, @@ -79,6 +84,11 @@ var operandsByOpCode = map[vm.OpCodeType][]operandType{ vm.OpDivU: []operandType{r, u}, vm.OpDivS: []operandType{r, s}, + vm.OpNot: []operandType{r}, + vm.OpAnd: []operandType{r, u}, + vm.OpOr: []operandType{r, u}, + vm.OpXor: []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 8359890..bd66e0a 100644 --- a/test/opcode_test.go +++ b/test/opcode_test.go @@ -94,6 +94,47 @@ functions: expectGlobalMemorySigned(t, state, 2, 1) } +func TestNot(t *testing.T) { + state := assembleAndExecute(t, ` +functions: +- - [mov, g0, 8] + - [not, g0] + - [and, g0, 15] +`) + + expectGlobalMemory(t, state, 0, 7) +} + +func TestAnd(t *testing.T) { + state := assembleAndExecute(t, ` +functions: +- - [mov, g0, 7] + - [and, g0, 18] +`) + + expectGlobalMemory(t, state, 0, 2) +} + +func TestOr(t *testing.T) { + state := assembleAndExecute(t, ` +functions: +- - [mov, g0, 7] + - [or, g0, 18] +`) + + expectGlobalMemory(t, state, 0, 23) +} + +func TestXor(t *testing.T) { + state := assembleAndExecute(t, ` +functions: +- - [mov, g0, 7] + - [xor, g0, 18] +`) + + expectGlobalMemory(t, state, 0, 21) +} + func TestEq(t *testing.T) { state := assembleAndExecute(t, ` functions: diff --git a/vm/opcode.go b/vm/opcode.go index 956ba33..ad97b71 100644 --- a/vm/opcode.go +++ b/vm/opcode.go @@ -19,43 +19,48 @@ const ( OpDivideSigned = 0x00000204 OpDivS = OpDivideSigned - OpIsEqual = 0x00000300 + OpNot = 0x00000300 + OpAnd = 0x00000301 + OpOr = 0x00000302 + OpXor = 0x00000303 + + OpIsEqual = 0x00000400 OpEq = OpIsEqual - OpIsLessThanUnsigned = 0x00000301 + OpIsLessThanUnsigned = 0x00000401 OpLTU = OpIsLessThanUnsigned - OpIsLessThanSigned = 0x00000302 + OpIsLessThanSigned = 0x00000402 OpLTS = OpIsLessThanSigned - OpIsGreaterThanUnsigned = 0x00000303 + OpIsGreaterThanUnsigned = 0x00000403 OpGTU = OpIsGreaterThanUnsigned - OpIsGreaterThanSigned = 0x00000304 + OpIsGreaterThanSigned = 0x00000404 OpGTS = OpIsGreaterThanSigned - OpIsLessThanOrEqualUnsigned = 0x00000305 + OpIsLessThanOrEqualUnsigned = 0x00000405 OpLTEU = OpIsLessThanOrEqualUnsigned - OpIsLessThanOrEqualSigned = 0x00000306 + OpIsLessThanOrEqualSigned = 0x00000406 OpLTES = OpIsLessThanOrEqualSigned - OpIsGreaterThanOrEqualUnsigned = 0x00000307 + OpIsGreaterThanOrEqualUnsigned = 0x00000407 OpGTEU = OpIsGreaterThanOrEqualUnsigned - OpIsGreaterThanOrEqualSigned = 0x00000308 + OpIsGreaterThanOrEqualSigned = 0x00000408 OpGTES = OpIsGreaterThanOrEqualSigned - OpJump = 0x00000400 + OpJump = 0x00000500 OpJmp = OpJump - OpJumpIfTrue = 0x00000401 + OpJumpIfTrue = 0x00000501 OpJmpT = OpJumpIfTrue - OpJumpIfFalse = 0x00000402 + OpJumpIfFalse = 0x00000502 OpJmpF = OpJumpIfFalse - OpCall = 0x00000500 + OpCall = 0x00000600 OpCal = OpCall - OpCallIfTrue = 0x00000501 + OpCallIfTrue = 0x00000601 OpCalT = OpCallIfTrue - OpCallIfFalse = 0x00000502 + OpCallIfFalse = 0x00000602 OpCalF = OpCallIfFalse - OpReturn = 0x00000600 + OpReturn = 0x00000700 OpRet = OpReturn - OpReturnIfTrue = 0x00000601 + OpReturnIfTrue = 0x00000701 OpRetT = OpReturnIfTrue - OpReturnIfFalse = 0x00000602 + OpReturnIfFalse = 0x00000702 OpRetF = OpReturnIfFalse ) diff --git a/vm/ophandler.go b/vm/ophandler.go index 330ab93..2959259 100644 --- a/vm/ophandler.go +++ b/vm/ophandler.go @@ -13,6 +13,11 @@ var opHandlers = map[OpCodeType]opHandler{ OpDivideUnsigned: (*State).handleDivideUnsigned, OpDivideSigned: (*State).handleDivideSigned, + OpNot: (*State).handleNot, + OpAnd: (*State).handleAnd, + OpOr: (*State).handleOr, + OpXor: (*State).handleXor, + OpIsEqual: (*State).handleIsEqual, OpIsLessThanUnsigned: (*State).handleIsLessThanUnsigned, OpIsLessThanSigned: (*State).handleIsLessThanSigned, @@ -74,6 +79,29 @@ func (state *State) handleDivideSigned(instr *Instruction) { state.writeSigned(&instr.Operand1, in1/in2) } +func (state *State) handleNot(instr *Instruction) { + in := state.readUnsigned(&instr.Operand1) + state.writeUnsigned(&instr.Operand1, in^uint64(0xffffffffffffffff)) +} + +func (state *State) handleAnd(instr *Instruction) { + in1 := state.readUnsigned(&instr.Operand1) + in2 := state.readUnsigned(&instr.Operand2) + state.writeUnsigned(&instr.Operand1, in1&in2) +} + +func (state *State) handleOr(instr *Instruction) { + in1 := state.readUnsigned(&instr.Operand1) + in2 := state.readUnsigned(&instr.Operand2) + state.writeUnsigned(&instr.Operand1, in1|in2) +} + +func (state *State) handleXor(instr *Instruction) { + in1 := state.readUnsigned(&instr.Operand1) + in2 := state.readUnsigned(&instr.Operand2) + state.writeUnsigned(&instr.Operand1, in1^in2) +} + func (state *State) handleIsEqual(instr *Instruction) { in1 := state.readUnsigned(&instr.Operand1) in2 := state.readUnsigned(&instr.Operand2)