| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- // This test describes how we eventually want to describe instructions in
- // the target independent code generators.
- // RUN: llvm-tblgen %s
- // XFAIL: vg_leak
- // Target indep stuff.
- class Instruction { // Would have other stuff eventually
- bit isTwoAddress = 0;
- string AssemblyString;
- }
- class RegisterClass;
- class RTLNode;
- def ops; // Marker for operand list.
- // Various expressions used in RTL descriptions.
- def imm8 : RTLNode;
- def imm32 : RTLNode;
- def addr : RTLNode;
- def set : RTLNode;
- def signext : RTLNode;
- def zeroext : RTLNode;
- def plus : RTLNode;
- def and : RTLNode;
- def xor : RTLNode;
- def shl : RTLNode;
- def load : RTLNode;
- def store : RTLNode;
- def unspec : RTLNode;
- // Start of X86 specific stuff.
- def R8 : RegisterClass;
- def R16 : RegisterClass;
- def R32 : RegisterClass;
- def CL; // As are currently defined
- def AL;
- def AX;
- def EDX;
- 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>;
- class Inst<dag opnds, string asmstr, bits<8> opcode,
- Format f, list<dag> rtl> : Instruction {
- dag Operands = opnds;
- string AssemblyString = asmstr;
- bits<8> Opcode = opcode;
- Format Format = f;
- list<dag> RTL = rtl;
- }
- // Start of instruction definitions, the real point of this file.
- //
- // Note that these patterns show a couple of important things:
- // 1. The order and contents of the operands of the MachineInstr are
- // described here. Eventually we can do away with this when everything
- // is generated from the description.
- // 2. The asm string is captured here, which makes it possible to get rid of
- // a ton of hacks in the various printers and a bunch of flags.
- // 3. Target specific properties (e.g. Format) can still be captured as
- // needed.
- // 4. We capture the behavior of the instruction with a simplified RTL-like
- // expression.
- // 5. The use/def properties for each operand are automatically inferred from
- // the pattern.
- // 6. Address expressions should become first-class entities.
- // Simple copy instruction.
- def MOV8rr : Inst<(ops R8:$dst, R8:$src),
- "mov $dst, $src", 0x88, MRMDestReg,
- [(set R8:$dst, R8:$src)]>;
- // Simple immediate initialization.
- def MOV8ri : Inst<(ops R8:$dst, imm8:$src),
- "mov $dst, $src", 0xB0, AddRegFrm,
- [(set R8:$dst, imm8:$src)]>;
- // Two address instructions are described as three-addr instructions, with
- // the special target-independent isTwoAddress flag set. The asm pattern
- // should not refer to the $src1, this would be enforced by the
- // TargetInstrInfo tablegen backend.
- let isTwoAddress = 1 in
- def AND8rr : Inst<(ops R8:$dst, R8:$src1, R8:$src2),
- "and $dst, $src2", 0x20, MRMDestReg,
- [(set R8:$dst, (and R8:$src1, R8:$src2))]>;
- // Instructions that have explicit uses/defs make them explicit in the RTL.
- // Instructions that need extra stuff emitted in the assembly can, trivially.
- let isTwoAddress = 1 in
- def SHL32rCL : Inst<(ops R32:$dst, R32:$src),
- "shl $dst, CL", 0xD2, MRM4r,
- [(set R32:$dst, (shl R32:$src, CL))]>;
- // The RTL list is a list, allowing complex instructions to be defined easily.
- // Temporary 'internal' registers can be used to break instructions apart.
- let isTwoAddress = 1 in
- def XOR32mi : Inst<(ops addr:$addr, imm32:$imm),
- "xor $dst, $src2", 0x81, MRM6m,
- [(set R32:$tmp1, (load addr:$addr)),
- (set R32:$tmp2, (xor R32:$tmp1, imm32:$imm)),
- (store addr:$addr, R32:$tmp2)]>;
- // Alternatively, if each tmporary register is only used once, the instruction
- // can just be described in nested form. This would be the canonical
- // representation the target generator would convert the above into. Pick your
- // favorite indentation scheme.
- let isTwoAddress = 1 in
- def AND32mr : Inst<(ops addr:$addr, R32:$src),
- "xor $dst, $src2", 0x81, MRM6m,
- [(store addr:$addr,
- (and
- (load addr:$addr),
- R32:$src)
- )
- ]>;
- // Describing complex instructions is not too hard! Note how implicit uses/defs
- // become explicit here.
- def CBW : Inst<(ops),
- "cbw", 0x98, RawFrm,
- [(set AX, (signext AL))]>;
- // Noop, does nothing.
- def NOOP : Inst<(ops), "nop", 0x90, RawFrm, []>;
- // Instructions that don't expect optimization can use unspec.
- def IN8rr : Inst<(ops), "in AL, EDX", 0xEC, RawFrm,
- [(set AL, (unspec EDX))]>;
|