Skip to content
X86InstrInfo.td 57.4 KiB
Newer Older
//===- X86InstrInfo.td - Describe the X86 Instruction Set -------*- C++ -*-===//
// 
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
// 
//===----------------------------------------------------------------------===//
//
// This file describes the X86 instruction set, defining the instructions, and
// properties of the instructions which are needed for code generation, machine
// code emission, and analysis.
//
//===----------------------------------------------------------------------===//

// *mem - Operand definitions for the funky X86 addressing mode operands.
//

class X86MemOperand<ValueType Ty> : Operand<Ty> {
  let NumMIOperands = 4;
  let PrintMethod = "printMemoryOperand";
}

def i8mem  : X86MemOperand<i8>;
def i16mem : X86MemOperand<i16>;
def i32mem : X86MemOperand<i32>;
def i64mem : X86MemOperand<i64>;
def f32mem : X86MemOperand<f32>;
def f64mem : X86MemOperand<f64>;
def f80mem : X86MemOperand<f80>;
// PCRelative calls need special operand formatting.
let PrintMethod = "printCallOperand" in
  def calltarget : Operand<i32>;

// Format specifies the encoding used by the instruction.  This is part of the
// ad-hoc solution used to emit machine instruction encodings by our machine
// code emitter.
class Format<bits<5> val> {
  bits<5> Value = val;
}

def Pseudo     : Format<0>; def RawFrm     : Format<1>;
def AddRegFrm  : Format<2>; def MRMDestReg : Format<3>;
def MRMDestMem : Format<4>; def MRMSrcReg  : Format<5>;
def MRMSrcMem  : Format<6>;
def MRM0r  : Format<16>; def MRM1r  : Format<17>; def MRM2r  : Format<18>;
def MRM3r  : Format<19>; def MRM4r  : Format<20>; def MRM5r  : Format<21>;
def MRM6r  : Format<22>; def MRM7r  : Format<23>;
def MRM0m  : Format<24>; def MRM1m  : Format<25>; def MRM2m  : Format<26>;
def MRM3m  : Format<27>; def MRM4m  : Format<28>; def MRM5m  : Format<29>;
def MRM6m  : Format<30>; def MRM7m  : Format<31>;
// ImmType - This specifies the immediate type used by an instruction. This is
// part of the ad-hoc solution used to emit machine instruction encodings by our
// machine code emitter.
class ImmType<bits<2> val> {
  bits<2> Value = val;
}
def NoImm  : ImmType<0>;
def Imm8   : ImmType<1>;
def Imm16  : ImmType<2>;
def Imm32  : ImmType<3>;

// FPFormat - This specifies what form this FP instruction has.  This is used by
// the Floating-Point stackifier pass.
class FPFormat<bits<3> val> {
  bits<3> Value = val;
}
def NotFP      : FPFormat<0>;
def ZeroArgFP  : FPFormat<1>;
def OneArgFP   : FPFormat<2>;
def OneArgFPRW : FPFormat<3>;
def TwoArgFP   : FPFormat<4>;
def CompareFP  : FPFormat<5>;
def CondMovFP  : FPFormat<6>;
def SpecialFP  : FPFormat<7>;
class X86Inst<bits<8> opcod, Format f, ImmType i, dag ops, string AsmStr> : Instruction {
  let Namespace = "X86";

  bits<8> Opcode = opcod;
  Format Form = f;
  bits<5> FormBits = Form.Value;
  ImmType ImmT = i;
  bits<2> ImmTypeBits = ImmT.Value;
  dag OperandList = ops;
  string AsmString = AsmStr;

  // Attributes specific to X86 instructions...
  bit hasOpSizePrefix = 0; // Does this inst have a 0x66 prefix?
  bits<4> Prefix = 0;       // Which prefix byte does this inst have?
  FPFormat FPForm;          // What flavor of FP instruction is this?
  bits<3> FPFormBits = 0;
}

class Imp<list<Register> uses, list<Register> defs> {
  list<Register> Uses = uses;
  list<Register> Defs = defs;
}


// Prefix byte classes which are used to indicate to the ad-hoc machine code
// emitter that various prefix bytes are required.
class OpSize { bit hasOpSizePrefix = 1; }
class TB     { bits<4> Prefix = 1; }
class REP    { bits<4> Prefix = 2; }
class D8     { bits<4> Prefix = 3; }
class D9     { bits<4> Prefix = 4; }
class DA     { bits<4> Prefix = 5; }
class DB     { bits<4> Prefix = 6; }
class DC     { bits<4> Prefix = 7; }
class DD     { bits<4> Prefix = 8; }
class DE     { bits<4> Prefix = 9; }
class DF     { bits<4> Prefix = 10; }
//===----------------------------------------------------------------------===//
// Instruction templates...

