Implemented modulo operation
This commit is contained in:
parent
65cc81032b
commit
60b8ff1308
@ -119,6 +119,9 @@ func (a Assembler) Finalize() ([]byte, []byte) {
|
|||||||
case LABEL:
|
case LABEL:
|
||||||
labels[x.Data.(*Label).Name] = Address(len(code))
|
labels[x.Data.(*Label).Name] = Address(len(code))
|
||||||
|
|
||||||
|
case MODULO:
|
||||||
|
code = modulo(code, x.Data)
|
||||||
|
|
||||||
case MOVE:
|
case MOVE:
|
||||||
switch operands := x.Data.(type) {
|
switch operands := x.Data.(type) {
|
||||||
case *RegisterNumber:
|
case *RegisterNumber:
|
||||||
|
@ -19,6 +19,7 @@ const (
|
|||||||
MUL
|
MUL
|
||||||
LABEL
|
LABEL
|
||||||
LOAD
|
LOAD
|
||||||
|
MODULO
|
||||||
MOVE
|
MOVE
|
||||||
POP
|
POP
|
||||||
PUSH
|
PUSH
|
||||||
@ -59,6 +60,8 @@ func (m Mnemonic) String() string {
|
|||||||
return "label"
|
return "label"
|
||||||
case LOAD:
|
case LOAD:
|
||||||
return "load"
|
return "load"
|
||||||
|
case MODULO:
|
||||||
|
return "mod"
|
||||||
case MOVE:
|
case MOVE:
|
||||||
return "move"
|
return "move"
|
||||||
case MUL:
|
case MUL:
|
||||||
|
@ -41,3 +41,28 @@ func divide(code []byte, data any) []byte {
|
|||||||
code = x64.PopRegister(code, x64.RDX)
|
code = x64.PopRegister(code, x64.RDX)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// modulo calculates the division remainder on x64 machines.
|
||||||
|
func modulo(code []byte, data any) []byte {
|
||||||
|
code = x64.PushRegister(code, x64.RDX)
|
||||||
|
code = x64.PushRegister(code, x64.RAX)
|
||||||
|
|
||||||
|
switch operands := data.(type) {
|
||||||
|
case *RegisterNumber:
|
||||||
|
code = x64.MoveRegisterRegister64(code, x64.RAX, operands.Register)
|
||||||
|
code = x64.MoveRegisterNumber32(code, operands.Register, uint32(operands.Number))
|
||||||
|
code = x64.ExtendRAXToRDX(code)
|
||||||
|
code = x64.DivRegister(code, operands.Register)
|
||||||
|
code = x64.MoveRegisterRegister64(code, operands.Register, x64.RDX)
|
||||||
|
|
||||||
|
case *RegisterRegister:
|
||||||
|
code = x64.MoveRegisterRegister64(code, x64.RAX, operands.Destination)
|
||||||
|
code = x64.ExtendRAXToRDX(code)
|
||||||
|
code = x64.DivRegister(code, operands.Source)
|
||||||
|
code = x64.MoveRegisterRegister64(code, operands.Destination, x64.RDX)
|
||||||
|
}
|
||||||
|
|
||||||
|
code = x64.PopRegister(code, x64.RAX)
|
||||||
|
code = x64.PopRegister(code, x64.RDX)
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
@ -22,6 +22,9 @@ func (f *Function) ExecuteRegisterNumber(operation token.Token, register cpu.Reg
|
|||||||
case token.Div, token.DivAssign:
|
case token.Div, token.DivAssign:
|
||||||
f.RegisterNumber(asm.DIV, register, number)
|
f.RegisterNumber(asm.DIV, register, number)
|
||||||
|
|
||||||
|
case token.Mod, token.ModAssign:
|
||||||
|
f.RegisterNumber(asm.MODULO, register, number)
|
||||||
|
|
||||||
case token.Equal, token.NotEqual, token.Less, token.LessEqual, token.Greater, token.GreaterEqual:
|
case token.Equal, token.NotEqual, token.Less, token.LessEqual, token.Greater, token.GreaterEqual:
|
||||||
f.RegisterNumber(asm.COMPARE, register, number)
|
f.RegisterNumber(asm.COMPARE, register, number)
|
||||||
|
|
||||||
|
@ -22,6 +22,9 @@ func (f *Function) ExecuteRegisterRegister(operation token.Token, destination cp
|
|||||||
case token.Div, token.DivAssign:
|
case token.Div, token.DivAssign:
|
||||||
f.RegisterRegister(asm.DIV, destination, source)
|
f.RegisterRegister(asm.DIV, destination, source)
|
||||||
|
|
||||||
|
case token.Mod, token.ModAssign:
|
||||||
|
f.RegisterRegister(asm.MODULO, destination, source)
|
||||||
|
|
||||||
case token.Equal, token.NotEqual, token.Less, token.LessEqual, token.Greater, token.GreaterEqual:
|
case token.Equal, token.NotEqual, token.Less, token.LessEqual, token.Greater, token.GreaterEqual:
|
||||||
f.RegisterRegister(asm.COMPARE, destination, source)
|
f.RegisterRegister(asm.COMPARE, destination, source)
|
||||||
|
|
||||||
|
37
tests/programs/remainder.q
Normal file
37
tests/programs/remainder.q
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
main() {
|
||||||
|
if 0 % 1 != 0 {
|
||||||
|
sys.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 1 % 1 != 0 {
|
||||||
|
sys.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 2 % 1 != 0 {
|
||||||
|
sys.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 0 % 2 != 0 {
|
||||||
|
sys.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 1 % 2 != 1 {
|
||||||
|
sys.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 2 % 2 != 0 {
|
||||||
|
sys.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 3 % 2 != 1 {
|
||||||
|
sys.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 256 % 10 != 6 {
|
||||||
|
sys.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
}
|
@ -35,6 +35,7 @@ var programs = []struct {
|
|||||||
{"jump-near", "", "", 0},
|
{"jump-near", "", "", 0},
|
||||||
{"loop", "", "", 0},
|
{"loop", "", "", 0},
|
||||||
{"loop-lifetime", "", "", 0},
|
{"loop-lifetime", "", "", 0},
|
||||||
|
{"remainder", "", "", 0},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrograms(t *testing.T) {
|
func TestPrograms(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user