Implemented modulo operation

This commit is contained in:
Eduard Urbach 2024-07-25 12:11:55 +02:00
parent 65cc81032b
commit 60b8ff1308
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
7 changed files with 75 additions and 0 deletions

View File

@ -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:

View File

@ -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:

View File

@ -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
}

View File

@ -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)

View File

@ -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)

View 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)
}

View File

@ -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) {