class I<bits<8> o, Format f, dag ops, string asm> : X86Inst<o, f, NoImm, ops, asm>;
class Ii8 <bits<8> o, Format f, dag ops, string asm> : X86Inst<o, f, Imm8 , ops, asm>;
class Ii16<bits<8> o, Format f, dag ops, string asm> : X86Inst<o, f, Imm16, ops, asm>;
class Ii32<bits<8> o, Format f, dag ops, string asm> : X86Inst<o, f, Imm32, ops, asm>;
//===----------------------------------------------------------------------===//
// Instruction list...
//

def PHI : I<0, Pseudo, (ops), "PHINODE">;        // PHI node.
def NOOP : I<0x90, RawFrm, (ops), "nop">; // nop
def ADJCALLSTACKDOWN : I<0, Pseudo, (ops), "#ADJCALLSTACKDOWN">;
def ADJCALLSTACKUP   : I<0, Pseudo, (ops), "#ADJCALLSTACKUP">;
def IMPLICIT_USE     : I<0, Pseudo, (ops), "#IMPLICIT_USE">;
def IMPLICIT_DEF     : I<0, Pseudo, (ops), "#IMPLICIT_DEF">;
let isTerminator = 1 in
  let Defs = [FP0, FP1, FP2, FP3, FP4, FP5, FP6] in
    def FP_REG_KILL  : I<0, Pseudo, (ops), "#FP_REG_KILL">;
//===----------------------------------------------------------------------===//
//  Control Flow Instructions...
//

// Return instruction...
let isTerminator = 1, isReturn = 1, isBarrier = 1 in
  def RET : I<0xC3, RawFrm, (ops), "ret">;

// All branches are RawFrm, Void, Branch, and Terminators
let isBranch = 1, isTerminator = 1 in
  class IBr<bits<8> opcode, dag ops, string asm> : I<opcode, RawFrm, ops, asm>;
  def JMP : IBr<0xE9, (ops i32imm:$dst), "jmp $dst">;
def JB  : IBr<0x82, (ops i32imm:$dst), "jb $dst">, TB;
def JAE : IBr<0x83, (ops i32imm:$dst), "jae $dst">, TB;
def JE  : IBr<0x84, (ops i32imm:$dst), "je $dst">, TB;
def JNE : IBr<0x85, (ops i32imm:$dst), "jne $dst">, TB;
def JBE : IBr<0x86, (ops i32imm:$dst), "jbe $dst">, TB;
def JA  : IBr<0x87, (ops i32imm:$dst), "ja $dst">, TB;
def JS  : IBr<0x88, (ops i32imm:$dst), "js $dst">, TB;
def JNS : IBr<0x89, (ops i32imm:$dst), "jns $dst">, TB;
def JL  : IBr<0x8C, (ops i32imm:$dst), "jl $dst">, TB;
def JGE : IBr<0x8D, (ops i32imm:$dst), "jge $dst">, TB;
def JLE : IBr<0x8E, (ops i32imm:$dst), "jle $dst">, TB;
def JG  : IBr<0x8F, (ops i32imm:$dst), "jg $dst">, TB;


//===----------------------------------------------------------------------===//
//  Call Instructions...
//
let isCall = 1 in
  // All calls clobber the non-callee saved registers...
  let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0] in {
    def CALLpcrel32 : I<0xE8, RawFrm, (ops calltarget:$dst), "call $dst">;
    def CALL32r     : I<0xFF, MRM2r, (ops R32:$dst), "call $dst">;
    def CALL32m     : I<0xFF, MRM2m, (ops i32mem:$dst), "call $dst">;
  }

       
//===----------------------------------------------------------------------===//
//  Miscellaneous Instructions...
//
def LEAVE    : I<0xC9, RawFrm,
                 (ops), "leave">, Imp<[EBP,ESP],[EBP,ESP]>;
def POP32r   : I<0x58, AddRegFrm,
                 (ops R32:$reg), "pop $reg">, Imp<[ESP],[ESP]>;
let isTwoAddress = 1 in                                    // R32 = bswap R32
  def BSWAP32r : I<0xC8, AddRegFrm,
                   (ops R32:$dst, R32:$src), "bswap $dst">, TB;
def XCHG8rr  : I<0x86, MRMDestReg,                    // xchg R8, R8
                 (ops R8:$src1, R8:$src2), "xchg $src1, $src2">;
Loading
Loading full blame...