185 lines
5.3 KiB
Go
185 lines
5.3 KiB
Go
package asmc
|
|
|
|
import (
|
|
"git.urbach.dev/cli/q/src/asm"
|
|
"git.urbach.dev/cli/q/src/x86"
|
|
)
|
|
|
|
func (c *compiler) compileX86(x asm.Instruction) {
|
|
switch x.Mnemonic {
|
|
case asm.ADD:
|
|
switch x.Type {
|
|
case asm.TypeRegisterNumber:
|
|
operands := c.assembler.Param.RegisterNumber[x.Index]
|
|
c.code = x86.AddRegisterNumber(c.code, operands.Register, operands.Number)
|
|
case asm.TypeRegisterRegister:
|
|
operands := c.assembler.Param.RegisterRegister[x.Index]
|
|
c.code = x86.AddRegisterRegister(c.code, operands.Destination, operands.Source)
|
|
}
|
|
|
|
case asm.AND:
|
|
switch x.Type {
|
|
case asm.TypeRegisterNumber:
|
|
operands := c.assembler.Param.RegisterNumber[x.Index]
|
|
c.code = x86.AndRegisterNumber(c.code, operands.Register, operands.Number)
|
|
case asm.TypeRegisterRegister:
|
|
operands := c.assembler.Param.RegisterRegister[x.Index]
|
|
c.code = x86.AndRegisterRegister(c.code, operands.Destination, operands.Source)
|
|
}
|
|
|
|
case asm.SUB:
|
|
switch x.Type {
|
|
case asm.TypeRegisterNumber:
|
|
operands := c.assembler.Param.RegisterNumber[x.Index]
|
|
c.code = x86.SubRegisterNumber(c.code, operands.Register, operands.Number)
|
|
case asm.TypeRegisterRegister:
|
|
operands := c.assembler.Param.RegisterRegister[x.Index]
|
|
c.code = x86.SubRegisterRegister(c.code, operands.Destination, operands.Source)
|
|
}
|
|
|
|
case asm.MUL:
|
|
switch x.Type {
|
|
case asm.TypeRegisterNumber:
|
|
operands := c.assembler.Param.RegisterNumber[x.Index]
|
|
c.code = x86.MulRegisterNumber(c.code, operands.Register, operands.Number)
|
|
case asm.TypeRegisterRegister:
|
|
operands := c.assembler.Param.RegisterRegister[x.Index]
|
|
c.code = x86.MulRegisterRegister(c.code, operands.Destination, operands.Source)
|
|
}
|
|
|
|
case asm.DIV:
|
|
switch x.Type {
|
|
case asm.TypeRegisterRegister:
|
|
operands := c.assembler.Param.RegisterRegister[x.Index]
|
|
if operands.Destination != x86.RAX {
|
|
c.code = x86.MoveRegisterRegister(c.code, x86.RAX, operands.Destination)
|
|
}
|
|
|
|
c.code = x86.ExtendRAXToRDX(c.code)
|
|
c.code = x86.DivRegister(c.code, operands.Source)
|
|
|
|
if operands.Destination != x86.RAX {
|
|
c.code = x86.MoveRegisterRegister(c.code, operands.Destination, x86.RAX)
|
|
}
|
|
}
|
|
|
|
case asm.MODULO:
|
|
switch x.Type {
|
|
case asm.TypeRegisterRegister:
|
|
operands := c.assembler.Param.RegisterRegister[x.Index]
|
|
if operands.Destination != x86.RAX {
|
|
c.code = x86.MoveRegisterRegister(c.code, x86.RAX, operands.Destination)
|
|
}
|
|
|
|
c.code = x86.ExtendRAXToRDX(c.code)
|
|
c.code = x86.DivRegister(c.code, operands.Source)
|
|
|
|
if operands.Destination != x86.RDX {
|
|
c.code = x86.MoveRegisterRegister(c.code, operands.Destination, x86.RDX)
|
|
}
|
|
}
|
|
|
|
case asm.CALL:
|
|
c.call(x)
|
|
|
|
case asm.COMMENT:
|
|
return
|
|
|
|
case asm.COMPARE:
|
|
switch x.Type {
|
|
case asm.TypeRegisterNumber:
|
|
operands := c.assembler.Param.RegisterNumber[x.Index]
|
|
c.code = x86.CompareRegisterNumber(c.code, operands.Register, operands.Number)
|
|
case asm.TypeRegisterRegister:
|
|
operands := c.assembler.Param.RegisterRegister[x.Index]
|
|
c.code = x86.CompareRegisterRegister(c.code, operands.Destination, operands.Source)
|
|
}
|
|
|
|
case asm.DLLCALL:
|
|
c.dllCall(x)
|
|
|
|
case asm.JE, asm.JNE, asm.JG, asm.JGE, asm.JL, asm.JLE, asm.JUMP:
|
|
c.jumpX86(x)
|
|
|
|
case asm.LABEL:
|
|
label := c.assembler.Param.Label[x.Index]
|
|
c.codeLabels[label.Name] = Address(len(c.code))
|
|
|
|
case asm.LOAD:
|
|
c.load(x)
|
|
|
|
case asm.MOVE:
|
|
c.move(x)
|
|
|
|
case asm.NEGATE:
|
|
switch x.Type {
|
|
case asm.TypeRegister:
|
|
operands := c.assembler.Param.Register[x.Index]
|
|
c.code = x86.NegateRegister(c.code, operands.Register)
|
|
}
|
|
|
|
case asm.OR:
|
|
switch x.Type {
|
|
case asm.TypeRegisterNumber:
|
|
operands := c.assembler.Param.RegisterNumber[x.Index]
|
|
c.code = x86.OrRegisterNumber(c.code, operands.Register, operands.Number)
|
|
case asm.TypeRegisterRegister:
|
|
operands := c.assembler.Param.RegisterRegister[x.Index]
|
|
c.code = x86.OrRegisterRegister(c.code, operands.Destination, operands.Source)
|
|
}
|
|
|
|
case asm.POP:
|
|
switch x.Type {
|
|
case asm.TypeRegister:
|
|
operands := c.assembler.Param.Register[x.Index]
|
|
c.code = x86.PopRegister(c.code, operands.Register)
|
|
}
|
|
|
|
case asm.PUSH:
|
|
switch x.Type {
|
|
case asm.TypeNumber:
|
|
operands := c.assembler.Param.Number[x.Index]
|
|
c.code = x86.PushNumber(c.code, int32(operands.Number))
|
|
case asm.TypeRegister:
|
|
operands := c.assembler.Param.Register[x.Index]
|
|
c.code = x86.PushRegister(c.code, operands.Register)
|
|
}
|
|
|
|
case asm.RETURN:
|
|
c.code = x86.Return(c.code)
|
|
|
|
case asm.SHIFTL:
|
|
switch x.Type {
|
|
case asm.TypeRegisterNumber:
|
|
operands := c.assembler.Param.RegisterNumber[x.Index]
|
|
c.code = x86.ShiftLeftNumber(c.code, operands.Register, byte(operands.Number)&0b111111)
|
|
}
|
|
|
|
case asm.SHIFTRS:
|
|
switch x.Type {
|
|
case asm.TypeRegisterNumber:
|
|
operands := c.assembler.Param.RegisterNumber[x.Index]
|
|
c.code = x86.ShiftRightSignedNumber(c.code, operands.Register, byte(operands.Number)&0b111111)
|
|
}
|
|
|
|
case asm.STORE:
|
|
c.store(x)
|
|
|
|
case asm.SYSCALL:
|
|
c.code = x86.Syscall(c.code)
|
|
|
|
case asm.XOR:
|
|
switch x.Type {
|
|
case asm.TypeRegisterNumber:
|
|
operands := c.assembler.Param.RegisterNumber[x.Index]
|
|
c.code = x86.XorRegisterNumber(c.code, operands.Register, operands.Number)
|
|
case asm.TypeRegisterRegister:
|
|
operands := c.assembler.Param.RegisterRegister[x.Index]
|
|
c.code = x86.XorRegisterRegister(c.code, operands.Destination, operands.Source)
|
|
}
|
|
|
|
default:
|
|
panic("unknown mnemonic: " + x.Mnemonic.String())
|
|
}
|
|
}
|