Implemented modulo operation
This commit is contained in:
parent
65cc81032b
commit
60b8ff1308
@ -119,6 +119,9 @@ func (a Assembler) Finalize() ([]byte, []byte) {
|
||||
case LABEL:
|
||||
labels[x.Data.(*Label).Name] = Address(len(code))
|
||||
|
||||
case MODULO:
|
||||
code = modulo(code, x.Data)
|
||||
|
||||
case MOVE:
|
||||
switch operands := x.Data.(type) {
|
||||
case *RegisterNumber:
|
||||
|
@ -19,6 +19,7 @@ const (
|
||||
MUL
|
||||
LABEL
|
||||
LOAD
|
||||
MODULO
|
||||
MOVE
|
||||
POP
|
||||
PUSH
|
||||
@ -59,6 +60,8 @@ func (m Mnemonic) String() string {
|
||||
return "label"
|
||||
case LOAD:
|
||||
return "load"
|
||||
case MODULO:
|
||||
return "mod"
|
||||
case MOVE:
|
||||
return "move"
|
||||
case MUL:
|
||||
|
@ -41,3 +41,28 @@ func divide(code []byte, data any) []byte {
|
||||
code = x64.PopRegister(code, x64.RDX)
|
||||
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:
|
||||
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:
|
||||
f.RegisterNumber(asm.COMPARE, register, number)
|
||||
|
||||
|
@ -22,6 +22,9 @@ func (f *Function) ExecuteRegisterRegister(operation token.Token, destination cp
|
||||
case token.Div, token.DivAssign:
|
||||
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:
|
||||
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},
|
||||
{"loop", "", "", 0},
|
||||
{"loop-lifetime", "", "", 0},
|
||||
{"remainder", "", "", 0},
|
||||
}
|
||||
|
||||
func TestPrograms(t *testing.T) {
|
||||
|
Loading…
Reference in New Issue
Block a user