diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/ARM/ARMFastISel.cpp | 12 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.cpp | 48 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.h | 6 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrVFP.td | 56 | ||||
-rw-r--r-- | lib/Target/ARM/Disassembler/ARMDisassembler.cpp | 27 | ||||
-rw-r--r-- | lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 35 | ||||
-rw-r--r-- | lib/Target/ARM/InstPrinter/ARMInstPrinter.h | 3 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h | 86 |
8 files changed, 128 insertions, 145 deletions
diff --git a/lib/Target/ARM/ARMFastISel.cpp b/lib/Target/ARM/ARMFastISel.cpp index 08770442b2..190563a571 100644 --- a/lib/Target/ARM/ARMFastISel.cpp +++ b/lib/Target/ARM/ARMFastISel.cpp @@ -502,11 +502,19 @@ unsigned ARMFastISel::ARMMaterializeFP(const ConstantFP *CFP, EVT VT) { // This checks to see if we can use VFP3 instructions to materialize // a constant, otherwise we have to go through the constant pool. if (TLI.isFPImmLegal(Val, VT)) { - unsigned Opc = is64bit ? ARM::FCONSTD : ARM::FCONSTS; + int Imm; + unsigned Opc; + if (is64bit) { + Imm = ARM_AM::getFP64Imm(Val); + Opc = ARM::FCONSTD; + } else { + Imm = ARM_AM::getFP32Imm(Val); + Opc = ARM::FCONSTS; + } unsigned DestReg = createResultReg(TLI.getRegClassFor(VT)); AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc), DestReg) - .addFPImm(CFP)); + .addImm(Imm)); return DestReg; } diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 54f8aaa6d3..2edecb261a 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -8176,50 +8176,6 @@ ARMTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { return false; } -int ARM::getVFPf32Imm(const APFloat &FPImm) { - APInt Imm = FPImm.bitcastToAPInt(); - uint32_t Sign = Imm.lshr(31).getZExtValue() & 1; - int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127; // -126 to 127 - int64_t Mantissa = Imm.getZExtValue() & 0x7fffff; // 23 bits - - // We can handle 4 bits of mantissa. - // mantissa = (16+UInt(e:f:g:h))/16. - if (Mantissa & 0x7ffff) - return -1; - Mantissa >>= 19; - if ((Mantissa & 0xf) != Mantissa) - return -1; - - // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 - if (Exp < -3 || Exp > 4) - return -1; - Exp = ((Exp+3) & 0x7) ^ 4; - - return ((int)Sign << 7) | (Exp << 4) | Mantissa; -} - -int ARM::getVFPf64Imm(const APFloat &FPImm) { - APInt Imm = FPImm.bitcastToAPInt(); - uint64_t Sign = Imm.lshr(63).getZExtValue() & 1; - int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023; // -1022 to 1023 - uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffLL; - - // We can handle 4 bits of mantissa. - // mantissa = (16+UInt(e:f:g:h))/16. - if (Mantissa & 0xffffffffffffLL) - return -1; - Mantissa >>= 48; - if ((Mantissa & 0xf) != Mantissa) - return -1; - - // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 - if (Exp < -3 || Exp > 4) - return -1; - Exp = ((Exp+3) & 0x7) ^ 4; - - return ((int)Sign << 7) | (Exp << 4) | Mantissa; -} - bool ARM::isBitFieldInvertedMask(unsigned v) { if (v == 0xffffffff) return 0; @@ -8242,9 +8198,9 @@ bool ARMTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { if (!Subtarget->hasVFP3()) return false; if (VT == MVT::f32) - return ARM::getVFPf32Imm(Imm) != -1; + return ARM_AM::getFP32Imm(Imm) != -1; if (VT == MVT::f64) - return ARM::getVFPf64Imm(Imm) != -1; + return ARM_AM::getFP64Imm(Imm) != -1; return false; } diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index b06e6594af..3b1023ee3a 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -227,12 +227,6 @@ namespace llvm { /// Define some predicates that are used for node matching. namespace ARM { - /// getVFPf32Imm / getVFPf64Imm - If the given fp immediate can be - /// materialized with a VMOV.f32 / VMOV.f64 (i.e. fconsts / fconstd) - /// instruction, returns its 8-bit integer representation. Otherwise, - /// returns -1. - int getVFPf32Imm(const APFloat &FPImm); - int getVFPf64Imm(const APFloat &FPImm); bool isBitFieldInvertedMask(unsigned v); } diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index d6628bb695..76b333e782 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -33,18 +33,24 @@ def arm_fmdrr : SDNode<"ARMISD::VMOVDRR", SDT_VMOVDRR>; def vfp_f32imm : Operand<f32>, PatLeaf<(f32 fpimm), [{ - return ARM::getVFPf32Imm(N->getValueAPF()) != -1; - }]> { - let PrintMethod = "printVFPf32ImmOperand"; - let DecoderMethod = "DecodeVFPfpImm"; + return ARM_AM::getFP32Imm(N->getValueAPF()) != -1; + }], SDNodeXForm<fpimm, [{ + APFloat InVal = N->getValueAPF(); + uint32_t enc = ARM_AM::getFP32Imm(InVal); + return CurDAG->getTargetConstant(enc, MVT::i32); + }]>> { + let PrintMethod = "printFPImmOperand"; } def vfp_f64imm : Operand<f64>, PatLeaf<(f64 fpimm), [{ - return ARM::getVFPf64Imm(N->getValueAPF()) != -1; - }]> { - let PrintMethod = "printVFPf64ImmOperand"; - let DecoderMethod = "DecodeVFPfpImm"; + return ARM_AM::getFP64Imm(N->getValueAPF()) != -1; + }], SDNodeXForm<fpimm, [{ + APFloat InVal = N->getValueAPF(); + uint32_t enc = ARM_AM::getFP64Imm(InVal); + return CurDAG->getTargetConstant(enc, MVT::i32); + }]>> { + let PrintMethod = "printFPImmOperand"; } @@ -1110,45 +1116,35 @@ def FCONSTD : VFPAI<(outs DPR:$Dd), (ins vfp_f64imm:$imm), VFPMiscFrm, IIC_fpUNA64, "vmov", ".f64\t$Dd, $imm", [(set DPR:$Dd, vfp_f64imm:$imm)]>, Requires<[HasVFP3]> { - // Instruction operands. - bits<5> Dd; - bits<32> imm; - - // Encode instruction operands. - let Inst{15-12} = Dd{3-0}; - let Inst{22} = Dd{4}; - let Inst{19} = imm{31}; // The immediate is handled as a float. - let Inst{18-16} = imm{25-23}; - let Inst{3-0} = imm{22-19}; + bits<5> Dd; + bits<8> imm; - // Encode remaining instruction bits. let Inst{27-23} = 0b11101; + let Inst{22} = Dd{4}; let Inst{21-20} = 0b11; + let Inst{19-16} = imm{7-4}; + let Inst{15-12} = Dd{3-0}; let Inst{11-9} = 0b101; let Inst{8} = 1; // Double precision. let Inst{7-4} = 0b0000; + let Inst{3-0} = imm{3-0}; } def FCONSTS : VFPAI<(outs SPR:$Sd), (ins vfp_f32imm:$imm), VFPMiscFrm, IIC_fpUNA32, "vmov", ".f32\t$Sd, $imm", [(set SPR:$Sd, vfp_f32imm:$imm)]>, Requires<[HasVFP3]> { - // Instruction operands. - bits<5> Sd; - bits<32> imm; - - // Encode instruction operands. - let Inst{15-12} = Sd{4-1}; - let Inst{22} = Sd{0}; - let Inst{19} = imm{31}; // The immediate is handled as a float. - let Inst{18-16} = imm{25-23}; - let Inst{3-0} = imm{22-19}; + bits<5> Sd; + bits<8> imm; - // Encode remaining instruction bits. let Inst{27-23} = 0b11101; + let Inst{22} = Sd{0}; let Inst{21-20} = 0b11; + let Inst{19-16} = imm{7-4}; + let Inst{15-12} = Sd{4-1}; let Inst{11-9} = 0b101; let Inst{8} = 0; // Single precision. let Inst{7-4} = 0b0000; + let Inst{3-0} = imm{3-0}; } } diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index c8d1321351..3d33ce2c2c 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -204,8 +204,6 @@ static DecodeStatus DecodeShiftRight64Imm(llvm::MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder); static DecodeStatus DecodeTBLInstruction(llvm::MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); -static DecodeStatus DecodeVFPfpImm(llvm::MCInst &Inst, unsigned Val, - uint64_t Address, const void *Decoder); static DecodeStatus DecodePostIdxReg(llvm::MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeCoprocessor(llvm::MCInst &Inst, unsigned Insn, @@ -2524,31 +2522,6 @@ static DecodeStatus DecodeTBLInstruction(llvm::MCInst &Inst, unsigned Insn, return S; } -static DecodeStatus DecodeVFPfpImm(llvm::MCInst &Inst, unsigned Val, - uint64_t Address, const void *Decoder) { - // The immediate needs to be a fully instantiated float. However, the - // auto-generated decoder is only able to fill in some of the bits - // necessary. For instance, the 'b' bit is replicated multiple times, - // and is even present in inverted form in one bit. We do a little - // binary parsing here to fill in those missing bits, and then - // reinterpret it all as a float. - union { - uint32_t integer; - float fp; - } fp_conv; - - fp_conv.integer = Val; - uint32_t b = fieldFromInstruction32(Val, 25, 1); - fp_conv.integer |= b << 26; - fp_conv.integer |= b << 27; - fp_conv.integer |= b << 28; - fp_conv.integer |= b << 29; - fp_conv.integer |= (~b & 0x1) << 30; - - Inst.addOperand(MCOperand::CreateFPImm(fp_conv.fp)); - return MCDisassembler::Success; -} - static DecodeStatus DecodeThumbAddSpecialReg(llvm::MCInst &Inst, uint16_t Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index bcf91c73ed..f3e29f80b8 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -934,39 +934,10 @@ void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI, O << "]"; } -void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum, - raw_ostream &O) { - const MCOperand &MO = MI->getOperand(OpNum); - O << '#'; - if (MO.isFPImm()) { - O << (float)MO.getFPImm(); - } else { - union { - uint32_t I; - float F; - } FPUnion; - - FPUnion.I = MO.getImm(); - O << FPUnion.F; - } -} - -void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum, - raw_ostream &O) { +void ARMInstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { const MCOperand &MO = MI->getOperand(OpNum); - O << '#'; - if (MO.isFPImm()) { - O << MO.getFPImm(); - } else { - // We expect the binary encoding of a floating point number here. - union { - uint64_t I; - double D; - } FPUnion; - - FPUnion.I = MO.getImm(); - O << FPUnion.D; - } + O << '#' << ARM_AM::getFPImmFloat(MO.getImm()); } void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum, diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h index 67484cc711..83a55ade19 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h @@ -120,8 +120,7 @@ public: void printNoHashImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printPImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printCImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O); - void printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); - void printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printFPImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printNEONModImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printImmPlusOneOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printRotImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); diff --git a/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h b/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h index fe467f0a85..982826a5f0 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h +++ b/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h @@ -14,6 +14,8 @@ #ifndef LLVM_TARGET_ARM_ARMADDRESSINGMODES_H #define LLVM_TARGET_ARM_ARMADDRESSINGMODES_H +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" #include "llvm/Support/MathExtras.h" #include <cassert> @@ -574,6 +576,90 @@ namespace ARM_AM { AMSubMode getLoadStoreMultipleSubMode(int Opcode); + //===--------------------------------------------------------------------===// + // Floating-point Immediates + // + static inline float getFPImmFloat(unsigned Imm) { + // We expect an 8-bit binary encoding of a floating-point number here. + union { + uint32_t I; + float F; + } FPUnion; + + uint8_t Sign = (Imm >> 7) & 0x1; + uint8_t Exp = (Imm >> 4) & 0x7; + uint8_t Mantissa = Imm & 0xf; + + // 8-bit FP iEEEE Float Encoding + // abcd efgh aBbbbbbc defgh000 00000000 00000000 + // + // where B = NOT(b); + + FPUnion.I = 0; + FPUnion.I |= Sign << 31; + FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30; + FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25; + FPUnion.I |= (Exp & 0x3) << 23; + FPUnion.I |= Mantissa << 19; + return FPUnion.F; + } + + /// getFP32Imm - Return an 8-bit floating-point version of the 32-bit + /// floating-point value. If the value cannot be represented as an 8-bit + /// floating-point value, then return -1. + static inline int getFP32Imm(const APInt &Imm) { + uint32_t Sign = Imm.lshr(31).getZExtValue() & 1; + int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127; // -126 to 127 + int64_t Mantissa = Imm.getZExtValue() & 0x7fffff; // 23 bits + + // We can handle 4 bits of mantissa. + // mantissa = (16+UInt(e:f:g:h))/16. + if (Mantissa & 0x7ffff) + return -1; + Mantissa >>= 19; + if ((Mantissa & 0xf) != Mantissa) + return -1; + + // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 + if (Exp < -3 || Exp > 4) + return -1; + Exp = ((Exp+3) & 0x7) ^ 4; + + return ((int)Sign << 7) | (Exp << 4) | Mantissa; + } + + static inline int getFP32Imm(const APFloat &FPImm) { + return getFP32Imm(FPImm.bitcastToAPInt()); + } + + /// getFP64Imm - Return an 8-bit floating-point version of the 64-bit + /// floating-point value. If the value cannot be represented as an 8-bit + /// floating-point value, then return -1. + static inline int getFP64Imm(const APInt &Imm) { + uint64_t Sign = Imm.lshr(63).getZExtValue() & 1; + int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023; // -1022 to 1023 + uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffULL; + + // We can handle 4 bits of mantissa. + // mantissa = (16+UInt(e:f:g:h))/16. + if (Mantissa & 0xffffffffffffULL) + return -1; + Mantissa >>= 48; + if ((Mantissa & 0xf) != Mantissa) + return -1; + + // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 + if (Exp < -3 || Exp > 4) + return -1; + Exp = ((Exp+3) & 0x7) ^ 4; + + return ((int)Sign << 7) | (Exp << 4) | Mantissa; + } + + static inline int getFP64Imm(const APFloat &FPImm) { + return getFP64Imm(FPImm.bitcastToAPInt()); + } + } // end namespace ARM_AM } // end namespace llvm |