Bitwise operators
This commit is contained in:
@@ -19,6 +19,11 @@ var opCodeByName = map[string]vm.OpCodeType{
|
|||||||
"dividesigned": vm.OpDivideSigned,
|
"dividesigned": vm.OpDivideSigned,
|
||||||
"divs": vm.OpDivS,
|
"divs": vm.OpDivS,
|
||||||
|
|
||||||
|
"not": vm.OpNot,
|
||||||
|
"and": vm.OpAnd,
|
||||||
|
"or": vm.OpOr,
|
||||||
|
"xor": vm.OpXor,
|
||||||
|
|
||||||
"isequal": vm.OpIsEqual,
|
"isequal": vm.OpIsEqual,
|
||||||
"eq": vm.OpEq,
|
"eq": vm.OpEq,
|
||||||
"islessthanunsigned": vm.OpIsLessThanUnsigned,
|
"islessthanunsigned": vm.OpIsLessThanUnsigned,
|
||||||
@@ -79,6 +84,11 @@ var operandsByOpCode = map[vm.OpCodeType][]operandType{
|
|||||||
vm.OpDivU: []operandType{r, u},
|
vm.OpDivU: []operandType{r, u},
|
||||||
vm.OpDivS: []operandType{r, s},
|
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.OpEq: []operandType{us, us},
|
||||||
vm.OpLTU: []operandType{u, u},
|
vm.OpLTU: []operandType{u, u},
|
||||||
vm.OpLTS: []operandType{s, s},
|
vm.OpLTS: []operandType{s, s},
|
||||||
|
|||||||
@@ -94,6 +94,47 @@ functions:
|
|||||||
expectGlobalMemorySigned(t, state, 2, 1)
|
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) {
|
func TestEq(t *testing.T) {
|
||||||
state := assembleAndExecute(t, `
|
state := assembleAndExecute(t, `
|
||||||
functions:
|
functions:
|
||||||
|
|||||||
41
vm/opcode.go
41
vm/opcode.go
@@ -19,43 +19,48 @@ const (
|
|||||||
OpDivideSigned = 0x00000204
|
OpDivideSigned = 0x00000204
|
||||||
OpDivS = OpDivideSigned
|
OpDivS = OpDivideSigned
|
||||||
|
|
||||||
OpIsEqual = 0x00000300
|
OpNot = 0x00000300
|
||||||
|
OpAnd = 0x00000301
|
||||||
|
OpOr = 0x00000302
|
||||||
|
OpXor = 0x00000303
|
||||||
|
|
||||||
|
OpIsEqual = 0x00000400
|
||||||
OpEq = OpIsEqual
|
OpEq = OpIsEqual
|
||||||
OpIsLessThanUnsigned = 0x00000301
|
OpIsLessThanUnsigned = 0x00000401
|
||||||
OpLTU = OpIsLessThanUnsigned
|
OpLTU = OpIsLessThanUnsigned
|
||||||
OpIsLessThanSigned = 0x00000302
|
OpIsLessThanSigned = 0x00000402
|
||||||
OpLTS = OpIsLessThanSigned
|
OpLTS = OpIsLessThanSigned
|
||||||
OpIsGreaterThanUnsigned = 0x00000303
|
OpIsGreaterThanUnsigned = 0x00000403
|
||||||
OpGTU = OpIsGreaterThanUnsigned
|
OpGTU = OpIsGreaterThanUnsigned
|
||||||
OpIsGreaterThanSigned = 0x00000304
|
OpIsGreaterThanSigned = 0x00000404
|
||||||
OpGTS = OpIsGreaterThanSigned
|
OpGTS = OpIsGreaterThanSigned
|
||||||
OpIsLessThanOrEqualUnsigned = 0x00000305
|
OpIsLessThanOrEqualUnsigned = 0x00000405
|
||||||
OpLTEU = OpIsLessThanOrEqualUnsigned
|
OpLTEU = OpIsLessThanOrEqualUnsigned
|
||||||
OpIsLessThanOrEqualSigned = 0x00000306
|
OpIsLessThanOrEqualSigned = 0x00000406
|
||||||
OpLTES = OpIsLessThanOrEqualSigned
|
OpLTES = OpIsLessThanOrEqualSigned
|
||||||
OpIsGreaterThanOrEqualUnsigned = 0x00000307
|
OpIsGreaterThanOrEqualUnsigned = 0x00000407
|
||||||
OpGTEU = OpIsGreaterThanOrEqualUnsigned
|
OpGTEU = OpIsGreaterThanOrEqualUnsigned
|
||||||
OpIsGreaterThanOrEqualSigned = 0x00000308
|
OpIsGreaterThanOrEqualSigned = 0x00000408
|
||||||
OpGTES = OpIsGreaterThanOrEqualSigned
|
OpGTES = OpIsGreaterThanOrEqualSigned
|
||||||
|
|
||||||
OpJump = 0x00000400
|
OpJump = 0x00000500
|
||||||
OpJmp = OpJump
|
OpJmp = OpJump
|
||||||
OpJumpIfTrue = 0x00000401
|
OpJumpIfTrue = 0x00000501
|
||||||
OpJmpT = OpJumpIfTrue
|
OpJmpT = OpJumpIfTrue
|
||||||
OpJumpIfFalse = 0x00000402
|
OpJumpIfFalse = 0x00000502
|
||||||
OpJmpF = OpJumpIfFalse
|
OpJmpF = OpJumpIfFalse
|
||||||
|
|
||||||
OpCall = 0x00000500
|
OpCall = 0x00000600
|
||||||
OpCal = OpCall
|
OpCal = OpCall
|
||||||
OpCallIfTrue = 0x00000501
|
OpCallIfTrue = 0x00000601
|
||||||
OpCalT = OpCallIfTrue
|
OpCalT = OpCallIfTrue
|
||||||
OpCallIfFalse = 0x00000502
|
OpCallIfFalse = 0x00000602
|
||||||
OpCalF = OpCallIfFalse
|
OpCalF = OpCallIfFalse
|
||||||
|
|
||||||
OpReturn = 0x00000600
|
OpReturn = 0x00000700
|
||||||
OpRet = OpReturn
|
OpRet = OpReturn
|
||||||
OpReturnIfTrue = 0x00000601
|
OpReturnIfTrue = 0x00000701
|
||||||
OpRetT = OpReturnIfTrue
|
OpRetT = OpReturnIfTrue
|
||||||
OpReturnIfFalse = 0x00000602
|
OpReturnIfFalse = 0x00000702
|
||||||
OpRetF = OpReturnIfFalse
|
OpRetF = OpReturnIfFalse
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ var opHandlers = map[OpCodeType]opHandler{
|
|||||||
OpDivideUnsigned: (*State).handleDivideUnsigned,
|
OpDivideUnsigned: (*State).handleDivideUnsigned,
|
||||||
OpDivideSigned: (*State).handleDivideSigned,
|
OpDivideSigned: (*State).handleDivideSigned,
|
||||||
|
|
||||||
|
OpNot: (*State).handleNot,
|
||||||
|
OpAnd: (*State).handleAnd,
|
||||||
|
OpOr: (*State).handleOr,
|
||||||
|
OpXor: (*State).handleXor,
|
||||||
|
|
||||||
OpIsEqual: (*State).handleIsEqual,
|
OpIsEqual: (*State).handleIsEqual,
|
||||||
OpIsLessThanUnsigned: (*State).handleIsLessThanUnsigned,
|
OpIsLessThanUnsigned: (*State).handleIsLessThanUnsigned,
|
||||||
OpIsLessThanSigned: (*State).handleIsLessThanSigned,
|
OpIsLessThanSigned: (*State).handleIsLessThanSigned,
|
||||||
@@ -74,6 +79,29 @@ func (state *State) handleDivideSigned(instr *Instruction) {
|
|||||||
state.writeSigned(&instr.Operand1, in1/in2)
|
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) {
|
func (state *State) handleIsEqual(instr *Instruction) {
|
||||||
in1 := state.readUnsigned(&instr.Operand1)
|
in1 := state.readUnsigned(&instr.Operand1)
|
||||||
in2 := state.readUnsigned(&instr.Operand2)
|
in2 := state.readUnsigned(&instr.Operand2)
|
||||||
|
|||||||
Reference in New Issue
Block a user