Implemented division
This commit is contained in:
parent
34af20d7a0
commit
2cbc064f14
@ -10,9 +10,11 @@ hello() {
|
|||||||
|
|
||||||
address += 4194304
|
address += 4194304
|
||||||
address += 1
|
address += 1
|
||||||
length += 5
|
|
||||||
length *= 2
|
length += 50
|
||||||
length -= 7
|
length -= 20
|
||||||
|
length *= 10
|
||||||
|
length /= 100
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
syscall(write, stdout, address, length)
|
syscall(write, stdout, address, length)
|
||||||
|
@ -130,6 +130,10 @@ func (f *Function) CompileInstruction(line token.List) error {
|
|||||||
case "*=":
|
case "*=":
|
||||||
f.Assembler.RegisterNumber(asm.MUL, register, number)
|
f.Assembler.RegisterNumber(asm.MUL, register, number)
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
case "/=":
|
||||||
|
f.Assembler.RegisterNumber(asm.DIV, register, number)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
src/build/arch/x64/Div.go
Normal file
20
src/build/arch/x64/Div.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package x64
|
||||||
|
|
||||||
|
import "git.akyoto.dev/cli/q/src/build/cpu"
|
||||||
|
|
||||||
|
// DivReg divides RDX:RAX by the value in the register.
|
||||||
|
func DivReg(code []byte, divisor cpu.Register) []byte {
|
||||||
|
rex := byte(0x48)
|
||||||
|
|
||||||
|
if divisor >= 8 {
|
||||||
|
rex++
|
||||||
|
divisor -= 8
|
||||||
|
}
|
||||||
|
|
||||||
|
return append(
|
||||||
|
code,
|
||||||
|
rex,
|
||||||
|
0xF7,
|
||||||
|
0xF8+byte(divisor),
|
||||||
|
)
|
||||||
|
}
|
39
src/build/arch/x64/Div_test.go
Normal file
39
src/build/arch/x64/Div_test.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package x64_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.akyoto.dev/cli/q/src/build/arch/x64"
|
||||||
|
"git.akyoto.dev/cli/q/src/build/cpu"
|
||||||
|
"git.akyoto.dev/go/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDivRegister(t *testing.T) {
|
||||||
|
usagePatterns := []struct {
|
||||||
|
Register cpu.Register
|
||||||
|
Code []byte
|
||||||
|
}{
|
||||||
|
{x64.RAX, []byte{0x48, 0xF7, 0xF8}},
|
||||||
|
{x64.RCX, []byte{0x48, 0xF7, 0xF9}},
|
||||||
|
{x64.RDX, []byte{0x48, 0xF7, 0xFA}},
|
||||||
|
{x64.RBX, []byte{0x48, 0xF7, 0xFB}},
|
||||||
|
{x64.RSP, []byte{0x48, 0xF7, 0xFC}},
|
||||||
|
{x64.RBP, []byte{0x48, 0xF7, 0xFD}},
|
||||||
|
{x64.RSI, []byte{0x48, 0xF7, 0xFE}},
|
||||||
|
{x64.RDI, []byte{0x48, 0xF7, 0xFF}},
|
||||||
|
{x64.R8, []byte{0x49, 0xF7, 0xF8}},
|
||||||
|
{x64.R9, []byte{0x49, 0xF7, 0xF9}},
|
||||||
|
{x64.R10, []byte{0x49, 0xF7, 0xFA}},
|
||||||
|
{x64.R11, []byte{0x49, 0xF7, 0xFB}},
|
||||||
|
{x64.R12, []byte{0x49, 0xF7, 0xFC}},
|
||||||
|
{x64.R13, []byte{0x49, 0xF7, 0xFD}},
|
||||||
|
{x64.R14, []byte{0x49, 0xF7, 0xFE}},
|
||||||
|
{x64.R15, []byte{0x49, 0xF7, 0xFF}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pattern := range usagePatterns {
|
||||||
|
t.Logf("idiv %s", pattern.Register)
|
||||||
|
code := x64.DivReg(nil, pattern.Register)
|
||||||
|
assert.DeepEqual(t, code, pattern.Code)
|
||||||
|
}
|
||||||
|
}
|
7
src/build/arch/x64/ExtendRAXToRDX.go
Normal file
7
src/build/arch/x64/ExtendRAXToRDX.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package x64
|
||||||
|
|
||||||
|
// ExtendRAXToRDX doubles the size of RAX by sign-extending it to RDX.
|
||||||
|
// This is also known as CQO.
|
||||||
|
func ExtendRAXToRDX(code []byte) []byte {
|
||||||
|
return append(code, 0x48, 0x99)
|
||||||
|
}
|
@ -45,6 +45,16 @@ func (a *Assembler) Finalize() ([]byte, []byte) {
|
|||||||
code = x64.MulRegNum(code, operands.Register, operands.Number)
|
code = x64.MulRegNum(code, operands.Register, operands.Number)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case DIV:
|
||||||
|
switch operands := x.Data.(type) {
|
||||||
|
case *RegisterNumber:
|
||||||
|
code = x64.MoveRegReg64(code, x64.RAX, operands.Register)
|
||||||
|
code = x64.MoveRegNum32(code, operands.Register, uint32(operands.Number))
|
||||||
|
code = x64.ExtendRAXToRDX(code)
|
||||||
|
code = x64.DivReg(code, operands.Register)
|
||||||
|
code = x64.MoveRegReg64(code, operands.Register, x64.RAX)
|
||||||
|
}
|
||||||
|
|
||||||
case CALL:
|
case CALL:
|
||||||
code = x64.Call(code, 0x00_00_00_00)
|
code = x64.Call(code, 0x00_00_00_00)
|
||||||
size := 4
|
size := 4
|
||||||
|
@ -6,6 +6,7 @@ const (
|
|||||||
NONE Mnemonic = iota
|
NONE Mnemonic = iota
|
||||||
ADD
|
ADD
|
||||||
CALL
|
CALL
|
||||||
|
DIV
|
||||||
JUMP
|
JUMP
|
||||||
MUL
|
MUL
|
||||||
LABEL
|
LABEL
|
||||||
@ -24,6 +25,9 @@ func (m Mnemonic) String() string {
|
|||||||
case CALL:
|
case CALL:
|
||||||
return "call"
|
return "call"
|
||||||
|
|
||||||
|
case DIV:
|
||||||
|
return "div"
|
||||||
|
|
||||||
case JUMP:
|
case JUMP:
|
||||||
return "jump"
|
return "jump"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user