From: Evan Cheng Date: Wed, 20 Jul 2011 23:34:39 +0000 (+0000) Subject: Sink ARMMCExpr and ARMAddressingModes into MC layer. First step to separate ARM MC... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ee04a6d3a40c3017124e3fd89a0db473a2824498;p=oota-llvm.git Sink ARMMCExpr and ARMAddressingModes into MC layer. First step to separate ARM MC code from target. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135636 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/ARM/ARMAddressingModes.h b/lib/Target/ARM/ARMAddressingModes.h deleted file mode 100644 index 595708fa788..00000000000 --- a/lib/Target/ARM/ARMAddressingModes.h +++ /dev/null @@ -1,595 +0,0 @@ -//===- ARMAddressingModes.h - ARM Addressing Modes --------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the ARM addressing mode implementation stuff. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_ARM_ARMADDRESSINGMODES_H -#define LLVM_TARGET_ARM_ARMADDRESSINGMODES_H - -#include "llvm/CodeGen/SelectionDAGNodes.h" -#include "llvm/Support/MathExtras.h" -#include - -namespace llvm { - -/// ARM_AM - ARM Addressing Mode Stuff -namespace ARM_AM { - enum ShiftOpc { - no_shift = 0, - asr, - lsl, - lsr, - ror, - rrx - }; - - enum AddrOpc { - add = '+', sub = '-' - }; - - static inline const char *getAddrOpcStr(AddrOpc Op) { - return Op == sub ? "-" : ""; - } - - static inline const char *getShiftOpcStr(ShiftOpc Op) { - switch (Op) { - default: assert(0 && "Unknown shift opc!"); - case ARM_AM::asr: return "asr"; - case ARM_AM::lsl: return "lsl"; - case ARM_AM::lsr: return "lsr"; - case ARM_AM::ror: return "ror"; - case ARM_AM::rrx: return "rrx"; - } - } - - static inline unsigned getShiftOpcEncoding(ShiftOpc Op) { - switch (Op) { - default: assert(0 && "Unknown shift opc!"); - case ARM_AM::asr: return 2; - case ARM_AM::lsl: return 0; - case ARM_AM::lsr: return 1; - case ARM_AM::ror: return 3; - } - } - - static inline ShiftOpc getShiftOpcForNode(SDValue N) { - switch (N.getOpcode()) { - default: return ARM_AM::no_shift; - case ISD::SHL: return ARM_AM::lsl; - case ISD::SRL: return ARM_AM::lsr; - case ISD::SRA: return ARM_AM::asr; - case ISD::ROTR: return ARM_AM::ror; - //case ISD::ROTL: // Only if imm -> turn into ROTR. - // Can't handle RRX here, because it would require folding a flag into - // the addressing mode. :( This causes us to miss certain things. - //case ARMISD::RRX: return ARM_AM::rrx; - } - } - - enum AMSubMode { - bad_am_submode = 0, - ia, - ib, - da, - db - }; - - static inline const char *getAMSubModeStr(AMSubMode Mode) { - switch (Mode) { - default: assert(0 && "Unknown addressing sub-mode!"); - case ARM_AM::ia: return "ia"; - case ARM_AM::ib: return "ib"; - case ARM_AM::da: return "da"; - case ARM_AM::db: return "db"; - } - } - - /// rotr32 - Rotate a 32-bit unsigned value right by a specified # bits. - /// - static inline unsigned rotr32(unsigned Val, unsigned Amt) { - assert(Amt < 32 && "Invalid rotate amount"); - return (Val >> Amt) | (Val << ((32-Amt)&31)); - } - - /// rotl32 - Rotate a 32-bit unsigned value left by a specified # bits. - /// - static inline unsigned rotl32(unsigned Val, unsigned Amt) { - assert(Amt < 32 && "Invalid rotate amount"); - return (Val << Amt) | (Val >> ((32-Amt)&31)); - } - - //===--------------------------------------------------------------------===// - // Addressing Mode #1: shift_operand with registers - //===--------------------------------------------------------------------===// - // - // This 'addressing mode' is used for arithmetic instructions. It can - // represent things like: - // reg - // reg [asr|lsl|lsr|ror|rrx] reg - // reg [asr|lsl|lsr|ror|rrx] imm - // - // This is stored three operands [rega, regb, opc]. The first is the base - // reg, the second is the shift amount (or reg0 if not present or imm). The - // third operand encodes the shift opcode and the imm if a reg isn't present. - // - static inline unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm) { - return ShOp | (Imm << 3); - } - static inline unsigned getSORegOffset(unsigned Op) { - return Op >> 3; - } - static inline ShiftOpc getSORegShOp(unsigned Op) { - return (ShiftOpc)(Op & 7); - } - - /// getSOImmValImm - Given an encoded imm field for the reg/imm form, return - /// the 8-bit imm value. - static inline unsigned getSOImmValImm(unsigned Imm) { - return Imm & 0xFF; - } - /// getSOImmValRot - Given an encoded imm field for the reg/imm form, return - /// the rotate amount. - static inline unsigned getSOImmValRot(unsigned Imm) { - return (Imm >> 8) * 2; - } - - /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand, - /// computing the rotate amount to use. If this immediate value cannot be - /// handled with a single shifter-op, determine a good rotate amount that will - /// take a maximal chunk of bits out of the immediate. - static inline unsigned getSOImmValRotate(unsigned Imm) { - // 8-bit (or less) immediates are trivially shifter_operands with a rotate - // of zero. - if ((Imm & ~255U) == 0) return 0; - - // Use CTZ to compute the rotate amount. - unsigned TZ = CountTrailingZeros_32(Imm); - - // Rotate amount must be even. Something like 0x200 must be rotated 8 bits, - // not 9. - unsigned RotAmt = TZ & ~1; - - // If we can handle this spread, return it. - if ((rotr32(Imm, RotAmt) & ~255U) == 0) - return (32-RotAmt)&31; // HW rotates right, not left. - - // For values like 0xF000000F, we should ignore the low 6 bits, then - // retry the hunt. - if (Imm & 63U) { - unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U); - unsigned RotAmt2 = TZ2 & ~1; - if ((rotr32(Imm, RotAmt2) & ~255U) == 0) - return (32-RotAmt2)&31; // HW rotates right, not left. - } - - // Otherwise, we have no way to cover this span of bits with a single - // shifter_op immediate. Return a chunk of bits that will be useful to - // handle. - return (32-RotAmt)&31; // HW rotates right, not left. - } - - /// getSOImmVal - Given a 32-bit immediate, if it is something that can fit - /// into an shifter_operand immediate operand, return the 12-bit encoding for - /// it. If not, return -1. - static inline int getSOImmVal(unsigned Arg) { - // 8-bit (or less) immediates are trivially shifter_operands with a rotate - // of zero. - if ((Arg & ~255U) == 0) return Arg; - - unsigned RotAmt = getSOImmValRotate(Arg); - - // If this cannot be handled with a single shifter_op, bail out. - if (rotr32(~255U, RotAmt) & Arg) - return -1; - - // Encode this correctly. - return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8); - } - - /// isSOImmTwoPartVal - Return true if the specified value can be obtained by - /// or'ing together two SOImmVal's. - static inline bool isSOImmTwoPartVal(unsigned V) { - // If this can be handled with a single shifter_op, bail out. - V = rotr32(~255U, getSOImmValRotate(V)) & V; - if (V == 0) - return false; - - // If this can be handled with two shifter_op's, accept. - V = rotr32(~255U, getSOImmValRotate(V)) & V; - return V == 0; - } - - /// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, - /// return the first chunk of it. - static inline unsigned getSOImmTwoPartFirst(unsigned V) { - return rotr32(255U, getSOImmValRotate(V)) & V; - } - - /// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, - /// return the second chunk of it. - static inline unsigned getSOImmTwoPartSecond(unsigned V) { - // Mask out the first hunk. - V = rotr32(~255U, getSOImmValRotate(V)) & V; - - // Take what's left. - assert(V == (rotr32(255U, getSOImmValRotate(V)) & V)); - return V; - } - - /// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed - /// by a left shift. Returns the shift amount to use. - static inline unsigned getThumbImmValShift(unsigned Imm) { - // 8-bit (or less) immediates are trivially immediate operand with a shift - // of zero. - if ((Imm & ~255U) == 0) return 0; - - // Use CTZ to compute the shift amount. - return CountTrailingZeros_32(Imm); - } - - /// isThumbImmShiftedVal - Return true if the specified value can be obtained - /// by left shifting a 8-bit immediate. - static inline bool isThumbImmShiftedVal(unsigned V) { - // If this can be handled with - V = (~255U << getThumbImmValShift(V)) & V; - return V == 0; - } - - /// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed - /// by a left shift. Returns the shift amount to use. - static inline unsigned getThumbImm16ValShift(unsigned Imm) { - // 16-bit (or less) immediates are trivially immediate operand with a shift - // of zero. - if ((Imm & ~65535U) == 0) return 0; - - // Use CTZ to compute the shift amount. - return CountTrailingZeros_32(Imm); - } - - /// isThumbImm16ShiftedVal - Return true if the specified value can be - /// obtained by left shifting a 16-bit immediate. - static inline bool isThumbImm16ShiftedVal(unsigned V) { - // If this can be handled with - V = (~65535U << getThumbImm16ValShift(V)) & V; - return V == 0; - } - - /// getThumbImmNonShiftedVal - If V is a value that satisfies - /// isThumbImmShiftedVal, return the non-shiftd value. - static inline unsigned getThumbImmNonShiftedVal(unsigned V) { - return V >> getThumbImmValShift(V); - } - - - /// getT2SOImmValSplat - Return the 12-bit encoded representation - /// if the specified value can be obtained by splatting the low 8 bits - /// into every other byte or every byte of a 32-bit value. i.e., - /// 00000000 00000000 00000000 abcdefgh control = 0 - /// 00000000 abcdefgh 00000000 abcdefgh control = 1 - /// abcdefgh 00000000 abcdefgh 00000000 control = 2 - /// abcdefgh abcdefgh abcdefgh abcdefgh control = 3 - /// Return -1 if none of the above apply. - /// See ARM Reference Manual A6.3.2. - static inline int getT2SOImmValSplatVal(unsigned V) { - unsigned u, Vs, Imm; - // control = 0 - if ((V & 0xffffff00) == 0) - return V; - - // If the value is zeroes in the first byte, just shift those off - Vs = ((V & 0xff) == 0) ? V >> 8 : V; - // Any passing value only has 8 bits of payload, splatted across the word - Imm = Vs & 0xff; - // Likewise, any passing values have the payload splatted into the 3rd byte - u = Imm | (Imm << 16); - - // control = 1 or 2 - if (Vs == u) - return (((Vs == V) ? 1 : 2) << 8) | Imm; - - // control = 3 - if (Vs == (u | (u << 8))) - return (3 << 8) | Imm; - - return -1; - } - - /// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the - /// specified value is a rotated 8-bit value. Return -1 if no rotation - /// encoding is possible. - /// See ARM Reference Manual A6.3.2. - static inline int getT2SOImmValRotateVal(unsigned V) { - unsigned RotAmt = CountLeadingZeros_32(V); - if (RotAmt >= 24) - return -1; - - // If 'Arg' can be handled with a single shifter_op return the value. - if ((rotr32(0xff000000U, RotAmt) & V) == V) - return (rotr32(V, 24 - RotAmt) & 0x7f) | ((RotAmt + 8) << 7); - - return -1; - } - - /// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit - /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit - /// encoding for it. If not, return -1. - /// See ARM Reference Manual A6.3.2. - static inline int getT2SOImmVal(unsigned Arg) { - // If 'Arg' is an 8-bit splat, then get the encoded value. - int Splat = getT2SOImmValSplatVal(Arg); - if (Splat != -1) - return Splat; - - // If 'Arg' can be handled with a single shifter_op return the value. - int Rot = getT2SOImmValRotateVal(Arg); - if (Rot != -1) - return Rot; - - return -1; - } - - static inline unsigned getT2SOImmValRotate(unsigned V) { - if ((V & ~255U) == 0) return 0; - // Use CTZ to compute the rotate amount. - unsigned RotAmt = CountTrailingZeros_32(V); - return (32 - RotAmt) & 31; - } - - static inline bool isT2SOImmTwoPartVal (unsigned Imm) { - unsigned V = Imm; - // Passing values can be any combination of splat values and shifter - // values. If this can be handled with a single shifter or splat, bail - // out. Those should be handled directly, not with a two-part val. - if (getT2SOImmValSplatVal(V) != -1) - return false; - V = rotr32 (~255U, getT2SOImmValRotate(V)) & V; - if (V == 0) - return false; - - // If this can be handled as an immediate, accept. - if (getT2SOImmVal(V) != -1) return true; - - // Likewise, try masking out a splat value first. - V = Imm; - if (getT2SOImmValSplatVal(V & 0xff00ff00U) != -1) - V &= ~0xff00ff00U; - else if (getT2SOImmValSplatVal(V & 0x00ff00ffU) != -1) - V &= ~0x00ff00ffU; - // If what's left can be handled as an immediate, accept. - if (getT2SOImmVal(V) != -1) return true; - - // Otherwise, do not accept. - return false; - } - - static inline unsigned getT2SOImmTwoPartFirst(unsigned Imm) { - assert (isT2SOImmTwoPartVal(Imm) && - "Immedate cannot be encoded as two part immediate!"); - // Try a shifter operand as one part - unsigned V = rotr32 (~255, getT2SOImmValRotate(Imm)) & Imm; - // If the rest is encodable as an immediate, then return it. - if (getT2SOImmVal(V) != -1) return V; - - // Try masking out a splat value first. - if (getT2SOImmValSplatVal(Imm & 0xff00ff00U) != -1) - return Imm & 0xff00ff00U; - - // The other splat is all that's left as an option. - assert (getT2SOImmValSplatVal(Imm & 0x00ff00ffU) != -1); - return Imm & 0x00ff00ffU; - } - - static inline unsigned getT2SOImmTwoPartSecond(unsigned Imm) { - // Mask out the first hunk - Imm ^= getT2SOImmTwoPartFirst(Imm); - // Return what's left - assert (getT2SOImmVal(Imm) != -1 && - "Unable to encode second part of T2 two part SO immediate"); - return Imm; - } - - - //===--------------------------------------------------------------------===// - // Addressing Mode #2 - //===--------------------------------------------------------------------===// - // - // This is used for most simple load/store instructions. - // - // addrmode2 := reg +/- reg shop imm - // addrmode2 := reg +/- imm12 - // - // The first operand is always a Reg. The second operand is a reg if in - // reg/reg form, otherwise it's reg#0. The third field encodes the operation - // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The - // fourth operand 16-17 encodes the index mode. - // - // If this addressing mode is a frame index (before prolog/epilog insertion - // and code rewriting), this operand will have the form: FI#, reg0, - // with no shift amount for the frame offset. - // - static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, - unsigned IdxMode = 0) { - assert(Imm12 < (1 << 12) && "Imm too large!"); - bool isSub = Opc == sub; - return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16) ; - } - static inline unsigned getAM2Offset(unsigned AM2Opc) { - return AM2Opc & ((1 << 12)-1); - } - static inline AddrOpc getAM2Op(unsigned AM2Opc) { - return ((AM2Opc >> 12) & 1) ? sub : add; - } - static inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) { - return (ShiftOpc)((AM2Opc >> 13) & 7); - } - static inline unsigned getAM2IdxMode(unsigned AM2Opc) { - return (AM2Opc >> 16); - } - - - //===--------------------------------------------------------------------===// - // Addressing Mode #3 - //===--------------------------------------------------------------------===// - // - // This is used for sign-extending loads, and load/store-pair instructions. - // - // addrmode3 := reg +/- reg - // addrmode3 := reg +/- imm8 - // - // The first operand is always a Reg. The second operand is a reg if in - // reg/reg form, otherwise it's reg#0. The third field encodes the operation - // in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the - // index mode. - - /// getAM3Opc - This function encodes the addrmode3 opc field. - static inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset, - unsigned IdxMode = 0) { - bool isSub = Opc == sub; - return ((int)isSub << 8) | Offset | (IdxMode << 9); - } - static inline unsigned char getAM3Offset(unsigned AM3Opc) { - return AM3Opc & 0xFF; - } - static inline AddrOpc getAM3Op(unsigned AM3Opc) { - return ((AM3Opc >> 8) & 1) ? sub : add; - } - static inline unsigned getAM3IdxMode(unsigned AM3Opc) { - return (AM3Opc >> 9); - } - - //===--------------------------------------------------------------------===// - // Addressing Mode #4 - //===--------------------------------------------------------------------===// - // - // This is used for load / store multiple instructions. - // - // addrmode4 := reg, - // - // The four modes are: - // IA - Increment after - // IB - Increment before - // DA - Decrement after - // DB - Decrement before - // For VFP instructions, only the IA and DB modes are valid. - - static inline AMSubMode getAM4SubMode(unsigned Mode) { - return (AMSubMode)(Mode & 0x7); - } - - static inline unsigned getAM4ModeImm(AMSubMode SubMode) { - return (int)SubMode; - } - - //===--------------------------------------------------------------------===// - // Addressing Mode #5 - //===--------------------------------------------------------------------===// - // - // This is used for coprocessor instructions, such as FP load/stores. - // - // addrmode5 := reg +/- imm8*4 - // - // The first operand is always a Reg. The second operand encodes the - // operation in bit 8 and the immediate in bits 0-7. - - /// getAM5Opc - This function encodes the addrmode5 opc field. - static inline unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset) { - bool isSub = Opc == sub; - return ((int)isSub << 8) | Offset; - } - static inline unsigned char getAM5Offset(unsigned AM5Opc) { - return AM5Opc & 0xFF; - } - static inline AddrOpc getAM5Op(unsigned AM5Opc) { - return ((AM5Opc >> 8) & 1) ? sub : add; - } - - //===--------------------------------------------------------------------===// - // Addressing Mode #6 - //===--------------------------------------------------------------------===// - // - // This is used for NEON load / store instructions. - // - // addrmode6 := reg with optional alignment - // - // This is stored in two operands [regaddr, align]. The first is the - // address register. The second operand is the value of the alignment - // specifier in bytes or zero if no explicit alignment. - // Valid alignments depend on the specific instruction. - - //===--------------------------------------------------------------------===// - // NEON Modified Immediates - //===--------------------------------------------------------------------===// - // - // Several NEON instructions (e.g., VMOV) take a "modified immediate" - // vector operand, where a small immediate encoded in the instruction - // specifies a full NEON vector value. These modified immediates are - // represented here as encoded integers. The low 8 bits hold the immediate - // value; bit 12 holds the "Op" field of the instruction, and bits 11-8 hold - // the "Cmode" field of the instruction. The interfaces below treat the - // Op and Cmode values as a single 5-bit value. - - static inline unsigned createNEONModImm(unsigned OpCmode, unsigned Val) { - return (OpCmode << 8) | Val; - } - static inline unsigned getNEONModImmOpCmode(unsigned ModImm) { - return (ModImm >> 8) & 0x1f; - } - static inline unsigned getNEONModImmVal(unsigned ModImm) { - return ModImm & 0xff; - } - - /// decodeNEONModImm - Decode a NEON modified immediate value into the - /// element value and the element size in bits. (If the element size is - /// smaller than the vector, it is splatted into all the elements.) - static inline uint64_t decodeNEONModImm(unsigned ModImm, unsigned &EltBits) { - unsigned OpCmode = getNEONModImmOpCmode(ModImm); - unsigned Imm8 = getNEONModImmVal(ModImm); - uint64_t Val = 0; - - if (OpCmode == 0xe) { - // 8-bit vector elements - Val = Imm8; - EltBits = 8; - } else if ((OpCmode & 0xc) == 0x8) { - // 16-bit vector elements - unsigned ByteNum = (OpCmode & 0x6) >> 1; - Val = Imm8 << (8 * ByteNum); - EltBits = 16; - } else if ((OpCmode & 0x8) == 0) { - // 32-bit vector elements, zero with one byte set - unsigned ByteNum = (OpCmode & 0x6) >> 1; - Val = Imm8 << (8 * ByteNum); - EltBits = 32; - } else if ((OpCmode & 0xe) == 0xc) { - // 32-bit vector elements, one byte with low bits set - unsigned ByteNum = 1 + (OpCmode & 0x1); - Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum))); - EltBits = 32; - } else if (OpCmode == 0x1e) { - // 64-bit vector elements - for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) { - if ((ModImm >> ByteNum) & 1) - Val |= (uint64_t)0xff << (8 * ByteNum); - } - EltBits = 64; - } else { - assert(false && "Unsupported NEON immediate"); - } - return Val; - } - - AMSubMode getLoadStoreMultipleSubMode(int Opcode); - -} // end namespace ARM_AM -} // end namespace llvm - -#endif - diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp index 5e438a97673..fa6e67807ae 100644 --- a/lib/Target/ARM/ARMAsmBackend.cpp +++ b/lib/Target/ARM/ARMAsmBackend.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMFixupKinds.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCDirectives.h" diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index dbc3ee41f3d..e34f6a047b2 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -15,15 +15,15 @@ #define DEBUG_TYPE "asm-printer" #include "ARM.h" #include "ARMAsmPrinter.h" -#include "ARMAddressingModes.h" #include "ARMBuildAttrs.h" #include "ARMBaseRegisterInfo.h" #include "ARMConstantPoolValue.h" #include "ARMMachineFunctionInfo.h" -#include "ARMMCExpr.h" #include "ARMTargetMachine.h" #include "ARMTargetObjectFile.h" #include "InstPrinter/ARMInstPrinter.h" +#include "MCTargetDesc/ARMAddressingModes.h" +#include "MCTargetDesc/ARMMCExpr.h" #include "llvm/Analysis/DebugInfo.h" #include "llvm/Constants.h" #include "llvm/Module.h" diff --git a/lib/Target/ARM/ARMBaseInfo.h b/lib/Target/ARM/ARMBaseInfo.h index 458f7dd1f78..aa7483cc31c 100644 --- a/lib/Target/ARM/ARMBaseInfo.h +++ b/lib/Target/ARM/ARMBaseInfo.h @@ -191,6 +191,9 @@ inline static unsigned getARMRegisterNumbering(unsigned Reg) { } } +/// ARMII - This namespace holds all of the target specific flags that +/// instruction info tracks. +/// namespace ARMII { /// ARM Index Modes @@ -287,6 +290,142 @@ namespace ARMII { /// call operand. MO_PLT }; + + enum { + //===------------------------------------------------------------------===// + // Instruction Flags. + + //===------------------------------------------------------------------===// + // This four-bit field describes the addressing mode used. + AddrModeMask = 0x1f, // The AddrMode enums are declared in ARMBaseInfo.h + + // IndexMode - Unindex, pre-indexed, or post-indexed are valid for load + // and store ops only. Generic "updating" flag is used for ld/st multiple. + // The index mode enums are declared in ARMBaseInfo.h + IndexModeShift = 5, + IndexModeMask = 3 << IndexModeShift, + + //===------------------------------------------------------------------===// + // Instruction encoding formats. + // + FormShift = 7, + FormMask = 0x3f << FormShift, + + // Pseudo instructions + Pseudo = 0 << FormShift, + + // Multiply instructions + MulFrm = 1 << FormShift, + + // Branch instructions + BrFrm = 2 << FormShift, + BrMiscFrm = 3 << FormShift, + + // Data Processing instructions + DPFrm = 4 << FormShift, + DPSoRegFrm = 5 << FormShift, + + // Load and Store + LdFrm = 6 << FormShift, + StFrm = 7 << FormShift, + LdMiscFrm = 8 << FormShift, + StMiscFrm = 9 << FormShift, + LdStMulFrm = 10 << FormShift, + + LdStExFrm = 11 << FormShift, + + // Miscellaneous arithmetic instructions + ArithMiscFrm = 12 << FormShift, + SatFrm = 13 << FormShift, + + // Extend instructions + ExtFrm = 14 << FormShift, + + // VFP formats + VFPUnaryFrm = 15 << FormShift, + VFPBinaryFrm = 16 << FormShift, + VFPConv1Frm = 17 << FormShift, + VFPConv2Frm = 18 << FormShift, + VFPConv3Frm = 19 << FormShift, + VFPConv4Frm = 20 << FormShift, + VFPConv5Frm = 21 << FormShift, + VFPLdStFrm = 22 << FormShift, + VFPLdStMulFrm = 23 << FormShift, + VFPMiscFrm = 24 << FormShift, + + // Thumb format + ThumbFrm = 25 << FormShift, + + // Miscelleaneous format + MiscFrm = 26 << FormShift, + + // NEON formats + NGetLnFrm = 27 << FormShift, + NSetLnFrm = 28 << FormShift, + NDupFrm = 29 << FormShift, + NLdStFrm = 30 << FormShift, + N1RegModImmFrm= 31 << FormShift, + N2RegFrm = 32 << FormShift, + NVCVTFrm = 33 << FormShift, + NVDupLnFrm = 34 << FormShift, + N2RegVShLFrm = 35 << FormShift, + N2RegVShRFrm = 36 << FormShift, + N3RegFrm = 37 << FormShift, + N3RegVShFrm = 38 << FormShift, + NVExtFrm = 39 << FormShift, + NVMulSLFrm = 40 << FormShift, + NVTBLFrm = 41 << FormShift, + + //===------------------------------------------------------------------===// + // Misc flags. + + // UnaryDP - Indicates this is a unary data processing instruction, i.e. + // it doesn't have a Rn operand. + UnaryDP = 1 << 13, + + // Xform16Bit - Indicates this Thumb2 instruction may be transformed into + // a 16-bit Thumb instruction if certain conditions are met. + Xform16Bit = 1 << 14, + + //===------------------------------------------------------------------===// + // Code domain. + DomainShift = 15, + DomainMask = 7 << DomainShift, + DomainGeneral = 0 << DomainShift, + DomainVFP = 1 << DomainShift, + DomainNEON = 2 << DomainShift, + DomainNEONA8 = 4 << DomainShift, + + //===------------------------------------------------------------------===// + // Field shifts - such shifts are used to set field while generating + // machine instructions. + // + // FIXME: This list will need adjusting/fixing as the MC code emitter + // takes shape and the ARMCodeEmitter.cpp bits go away. + ShiftTypeShift = 4, + + M_BitShift = 5, + ShiftImmShift = 5, + ShiftShift = 7, + N_BitShift = 7, + ImmHiShift = 8, + SoRotImmShift = 8, + RegRsShift = 8, + ExtRotImmShift = 10, + RegRdLoShift = 12, + RegRdShift = 12, + RegRdHiShift = 16, + RegRnShift = 16, + S_BitShift = 20, + W_BitShift = 21, + AM3_I_BitShift = 22, + D_BitShift = 22, + U_BitShift = 23, + P_BitShift = 24, + I_BitShift = 25, + CondShift = 28 + }; + } // end namespace ARMII } // end namespace llvm; diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 649bd7d5ce3..f931a58aed7 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -13,11 +13,11 @@ #include "ARMBaseInstrInfo.h" #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMConstantPoolValue.h" #include "ARMHazardRecognizer.h" #include "ARMMachineFunctionInfo.h" #include "ARMRegisterInfo.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/Constants.h" #include "llvm/Function.h" #include "llvm/GlobalValue.h" @@ -29,6 +29,7 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/BranchProbability.h" #include "llvm/Support/CommandLine.h" diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index 507e8974bf7..9f002b047f5 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -27,146 +27,6 @@ namespace llvm { class ARMSubtarget; class ARMBaseRegisterInfo; -/// ARMII - This namespace holds all of the target specific flags that -/// instruction info tracks. -/// -namespace ARMII { - enum { - //===------------------------------------------------------------------===// - // Instruction Flags. - - //===------------------------------------------------------------------===// - // This four-bit field describes the addressing mode used. - AddrModeMask = 0x1f, // The AddrMode enums are declared in ARMBaseInfo.h - - // IndexMode - Unindex, pre-indexed, or post-indexed are valid for load - // and store ops only. Generic "updating" flag is used for ld/st multiple. - // The index mode enums are declared in ARMBaseInfo.h - IndexModeShift = 5, - IndexModeMask = 3 << IndexModeShift, - - //===------------------------------------------------------------------===// - // Instruction encoding formats. - // - FormShift = 7, - FormMask = 0x3f << FormShift, - - // Pseudo instructions - Pseudo = 0 << FormShift, - - // Multiply instructions - MulFrm = 1 << FormShift, - - // Branch instructions - BrFrm = 2 << FormShift, - BrMiscFrm = 3 << FormShift, - - // Data Processing instructions - DPFrm = 4 << FormShift, - DPSoRegFrm = 5 << FormShift, - - // Load and Store - LdFrm = 6 << FormShift, - StFrm = 7 << FormShift, - LdMiscFrm = 8 << FormShift, - StMiscFrm = 9 << FormShift, - LdStMulFrm = 10 << FormShift, - - LdStExFrm = 11 << FormShift, - - // Miscellaneous arithmetic instructions - ArithMiscFrm = 12 << FormShift, - SatFrm = 13 << FormShift, - - // Extend instructions - ExtFrm = 14 << FormShift, - - // VFP formats - VFPUnaryFrm = 15 << FormShift, - VFPBinaryFrm = 16 << FormShift, - VFPConv1Frm = 17 << FormShift, - VFPConv2Frm = 18 << FormShift, - VFPConv3Frm = 19 << FormShift, - VFPConv4Frm = 20 << FormShift, - VFPConv5Frm = 21 << FormShift, - VFPLdStFrm = 22 << FormShift, - VFPLdStMulFrm = 23 << FormShift, - VFPMiscFrm = 24 << FormShift, - - // Thumb format - ThumbFrm = 25 << FormShift, - - // Miscelleaneous format - MiscFrm = 26 << FormShift, - - // NEON formats - NGetLnFrm = 27 << FormShift, - NSetLnFrm = 28 << FormShift, - NDupFrm = 29 << FormShift, - NLdStFrm = 30 << FormShift, - N1RegModImmFrm= 31 << FormShift, - N2RegFrm = 32 << FormShift, - NVCVTFrm = 33 << FormShift, - NVDupLnFrm = 34 << FormShift, - N2RegVShLFrm = 35 << FormShift, - N2RegVShRFrm = 36 << FormShift, - N3RegFrm = 37 << FormShift, - N3RegVShFrm = 38 << FormShift, - NVExtFrm = 39 << FormShift, - NVMulSLFrm = 40 << FormShift, - NVTBLFrm = 41 << FormShift, - - //===------------------------------------------------------------------===// - // Misc flags. - - // UnaryDP - Indicates this is a unary data processing instruction, i.e. - // it doesn't have a Rn operand. - UnaryDP = 1 << 13, - - // Xform16Bit - Indicates this Thumb2 instruction may be transformed into - // a 16-bit Thumb instruction if certain conditions are met. - Xform16Bit = 1 << 14, - - //===------------------------------------------------------------------===// - // Code domain. - DomainShift = 15, - DomainMask = 7 << DomainShift, - DomainGeneral = 0 << DomainShift, - DomainVFP = 1 << DomainShift, - DomainNEON = 2 << DomainShift, - DomainNEONA8 = 4 << DomainShift, - - //===------------------------------------------------------------------===// - // Field shifts - such shifts are used to set field while generating - // machine instructions. - // - // FIXME: This list will need adjusting/fixing as the MC code emitter - // takes shape and the ARMCodeEmitter.cpp bits go away. - ShiftTypeShift = 4, - - M_BitShift = 5, - ShiftImmShift = 5, - ShiftShift = 7, - N_BitShift = 7, - ImmHiShift = 8, - SoRotImmShift = 8, - RegRsShift = 8, - ExtRotImmShift = 10, - RegRdLoShift = 12, - RegRdShift = 12, - RegRdHiShift = 16, - RegRnShift = 16, - S_BitShift = 20, - W_BitShift = 21, - AM3_I_BitShift = 22, - D_BitShift = 22, - U_BitShift = 23, - P_BitShift = 24, - I_BitShift = 25, - CondShift = 28 - }; -} - class ARMBaseInstrInfo : public ARMGenInstrInfo { const ARMSubtarget &Subtarget; diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index 25130f91236..fe7e45f9143 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -12,13 +12,13 @@ //===----------------------------------------------------------------------===// #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMBaseInstrInfo.h" #include "ARMBaseRegisterInfo.h" #include "ARMFrameLowering.h" #include "ARMInstrInfo.h" #include "ARMMachineFunctionInfo.h" #include "ARMSubtarget.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index d6fca627750..818c5acf9c6 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -14,12 +14,12 @@ #define DEBUG_TYPE "jit" #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMConstantPoolValue.h" #include "ARMInstrInfo.h" #include "ARMRelocations.h" #include "ARMSubtarget.h" #include "ARMTargetMachine.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp index f53714cb8d9..82d404c67d9 100644 --- a/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -15,10 +15,10 @@ #define DEBUG_TYPE "arm-cp-islands" #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMMachineFunctionInfo.h" #include "ARMInstrInfo.h" #include "Thumb2InstrInfo.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp index 94b72fdb9a7..708e88be6fe 100644 --- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -16,11 +16,11 @@ #define DEBUG_TYPE "arm-pseudo" #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMBaseInstrInfo.h" #include "ARMBaseRegisterInfo.h" #include "ARMMachineFunctionInfo.h" #include "ARMRegisterInfo.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" diff --git a/lib/Target/ARM/ARMFastISel.cpp b/lib/Target/ARM/ARMFastISel.cpp index 050b8c1bc4a..5d73bd991e0 100644 --- a/lib/Target/ARM/ARMFastISel.cpp +++ b/lib/Target/ARM/ARMFastISel.cpp @@ -14,13 +14,13 @@ //===----------------------------------------------------------------------===// #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMBaseInstrInfo.h" #include "ARMCallingConv.h" #include "ARMRegisterInfo.h" #include "ARMTargetMachine.h" #include "ARMSubtarget.h" #include "ARMConstantPoolValue.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/CallingConv.h" #include "llvm/DerivedTypes.h" #include "llvm/GlobalVariable.h" diff --git a/lib/Target/ARM/ARMFrameLowering.cpp b/lib/Target/ARM/ARMFrameLowering.cpp index 381b404519e..da61ccbceb9 100644 --- a/lib/Target/ARM/ARMFrameLowering.cpp +++ b/lib/Target/ARM/ARMFrameLowering.cpp @@ -12,10 +12,10 @@ //===----------------------------------------------------------------------===// #include "ARMFrameLowering.h" -#include "ARMAddressingModes.h" #include "ARMBaseInstrInfo.h" #include "ARMBaseRegisterInfo.h" #include "ARMMachineFunctionInfo.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index 2c9481b86c5..92df37fea6b 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -14,8 +14,8 @@ #define DEBUG_TYPE "arm-isel" #include "ARM.h" #include "ARMBaseInstrInfo.h" -#include "ARMAddressingModes.h" #include "ARMTargetMachine.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/CallingConv.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" @@ -373,7 +373,7 @@ bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue N, if (DisableShifterOp) return false; - ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); // Don't match base register only case. That is matched to a separate // lower complexity pattern with explicit register operand. @@ -489,7 +489,8 @@ bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, // Otherwise this is R +/- [possibly shifted] R. ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add; - ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); + ARM_AM::ShiftOpc ShOpcVal = + ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode()); unsigned ShAmt = 0; Base = N.getOperand(0); @@ -515,7 +516,7 @@ bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, // Try matching (R shl C) + (R). if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift && !(Subtarget->isCortexA9() || N.getOperand(0).hasOneUse())) { - ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); + ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode()); if (ShOpcVal != ARM_AM::no_shift) { // Check to see if the RHS of the shift is a constant, if not, we can't // fold it. @@ -630,7 +631,8 @@ AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N, // Otherwise this is R +/- [possibly shifted] R. ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub; - ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); + ARM_AM::ShiftOpc ShOpcVal = + ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode()); unsigned ShAmt = 0; Base = N.getOperand(0); @@ -656,7 +658,7 @@ AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N, // Try matching (R shl C) + (R). if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift && !(Subtarget->isCortexA9() || N.getOperand(0).hasOneUse())) { - ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); + ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode()); if (ShOpcVal != ARM_AM::no_shift) { // Check to see if the RHS of the shift is a constant, if not, we can't // fold it. @@ -701,7 +703,7 @@ bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N, } Offset = N; - ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); unsigned ShAmt = 0; if (ShOpcVal != ARM_AM::no_shift) { // Check to see if the RHS of the shift is a constant, if not, we can't fold @@ -1079,7 +1081,7 @@ bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue N, SDValue &BaseReg, if (DisableShifterOp) return false; - ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); // Don't match base register only case. That is matched to a separate // lower complexity pattern with explicit register operand. @@ -1220,9 +1222,9 @@ bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N, OffReg = N.getOperand(1); // Swap if it is ((R << c) + R). - ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg); + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode()); if (ShOpcVal != ARM_AM::lsl) { - ShOpcVal = ARM_AM::getShiftOpcForNode(Base); + ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode()); if (ShOpcVal == ARM_AM::lsl) std::swap(Base, OffReg); } diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 45fac88b4d2..129b1bcd003 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -14,7 +14,6 @@ #define DEBUG_TYPE "arm-isel" #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMCallingConv.h" #include "ARMConstantPoolValue.h" #include "ARMISelLowering.h" @@ -24,6 +23,7 @@ #include "ARMSubtarget.h" #include "ARMTargetMachine.h" #include "ARMTargetObjectFile.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/CallingConv.h" #include "llvm/Constants.h" #include "llvm/Function.h" @@ -7351,7 +7351,8 @@ static bool getARMIndexedAddressParts(SDNode *Ptr, EVT VT, if (Ptr->getOpcode() == ISD::ADD) { isInc = true; - ARM_AM::ShiftOpc ShOpcVal= ARM_AM::getShiftOpcForNode(Ptr->getOperand(0)); + ARM_AM::ShiftOpc ShOpcVal= + ARM_AM::getShiftOpcForNode(Ptr->getOperand(0).getOpcode()); if (ShOpcVal != ARM_AM::no_shift) { Base = Ptr->getOperand(1); Offset = Ptr->getOperand(0); diff --git a/lib/Target/ARM/ARMInstrInfo.cpp b/lib/Target/ARM/ARMInstrInfo.cpp index adcbf1806fe..4f469bb5b38 100644 --- a/lib/Target/ARM/ARMInstrInfo.cpp +++ b/lib/Target/ARM/ARMInstrInfo.cpp @@ -13,8 +13,8 @@ #include "ARMInstrInfo.h" #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMMachineFunctionInfo.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/LiveVariables.h" #include "llvm/CodeGen/MachineFrameInfo.h" diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp index c6efea1d780..06ee449692a 100644 --- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -14,10 +14,10 @@ #define DEBUG_TYPE "arm-ldst-opt" #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMBaseInstrInfo.h" #include "ARMMachineFunctionInfo.h" #include "ARMRegisterInfo.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" #include "llvm/CodeGen/MachineBasicBlock.h" @@ -26,6 +26,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index 39be3f0e39f..b76ad7b2bee 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -13,16 +13,16 @@ #define DEBUG_TYPE "mccodeemitter" #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMFixupKinds.h" #include "ARMInstrInfo.h" -#include "ARMMCExpr.h" -#include "ARMSubtarget.h" +#include "MCTargetDesc/ARMAddressingModes.h" +#include "MCTargetDesc/ARMMCExpr.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/ADT/APFloat.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/raw_ostream.h" diff --git a/lib/Target/ARM/ARMMCExpr.cpp b/lib/Target/ARM/ARMMCExpr.cpp deleted file mode 100644 index 2727ba8c8aa..00000000000 --- a/lib/Target/ARM/ARMMCExpr.cpp +++ /dev/null @@ -1,73 +0,0 @@ -//===-- ARMMCExpr.cpp - ARM specific MC expression classes ----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "armmcexpr" -#include "ARMMCExpr.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCAssembler.h" -using namespace llvm; - -const ARMMCExpr* -ARMMCExpr::Create(VariantKind Kind, const MCExpr *Expr, - MCContext &Ctx) { - return new (Ctx) ARMMCExpr(Kind, Expr); -} - -void ARMMCExpr::PrintImpl(raw_ostream &OS) const { - switch (Kind) { - default: assert(0 && "Invalid kind!"); - case VK_ARM_HI16: OS << ":upper16:"; break; - case VK_ARM_LO16: OS << ":lower16:"; break; - } - - const MCExpr *Expr = getSubExpr(); - if (Expr->getKind() != MCExpr::SymbolRef) - OS << '('; - Expr->print(OS); - if (Expr->getKind() != MCExpr::SymbolRef) - OS << ')'; -} - -bool -ARMMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, - const MCAsmLayout *Layout) const { - return false; -} - -// FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps -// that method should be made public? -static void AddValueSymbols_(const MCExpr *Value, MCAssembler *Asm) { - switch (Value->getKind()) { - case MCExpr::Target: - assert(0 && "Can't handle nested target expr!"); - break; - - case MCExpr::Constant: - break; - - case MCExpr::Binary: { - const MCBinaryExpr *BE = cast(Value); - AddValueSymbols_(BE->getLHS(), Asm); - AddValueSymbols_(BE->getRHS(), Asm); - break; - } - - case MCExpr::SymbolRef: - Asm->getOrCreateSymbolData(cast(Value)->getSymbol()); - break; - - case MCExpr::Unary: - AddValueSymbols_(cast(Value)->getSubExpr(), Asm); - break; - } -} - -void ARMMCExpr::AddValueSymbols(MCAssembler *Asm) const { - AddValueSymbols_(getSubExpr(), Asm); -} diff --git a/lib/Target/ARM/ARMMCExpr.h b/lib/Target/ARM/ARMMCExpr.h deleted file mode 100644 index 0a2e883deb1..00000000000 --- a/lib/Target/ARM/ARMMCExpr.h +++ /dev/null @@ -1,76 +0,0 @@ -//===-- ARMMCExpr.h - ARM specific MC expression classes ------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef ARMMCEXPR_H -#define ARMMCEXPR_H - -#include "llvm/MC/MCExpr.h" - -namespace llvm { - -class ARMMCExpr : public MCTargetExpr { -public: - enum VariantKind { - VK_ARM_None, - VK_ARM_HI16, // The R_ARM_MOVT_ABS relocation (:upper16: in the .s file) - VK_ARM_LO16 // The R_ARM_MOVW_ABS_NC relocation (:lower16: in the .s file) - }; - -private: - const VariantKind Kind; - const MCExpr *Expr; - - explicit ARMMCExpr(VariantKind _Kind, const MCExpr *_Expr) - : Kind(_Kind), Expr(_Expr) {} - -public: - /// @name Construction - /// @{ - - static const ARMMCExpr *Create(VariantKind Kind, const MCExpr *Expr, - MCContext &Ctx); - - static const ARMMCExpr *CreateUpper16(const MCExpr *Expr, MCContext &Ctx) { - return Create(VK_ARM_HI16, Expr, Ctx); - } - - static const ARMMCExpr *CreateLower16(const MCExpr *Expr, MCContext &Ctx) { - return Create(VK_ARM_LO16, Expr, Ctx); - } - - /// @} - /// @name Accessors - /// @{ - - /// getOpcode - Get the kind of this expression. - VariantKind getKind() const { return Kind; } - - /// getSubExpr - Get the child of this expression. - const MCExpr *getSubExpr() const { return Expr; } - - /// @} - - void PrintImpl(raw_ostream &OS) const; - bool EvaluateAsRelocatableImpl(MCValue &Res, - const MCAsmLayout *Layout) const; - void AddValueSymbols(MCAssembler *) const; - const MCSection *FindAssociatedSection() const { - return getSubExpr()->FindAssociatedSection(); - } - - static bool classof(const MCExpr *E) { - return E->getKind() == MCExpr::Target; - } - - static bool classof(const ARMMCExpr *) { return true; } - -}; -} // end namespace llvm - -#endif diff --git a/lib/Target/ARM/ARMMCInstLower.cpp b/lib/Target/ARM/ARMMCInstLower.cpp index 7411b599f0f..daa126def40 100644 --- a/lib/Target/ARM/ARMMCInstLower.cpp +++ b/lib/Target/ARM/ARMMCInstLower.cpp @@ -14,7 +14,7 @@ #include "ARM.h" #include "ARMAsmPrinter.h" -#include "ARMMCExpr.h" +#include "MCTargetDesc/ARMMCExpr.h" #include "llvm/Constants.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/MC/MCExpr.h" diff --git a/lib/Target/ARM/ARMSelectionDAGInfo.h b/lib/Target/ARM/ARMSelectionDAGInfo.h index ec1bf5ca194..6419a737295 100644 --- a/lib/Target/ARM/ARMSelectionDAGInfo.h +++ b/lib/Target/ARM/ARMSelectionDAGInfo.h @@ -14,10 +14,27 @@ #ifndef ARMSELECTIONDAGINFO_H #define ARMSELECTIONDAGINFO_H +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/Target/TargetSelectionDAGInfo.h" namespace llvm { +namespace ARM_AM { + static inline ShiftOpc getShiftOpcForNode(unsigned Opcode) { + switch (Opcode) { + default: return ARM_AM::no_shift; + case ISD::SHL: return ARM_AM::lsl; + case ISD::SRL: return ARM_AM::lsr; + case ISD::SRA: return ARM_AM::asr; + case ISD::ROTR: return ARM_AM::ror; + //case ISD::ROTL: // Only if imm -> turn into ROTR. + // Can't handle RRX here, because it would require folding a flag into + // the addressing mode. :( This causes us to miss certain things. + //case ARMISD::RRX: return ARM_AM::rrx; + } + } +} // end namespace ARM_AM + class ARMSelectionDAGInfo : public TargetSelectionDAGInfo { /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can /// make the right decision when generating code for different targets. diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 89501dc0888..4e3555ad6cc 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -8,10 +8,10 @@ //===----------------------------------------------------------------------===// #include "ARM.h" -#include "ARMAddressingModes.h" -#include "ARMMCExpr.h" #include "ARMBaseRegisterInfo.h" #include "ARMSubtarget.h" +#include "MCTargetDesc/ARMAddressingModes.h" +#include "MCTargetDesc/ARMMCExpr.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" diff --git a/lib/Target/ARM/CMakeLists.txt b/lib/Target/ARM/CMakeLists.txt index 21608d0b62f..f60e403c84f 100644 --- a/lib/Target/ARM/CMakeLists.txt +++ b/lib/Target/ARM/CMakeLists.txt @@ -34,7 +34,6 @@ add_llvm_target(ARMCodeGen ARMJITInfo.cpp ARMMachObjectWriter.cpp ARMMCCodeEmitter.cpp - ARMMCExpr.cpp ARMLoadStoreOptimizer.cpp ARMMCInstLower.cpp ARMRegisterInfo.cpp diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp index 22aa10c7716..d40a9f7b14b 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp @@ -16,8 +16,10 @@ #define DEBUG_TYPE "arm-disassembler" #include "ARMDisassemblerCore.h" -#include "ARMAddressingModes.h" -#include "ARMMCExpr.h" +#include "MCTargetDesc/ARMAddressingModes.h" +#include "MCTargetDesc/ARMMCExpr.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/APFloat.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index e49825381d2..fc12d46c237 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -14,7 +14,7 @@ #define DEBUG_TYPE "asm-printer" #include "ARMBaseInfo.h" #include "ARMInstPrinter.h" -#include "ARMAddressingModes.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" diff --git a/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h b/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h new file mode 100644 index 00000000000..971b459a5f5 --- /dev/null +++ b/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h @@ -0,0 +1,580 @@ +//===- ARMAddressingModes.h - ARM Addressing Modes --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the ARM addressing mode implementation stuff. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_ARM_ARMADDRESSINGMODES_H +#define LLVM_TARGET_ARM_ARMADDRESSINGMODES_H + +#include "llvm/Support/MathExtras.h" +#include + +namespace llvm { + +/// ARM_AM - ARM Addressing Mode Stuff +namespace ARM_AM { + enum ShiftOpc { + no_shift = 0, + asr, + lsl, + lsr, + ror, + rrx + }; + + enum AddrOpc { + add = '+', sub = '-' + }; + + static inline const char *getAddrOpcStr(AddrOpc Op) { + return Op == sub ? "-" : ""; + } + + static inline const char *getShiftOpcStr(ShiftOpc Op) { + switch (Op) { + default: assert(0 && "Unknown shift opc!"); + case ARM_AM::asr: return "asr"; + case ARM_AM::lsl: return "lsl"; + case ARM_AM::lsr: return "lsr"; + case ARM_AM::ror: return "ror"; + case ARM_AM::rrx: return "rrx"; + } + } + + static inline unsigned getShiftOpcEncoding(ShiftOpc Op) { + switch (Op) { + default: assert(0 && "Unknown shift opc!"); + case ARM_AM::asr: return 2; + case ARM_AM::lsl: return 0; + case ARM_AM::lsr: return 1; + case ARM_AM::ror: return 3; + } + } + + enum AMSubMode { + bad_am_submode = 0, + ia, + ib, + da, + db + }; + + static inline const char *getAMSubModeStr(AMSubMode Mode) { + switch (Mode) { + default: assert(0 && "Unknown addressing sub-mode!"); + case ARM_AM::ia: return "ia"; + case ARM_AM::ib: return "ib"; + case ARM_AM::da: return "da"; + case ARM_AM::db: return "db"; + } + } + + /// rotr32 - Rotate a 32-bit unsigned value right by a specified # bits. + /// + static inline unsigned rotr32(unsigned Val, unsigned Amt) { + assert(Amt < 32 && "Invalid rotate amount"); + return (Val >> Amt) | (Val << ((32-Amt)&31)); + } + + /// rotl32 - Rotate a 32-bit unsigned value left by a specified # bits. + /// + static inline unsigned rotl32(unsigned Val, unsigned Amt) { + assert(Amt < 32 && "Invalid rotate amount"); + return (Val << Amt) | (Val >> ((32-Amt)&31)); + } + + //===--------------------------------------------------------------------===// + // Addressing Mode #1: shift_operand with registers + //===--------------------------------------------------------------------===// + // + // This 'addressing mode' is used for arithmetic instructions. It can + // represent things like: + // reg + // reg [asr|lsl|lsr|ror|rrx] reg + // reg [asr|lsl|lsr|ror|rrx] imm + // + // This is stored three operands [rega, regb, opc]. The first is the base + // reg, the second is the shift amount (or reg0 if not present or imm). The + // third operand encodes the shift opcode and the imm if a reg isn't present. + // + static inline unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm) { + return ShOp | (Imm << 3); + } + static inline unsigned getSORegOffset(unsigned Op) { + return Op >> 3; + } + static inline ShiftOpc getSORegShOp(unsigned Op) { + return (ShiftOpc)(Op & 7); + } + + /// getSOImmValImm - Given an encoded imm field for the reg/imm form, return + /// the 8-bit imm value. + static inline unsigned getSOImmValImm(unsigned Imm) { + return Imm & 0xFF; + } + /// getSOImmValRot - Given an encoded imm field for the reg/imm form, return + /// the rotate amount. + static inline unsigned getSOImmValRot(unsigned Imm) { + return (Imm >> 8) * 2; + } + + /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand, + /// computing the rotate amount to use. If this immediate value cannot be + /// handled with a single shifter-op, determine a good rotate amount that will + /// take a maximal chunk of bits out of the immediate. + static inline unsigned getSOImmValRotate(unsigned Imm) { + // 8-bit (or less) immediates are trivially shifter_operands with a rotate + // of zero. + if ((Imm & ~255U) == 0) return 0; + + // Use CTZ to compute the rotate amount. + unsigned TZ = CountTrailingZeros_32(Imm); + + // Rotate amount must be even. Something like 0x200 must be rotated 8 bits, + // not 9. + unsigned RotAmt = TZ & ~1; + + // If we can handle this spread, return it. + if ((rotr32(Imm, RotAmt) & ~255U) == 0) + return (32-RotAmt)&31; // HW rotates right, not left. + + // For values like 0xF000000F, we should ignore the low 6 bits, then + // retry the hunt. + if (Imm & 63U) { + unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U); + unsigned RotAmt2 = TZ2 & ~1; + if ((rotr32(Imm, RotAmt2) & ~255U) == 0) + return (32-RotAmt2)&31; // HW rotates right, not left. + } + + // Otherwise, we have no way to cover this span of bits with a single + // shifter_op immediate. Return a chunk of bits that will be useful to + // handle. + return (32-RotAmt)&31; // HW rotates right, not left. + } + + /// getSOImmVal - Given a 32-bit immediate, if it is something that can fit + /// into an shifter_operand immediate operand, return the 12-bit encoding for + /// it. If not, return -1. + static inline int getSOImmVal(unsigned Arg) { + // 8-bit (or less) immediates are trivially shifter_operands with a rotate + // of zero. + if ((Arg & ~255U) == 0) return Arg; + + unsigned RotAmt = getSOImmValRotate(Arg); + + // If this cannot be handled with a single shifter_op, bail out. + if (rotr32(~255U, RotAmt) & Arg) + return -1; + + // Encode this correctly. + return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8); + } + + /// isSOImmTwoPartVal - Return true if the specified value can be obtained by + /// or'ing together two SOImmVal's. + static inline bool isSOImmTwoPartVal(unsigned V) { + // If this can be handled with a single shifter_op, bail out. + V = rotr32(~255U, getSOImmValRotate(V)) & V; + if (V == 0) + return false; + + // If this can be handled with two shifter_op's, accept. + V = rotr32(~255U, getSOImmValRotate(V)) & V; + return V == 0; + } + + /// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, + /// return the first chunk of it. + static inline unsigned getSOImmTwoPartFirst(unsigned V) { + return rotr32(255U, getSOImmValRotate(V)) & V; + } + + /// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, + /// return the second chunk of it. + static inline unsigned getSOImmTwoPartSecond(unsigned V) { + // Mask out the first hunk. + V = rotr32(~255U, getSOImmValRotate(V)) & V; + + // Take what's left. + assert(V == (rotr32(255U, getSOImmValRotate(V)) & V)); + return V; + } + + /// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed + /// by a left shift. Returns the shift amount to use. + static inline unsigned getThumbImmValShift(unsigned Imm) { + // 8-bit (or less) immediates are trivially immediate operand with a shift + // of zero. + if ((Imm & ~255U) == 0) return 0; + + // Use CTZ to compute the shift amount. + return CountTrailingZeros_32(Imm); + } + + /// isThumbImmShiftedVal - Return true if the specified value can be obtained + /// by left shifting a 8-bit immediate. + static inline bool isThumbImmShiftedVal(unsigned V) { + // If this can be handled with + V = (~255U << getThumbImmValShift(V)) & V; + return V == 0; + } + + /// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed + /// by a left shift. Returns the shift amount to use. + static inline unsigned getThumbImm16ValShift(unsigned Imm) { + // 16-bit (or less) immediates are trivially immediate operand with a shift + // of zero. + if ((Imm & ~65535U) == 0) return 0; + + // Use CTZ to compute the shift amount. + return CountTrailingZeros_32(Imm); + } + + /// isThumbImm16ShiftedVal - Return true if the specified value can be + /// obtained by left shifting a 16-bit immediate. + static inline bool isThumbImm16ShiftedVal(unsigned V) { + // If this can be handled with + V = (~65535U << getThumbImm16ValShift(V)) & V; + return V == 0; + } + + /// getThumbImmNonShiftedVal - If V is a value that satisfies + /// isThumbImmShiftedVal, return the non-shiftd value. + static inline unsigned getThumbImmNonShiftedVal(unsigned V) { + return V >> getThumbImmValShift(V); + } + + + /// getT2SOImmValSplat - Return the 12-bit encoded representation + /// if the specified value can be obtained by splatting the low 8 bits + /// into every other byte or every byte of a 32-bit value. i.e., + /// 00000000 00000000 00000000 abcdefgh control = 0 + /// 00000000 abcdefgh 00000000 abcdefgh control = 1 + /// abcdefgh 00000000 abcdefgh 00000000 control = 2 + /// abcdefgh abcdefgh abcdefgh abcdefgh control = 3 + /// Return -1 if none of the above apply. + /// See ARM Reference Manual A6.3.2. + static inline int getT2SOImmValSplatVal(unsigned V) { + unsigned u, Vs, Imm; + // control = 0 + if ((V & 0xffffff00) == 0) + return V; + + // If the value is zeroes in the first byte, just shift those off + Vs = ((V & 0xff) == 0) ? V >> 8 : V; + // Any passing value only has 8 bits of payload, splatted across the word + Imm = Vs & 0xff; + // Likewise, any passing values have the payload splatted into the 3rd byte + u = Imm | (Imm << 16); + + // control = 1 or 2 + if (Vs == u) + return (((Vs == V) ? 1 : 2) << 8) | Imm; + + // control = 3 + if (Vs == (u | (u << 8))) + return (3 << 8) | Imm; + + return -1; + } + + /// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the + /// specified value is a rotated 8-bit value. Return -1 if no rotation + /// encoding is possible. + /// See ARM Reference Manual A6.3.2. + static inline int getT2SOImmValRotateVal(unsigned V) { + unsigned RotAmt = CountLeadingZeros_32(V); + if (RotAmt >= 24) + return -1; + + // If 'Arg' can be handled with a single shifter_op return the value. + if ((rotr32(0xff000000U, RotAmt) & V) == V) + return (rotr32(V, 24 - RotAmt) & 0x7f) | ((RotAmt + 8) << 7); + + return -1; + } + + /// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit + /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit + /// encoding for it. If not, return -1. + /// See ARM Reference Manual A6.3.2. + static inline int getT2SOImmVal(unsigned Arg) { + // If 'Arg' is an 8-bit splat, then get the encoded value. + int Splat = getT2SOImmValSplatVal(Arg); + if (Splat != -1) + return Splat; + + // If 'Arg' can be handled with a single shifter_op return the value. + int Rot = getT2SOImmValRotateVal(Arg); + if (Rot != -1) + return Rot; + + return -1; + } + + static inline unsigned getT2SOImmValRotate(unsigned V) { + if ((V & ~255U) == 0) return 0; + // Use CTZ to compute the rotate amount. + unsigned RotAmt = CountTrailingZeros_32(V); + return (32 - RotAmt) & 31; + } + + static inline bool isT2SOImmTwoPartVal (unsigned Imm) { + unsigned V = Imm; + // Passing values can be any combination of splat values and shifter + // values. If this can be handled with a single shifter or splat, bail + // out. Those should be handled directly, not with a two-part val. + if (getT2SOImmValSplatVal(V) != -1) + return false; + V = rotr32 (~255U, getT2SOImmValRotate(V)) & V; + if (V == 0) + return false; + + // If this can be handled as an immediate, accept. + if (getT2SOImmVal(V) != -1) return true; + + // Likewise, try masking out a splat value first. + V = Imm; + if (getT2SOImmValSplatVal(V & 0xff00ff00U) != -1) + V &= ~0xff00ff00U; + else if (getT2SOImmValSplatVal(V & 0x00ff00ffU) != -1) + V &= ~0x00ff00ffU; + // If what's left can be handled as an immediate, accept. + if (getT2SOImmVal(V) != -1) return true; + + // Otherwise, do not accept. + return false; + } + + static inline unsigned getT2SOImmTwoPartFirst(unsigned Imm) { + assert (isT2SOImmTwoPartVal(Imm) && + "Immedate cannot be encoded as two part immediate!"); + // Try a shifter operand as one part + unsigned V = rotr32 (~255, getT2SOImmValRotate(Imm)) & Imm; + // If the rest is encodable as an immediate, then return it. + if (getT2SOImmVal(V) != -1) return V; + + // Try masking out a splat value first. + if (getT2SOImmValSplatVal(Imm & 0xff00ff00U) != -1) + return Imm & 0xff00ff00U; + + // The other splat is all that's left as an option. + assert (getT2SOImmValSplatVal(Imm & 0x00ff00ffU) != -1); + return Imm & 0x00ff00ffU; + } + + static inline unsigned getT2SOImmTwoPartSecond(unsigned Imm) { + // Mask out the first hunk + Imm ^= getT2SOImmTwoPartFirst(Imm); + // Return what's left + assert (getT2SOImmVal(Imm) != -1 && + "Unable to encode second part of T2 two part SO immediate"); + return Imm; + } + + + //===--------------------------------------------------------------------===// + // Addressing Mode #2 + //===--------------------------------------------------------------------===// + // + // This is used for most simple load/store instructions. + // + // addrmode2 := reg +/- reg shop imm + // addrmode2 := reg +/- imm12 + // + // The first operand is always a Reg. The second operand is a reg if in + // reg/reg form, otherwise it's reg#0. The third field encodes the operation + // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The + // fourth operand 16-17 encodes the index mode. + // + // If this addressing mode is a frame index (before prolog/epilog insertion + // and code rewriting), this operand will have the form: FI#, reg0, + // with no shift amount for the frame offset. + // + static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, + unsigned IdxMode = 0) { + assert(Imm12 < (1 << 12) && "Imm too large!"); + bool isSub = Opc == sub; + return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16) ; + } + static inline unsigned getAM2Offset(unsigned AM2Opc) { + return AM2Opc & ((1 << 12)-1); + } + static inline AddrOpc getAM2Op(unsigned AM2Opc) { + return ((AM2Opc >> 12) & 1) ? sub : add; + } + static inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) { + return (ShiftOpc)((AM2Opc >> 13) & 7); + } + static inline unsigned getAM2IdxMode(unsigned AM2Opc) { + return (AM2Opc >> 16); + } + + + //===--------------------------------------------------------------------===// + // Addressing Mode #3 + //===--------------------------------------------------------------------===// + // + // This is used for sign-extending loads, and load/store-pair instructions. + // + // addrmode3 := reg +/- reg + // addrmode3 := reg +/- imm8 + // + // The first operand is always a Reg. The second operand is a reg if in + // reg/reg form, otherwise it's reg#0. The third field encodes the operation + // in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the + // index mode. + + /// getAM3Opc - This function encodes the addrmode3 opc field. + static inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset, + unsigned IdxMode = 0) { + bool isSub = Opc == sub; + return ((int)isSub << 8) | Offset | (IdxMode << 9); + } + static inline unsigned char getAM3Offset(unsigned AM3Opc) { + return AM3Opc & 0xFF; + } + static inline AddrOpc getAM3Op(unsigned AM3Opc) { + return ((AM3Opc >> 8) & 1) ? sub : add; + } + static inline unsigned getAM3IdxMode(unsigned AM3Opc) { + return (AM3Opc >> 9); + } + + //===--------------------------------------------------------------------===// + // Addressing Mode #4 + //===--------------------------------------------------------------------===// + // + // This is used for load / store multiple instructions. + // + // addrmode4 := reg, + // + // The four modes are: + // IA - Increment after + // IB - Increment before + // DA - Decrement after + // DB - Decrement before + // For VFP instructions, only the IA and DB modes are valid. + + static inline AMSubMode getAM4SubMode(unsigned Mode) { + return (AMSubMode)(Mode & 0x7); + } + + static inline unsigned getAM4ModeImm(AMSubMode SubMode) { + return (int)SubMode; + } + + //===--------------------------------------------------------------------===// + // Addressing Mode #5 + //===--------------------------------------------------------------------===// + // + // This is used for coprocessor instructions, such as FP load/stores. + // + // addrmode5 := reg +/- imm8*4 + // + // The first operand is always a Reg. The second operand encodes the + // operation in bit 8 and the immediate in bits 0-7. + + /// getAM5Opc - This function encodes the addrmode5 opc field. + static inline unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset) { + bool isSub = Opc == sub; + return ((int)isSub << 8) | Offset; + } + static inline unsigned char getAM5Offset(unsigned AM5Opc) { + return AM5Opc & 0xFF; + } + static inline AddrOpc getAM5Op(unsigned AM5Opc) { + return ((AM5Opc >> 8) & 1) ? sub : add; + } + + //===--------------------------------------------------------------------===// + // Addressing Mode #6 + //===--------------------------------------------------------------------===// + // + // This is used for NEON load / store instructions. + // + // addrmode6 := reg with optional alignment + // + // This is stored in two operands [regaddr, align]. The first is the + // address register. The second operand is the value of the alignment + // specifier in bytes or zero if no explicit alignment. + // Valid alignments depend on the specific instruction. + + //===--------------------------------------------------------------------===// + // NEON Modified Immediates + //===--------------------------------------------------------------------===// + // + // Several NEON instructions (e.g., VMOV) take a "modified immediate" + // vector operand, where a small immediate encoded in the instruction + // specifies a full NEON vector value. These modified immediates are + // represented here as encoded integers. The low 8 bits hold the immediate + // value; bit 12 holds the "Op" field of the instruction, and bits 11-8 hold + // the "Cmode" field of the instruction. The interfaces below treat the + // Op and Cmode values as a single 5-bit value. + + static inline unsigned createNEONModImm(unsigned OpCmode, unsigned Val) { + return (OpCmode << 8) | Val; + } + static inline unsigned getNEONModImmOpCmode(unsigned ModImm) { + return (ModImm >> 8) & 0x1f; + } + static inline unsigned getNEONModImmVal(unsigned ModImm) { + return ModImm & 0xff; + } + + /// decodeNEONModImm - Decode a NEON modified immediate value into the + /// element value and the element size in bits. (If the element size is + /// smaller than the vector, it is splatted into all the elements.) + static inline uint64_t decodeNEONModImm(unsigned ModImm, unsigned &EltBits) { + unsigned OpCmode = getNEONModImmOpCmode(ModImm); + unsigned Imm8 = getNEONModImmVal(ModImm); + uint64_t Val = 0; + + if (OpCmode == 0xe) { + // 8-bit vector elements + Val = Imm8; + EltBits = 8; + } else if ((OpCmode & 0xc) == 0x8) { + // 16-bit vector elements + unsigned ByteNum = (OpCmode & 0x6) >> 1; + Val = Imm8 << (8 * ByteNum); + EltBits = 16; + } else if ((OpCmode & 0x8) == 0) { + // 32-bit vector elements, zero with one byte set + unsigned ByteNum = (OpCmode & 0x6) >> 1; + Val = Imm8 << (8 * ByteNum); + EltBits = 32; + } else if ((OpCmode & 0xe) == 0xc) { + // 32-bit vector elements, one byte with low bits set + unsigned ByteNum = 1 + (OpCmode & 0x1); + Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum))); + EltBits = 32; + } else if (OpCmode == 0x1e) { + // 64-bit vector elements + for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) { + if ((ModImm >> ByteNum) & 1) + Val |= (uint64_t)0xff << (8 * ByteNum); + } + EltBits = 64; + } else { + assert(false && "Unsupported NEON immediate"); + } + return Val; + } + + AMSubMode getLoadStoreMultipleSubMode(int Opcode); + +} // end namespace ARM_AM +} // end namespace llvm + +#endif + diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCExpr.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.cpp new file mode 100644 index 00000000000..2727ba8c8aa --- /dev/null +++ b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.cpp @@ -0,0 +1,73 @@ +//===-- ARMMCExpr.cpp - ARM specific MC expression classes ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "armmcexpr" +#include "ARMMCExpr.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCAssembler.h" +using namespace llvm; + +const ARMMCExpr* +ARMMCExpr::Create(VariantKind Kind, const MCExpr *Expr, + MCContext &Ctx) { + return new (Ctx) ARMMCExpr(Kind, Expr); +} + +void ARMMCExpr::PrintImpl(raw_ostream &OS) const { + switch (Kind) { + default: assert(0 && "Invalid kind!"); + case VK_ARM_HI16: OS << ":upper16:"; break; + case VK_ARM_LO16: OS << ":lower16:"; break; + } + + const MCExpr *Expr = getSubExpr(); + if (Expr->getKind() != MCExpr::SymbolRef) + OS << '('; + Expr->print(OS); + if (Expr->getKind() != MCExpr::SymbolRef) + OS << ')'; +} + +bool +ARMMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout) const { + return false; +} + +// FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps +// that method should be made public? +static void AddValueSymbols_(const MCExpr *Value, MCAssembler *Asm) { + switch (Value->getKind()) { + case MCExpr::Target: + assert(0 && "Can't handle nested target expr!"); + break; + + case MCExpr::Constant: + break; + + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast(Value); + AddValueSymbols_(BE->getLHS(), Asm); + AddValueSymbols_(BE->getRHS(), Asm); + break; + } + + case MCExpr::SymbolRef: + Asm->getOrCreateSymbolData(cast(Value)->getSymbol()); + break; + + case MCExpr::Unary: + AddValueSymbols_(cast(Value)->getSubExpr(), Asm); + break; + } +} + +void ARMMCExpr::AddValueSymbols(MCAssembler *Asm) const { + AddValueSymbols_(getSubExpr(), Asm); +} diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCExpr.h b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.h new file mode 100644 index 00000000000..0a2e883deb1 --- /dev/null +++ b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.h @@ -0,0 +1,76 @@ +//===-- ARMMCExpr.h - ARM specific MC expression classes ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMMCEXPR_H +#define ARMMCEXPR_H + +#include "llvm/MC/MCExpr.h" + +namespace llvm { + +class ARMMCExpr : public MCTargetExpr { +public: + enum VariantKind { + VK_ARM_None, + VK_ARM_HI16, // The R_ARM_MOVT_ABS relocation (:upper16: in the .s file) + VK_ARM_LO16 // The R_ARM_MOVW_ABS_NC relocation (:lower16: in the .s file) + }; + +private: + const VariantKind Kind; + const MCExpr *Expr; + + explicit ARMMCExpr(VariantKind _Kind, const MCExpr *_Expr) + : Kind(_Kind), Expr(_Expr) {} + +public: + /// @name Construction + /// @{ + + static const ARMMCExpr *Create(VariantKind Kind, const MCExpr *Expr, + MCContext &Ctx); + + static const ARMMCExpr *CreateUpper16(const MCExpr *Expr, MCContext &Ctx) { + return Create(VK_ARM_HI16, Expr, Ctx); + } + + static const ARMMCExpr *CreateLower16(const MCExpr *Expr, MCContext &Ctx) { + return Create(VK_ARM_LO16, Expr, Ctx); + } + + /// @} + /// @name Accessors + /// @{ + + /// getOpcode - Get the kind of this expression. + VariantKind getKind() const { return Kind; } + + /// getSubExpr - Get the child of this expression. + const MCExpr *getSubExpr() const { return Expr; } + + /// @} + + void PrintImpl(raw_ostream &OS) const; + bool EvaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout) const; + void AddValueSymbols(MCAssembler *) const; + const MCSection *FindAssociatedSection() const { + return getSubExpr()->FindAssociatedSection(); + } + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Target; + } + + static bool classof(const ARMMCExpr *) { return true; } + +}; +} // end namespace llvm + +#endif diff --git a/lib/Target/ARM/MCTargetDesc/CMakeLists.txt b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt index 68daf42c919..c5321f90e2a 100644 --- a/lib/Target/ARM/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt @@ -1,6 +1,7 @@ add_llvm_library(LLVMARMDesc ARMMCTargetDesc.cpp ARMMCAsmInfo.cpp + ARMMCExpr.cpp ) # Hack: we need to include 'main' target directory to grab private headers diff --git a/lib/Target/ARM/Thumb1RegisterInfo.cpp b/lib/Target/ARM/Thumb1RegisterInfo.cpp index 61156e2d50c..cb7d5b6c7d2 100644 --- a/lib/Target/ARM/Thumb1RegisterInfo.cpp +++ b/lib/Target/ARM/Thumb1RegisterInfo.cpp @@ -13,12 +13,12 @@ //===----------------------------------------------------------------------===// #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMBaseInstrInfo.h" #include "ARMMachineFunctionInfo.h" #include "ARMSubtarget.h" #include "Thumb1InstrInfo.h" #include "Thumb1RegisterInfo.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" diff --git a/lib/Target/ARM/Thumb2InstrInfo.cpp b/lib/Target/ARM/Thumb2InstrInfo.cpp index 51b56aaeb00..33fa5213be7 100644 --- a/lib/Target/ARM/Thumb2InstrInfo.cpp +++ b/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -14,9 +14,9 @@ #include "Thumb2InstrInfo.h" #include "ARM.h" #include "ARMConstantPoolValue.h" -#include "ARMAddressingModes.h" #include "ARMMachineFunctionInfo.h" #include "Thumb2InstrInfo.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineMemOperand.h" diff --git a/lib/Target/ARM/Thumb2SizeReduction.cpp b/lib/Target/ARM/Thumb2SizeReduction.cpp index c741a6e8a5b..60900810e5a 100644 --- a/lib/Target/ARM/Thumb2SizeReduction.cpp +++ b/lib/Target/ARM/Thumb2SizeReduction.cpp @@ -9,11 +9,11 @@ #define DEBUG_TYPE "t2-reduce-size" #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMBaseRegisterInfo.h" #include "ARMBaseInstrInfo.h" #include "ARMSubtarget.h" #include "Thumb2InstrInfo.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFunctionPass.h"