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