package asmc import ( "git.akyoto.dev/cli/q/src/asm" "git.akyoto.dev/cli/q/src/x86" ) func (c *compiler) compile(x asm.Instruction) { switch x.Mnemonic { case asm.ADD: switch operands := x.Data.(type) { case *asm.RegisterNumber: c.code = x86.AddRegisterNumber(c.code, operands.Register, operands.Number) case *asm.RegisterRegister: c.code = x86.AddRegisterRegister(c.code, operands.Destination, operands.Source) } case asm.AND: switch operands := x.Data.(type) { case *asm.RegisterNumber: c.code = x86.AndRegisterNumber(c.code, operands.Register, operands.Number) case *asm.RegisterRegister: c.code = x86.AndRegisterRegister(c.code, operands.Destination, operands.Source) } case asm.SUB: switch operands := x.Data.(type) { case *asm.RegisterNumber: c.code = x86.SubRegisterNumber(c.code, operands.Register, operands.Number) case *asm.RegisterRegister: c.code = x86.SubRegisterRegister(c.code, operands.Destination, operands.Source) } case asm.MUL: switch operands := x.Data.(type) { case *asm.RegisterNumber: c.code = x86.MulRegisterNumber(c.code, operands.Register, operands.Number) case *asm.RegisterRegister: c.code = x86.MulRegisterRegister(c.code, operands.Destination, operands.Source) } case asm.DIV: switch operands := x.Data.(type) { case *asm.RegisterRegister: 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 operands := x.Data.(type) { case *asm.RegisterRegister: 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 operands := x.Data.(type) { case *asm.RegisterNumber: c.code = x86.CompareRegisterNumber(c.code, operands.Register, operands.Number) case *asm.RegisterRegister: 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.jump(x) case asm.LABEL: c.codeLabels[x.Data.(*asm.Label).Name] = Address(len(c.code)) case asm.LOAD: switch operands := x.Data.(type) { case *asm.MemoryRegister: c.code = x86.LoadRegister(c.code, operands.Register, operands.Address.Offset, operands.Address.Length, operands.Address.Base) } case asm.MOVE: c.move(x) case asm.NEGATE: switch operands := x.Data.(type) { case *asm.Register: c.code = x86.NegateRegister(c.code, operands.Register) } case asm.OR: switch operands := x.Data.(type) { case *asm.RegisterNumber: c.code = x86.OrRegisterNumber(c.code, operands.Register, operands.Number) case *asm.RegisterRegister: c.code = x86.OrRegisterRegister(c.code, operands.Destination, operands.Source) } case asm.POP: switch operands := x.Data.(type) { case *asm.Register: c.code = x86.PopRegister(c.code, operands.Register) } case asm.PUSH: switch operands := x.Data.(type) { case *asm.Number: c.code = x86.PushNumber(c.code, operands.Number) case *asm.Register: c.code = x86.PushRegister(c.code, operands.Register) } case asm.RETURN: c.code = x86.Return(c.code) case asm.SHIFTL: switch operands := x.Data.(type) { case *asm.RegisterNumber: c.code = x86.ShiftLeftNumber(c.code, operands.Register, byte(operands.Number)&0b111111) } case asm.SHIFTRS: switch operands := x.Data.(type) { case *asm.RegisterNumber: 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 operands := x.Data.(type) { case *asm.RegisterNumber: c.code = x86.XorRegisterNumber(c.code, operands.Register, operands.Number) case *asm.RegisterRegister: c.code = x86.XorRegisterRegister(c.code, operands.Destination, operands.Source) } default: panic("unknown mnemonic: " + x.Mnemonic.String()) } }