diff --git a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp index 65d9228ad94..9cbece93a3c 100644 --- a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -68,7 +68,8 @@ class SparcAsmParser : public MCTargetAsmParser { StringRef Name); OperandMatchResultTy - parseSparcAsmOperand(SparcOperand *&Operand, bool isCall = false); + parseSparcAsmOperand(SparcOperand *&Operand, bool isCall = false, + bool createTokenForFCC = true); OperandMatchResultTy parseBranchModifiers(SmallVectorImpl &Operands); @@ -631,7 +632,10 @@ parseOperand(SmallVectorImpl &Operands, } SparcOperand *Op = 0; - ResTy = parseSparcAsmOperand(Op, (Mnemonic == "call")); + + bool createTokenForFCC = !(Mnemonic == "fcmps" || Mnemonic == "fcmpd" + || Mnemonic == "fcmpq"); + ResTy = parseSparcAsmOperand(Op, (Mnemonic == "call"), createTokenForFCC); if (ResTy != MatchOperand_Success || !Op) return MatchOperand_ParseFail; @@ -642,7 +646,8 @@ parseOperand(SmallVectorImpl &Operands, } SparcAsmParser::OperandMatchResultTy -SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op, bool isCall) +SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op, bool isCall, + bool createTokenForFCC) { SMLoc S = Parser.getTok().getLoc(); @@ -677,9 +682,11 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op, bool isCall) break; case Sparc::FCC0: - assert(name == "fcc0" && "Cannot handle %fcc other than %fcc0 yet"); - Op = SparcOperand::CreateToken("%fcc0", S); - break; + if (createTokenForFCC) { + assert(name == "fcc0" && "Cannot handle %fcc other than %fcc0 yet"); + Op = SparcOperand::CreateToken("%fcc0", S); + break; + } } break; } @@ -783,7 +790,7 @@ bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, && !name.substr(3).getAsInteger(10, intVal) && intVal < 4) { // FIXME: check 64bit and handle %fcc1 - %fcc3 - RegNo = Sparc::FCC0; + RegNo = Sparc::FCC0 + intVal; RegKind = SparcOperand::rk_CCReg; return true; } diff --git a/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp index e8314f23842..e01196cbccb 100644 --- a/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +++ b/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp @@ -113,6 +113,9 @@ static const unsigned QFPRegDecoderTable[] = { SP::Q6, SP::Q14, ~0U, ~0U, SP::Q7, SP::Q15, ~0U, ~0U } ; +static const unsigned FCCRegDecoderTable[] = { + SP::FCC0, SP::FCC1, SP::FCC2, SP::FCC3 }; + static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, @@ -174,6 +177,16 @@ static DecodeStatus DecodeQFPRegsRegisterClass(MCInst &Inst, return MCDisassembler::Success; } +static DecodeStatus DecodeFCCRegsRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo > 3) + return MCDisassembler::Fail; + Inst.addOperand(MCOperand::CreateReg(FCCRegDecoderTable[RegNo])); + return MCDisassembler::Success; +} + + static DecodeStatus DecodeLoadInt(MCInst &Inst, unsigned insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeLoadFP(MCInst &Inst, unsigned insn, uint64_t Address, diff --git a/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp b/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp index f887b945a36..66b4b519f7e 100644 --- a/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +++ b/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp @@ -32,6 +32,10 @@ namespace Sparc { #define PRINT_ALIAS_INSTR #include "SparcGenAsmWriter.inc" +bool SparcInstPrinter::isV9() const { + return (STI.getFeatureBits() & Sparc::FeatureV9) != 0; +} + void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { OS << '%' << StringRef(getRegisterName(RegNo)).lower(); @@ -65,6 +69,26 @@ bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, raw_ostream &O) return true; } } + case SP::V9FCMPS: + case SP::V9FCMPD: + case SP::V9FCMPQ: { + if (isV9() + || (MI->getNumOperands() != 3) + || (!MI->getOperand(0).isReg()) + || (MI->getOperand(0).getReg() != SP::FCC0)) + return false; + // if V8, skip printing %fcc0. + switch(MI->getOpcode()) { + default: + case SP::V9FCMPS: O << "\tfcmps "; break; + case SP::V9FCMPD: O << "\tfcmpd "; break; + case SP::V9FCMPQ: O << "\tfcmpq "; break; + } + printOperand(MI, 1, O); + O << ", "; + printOperand(MI, 2, O); + return true; + } } } diff --git a/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h b/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h index 63ed41a4c12..45ee6c027f9 100644 --- a/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h +++ b/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h @@ -15,21 +15,25 @@ #define SparcINSTPRINTER_H #include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCSubtargetInfo.h" namespace llvm { class MCOperand; class SparcInstPrinter : public MCInstPrinter { + const MCSubtargetInfo &STI; public: SparcInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, - const MCRegisterInfo &MRI) - : MCInstPrinter(MAI, MII, MRI) {} + const MCRegisterInfo &MRI, + const MCSubtargetInfo &sti) + : MCInstPrinter(MAI, MII, MRI), STI(sti) {} virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot); bool printSparcAliasInstr(const MCInst *MI, raw_ostream &OS); + bool isV9() const; // Autogenerated by tblgen. void printInstruction(const MCInst *MI, raw_ostream &O); diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp index 1961254e48a..c69af56bb00 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp @@ -153,7 +153,7 @@ static MCInstPrinter *createSparcMCInstPrinter(const Target &T, const MCInstrInfo &MII, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI) { - return new SparcInstPrinter(MAI, MII, MRI); + return new SparcInstPrinter(MAI, MII, MRI, STI); } extern "C" void LLVMInitializeSparcTargetMC() { diff --git a/lib/Target/Sparc/SparcInstrAliases.td b/lib/Target/Sparc/SparcInstrAliases.td index 2fc6b7120f8..4d7acd5d4e5 100644 --- a/lib/Target/Sparc/SparcInstrAliases.td +++ b/lib/Target/Sparc/SparcInstrAliases.td @@ -228,3 +228,9 @@ def : MnemonicAlias<"addccc", "addxcc">, Requires<[HasV9]>; def : MnemonicAlias<"subc", "subx">, Requires<[HasV9]>; def : MnemonicAlias<"subccc", "subxcc">, Requires<[HasV9]>; + + +def : InstAlias<"fcmps $rs1, $rs2", (V9FCMPS FCC0, FPRegs:$rs1, FPRegs:$rs2)>; +def : InstAlias<"fcmpd $rs1, $rs2", (V9FCMPD FCC0, DFPRegs:$rs1, DFPRegs:$rs2)>; +def : InstAlias<"fcmpq $rs1, $rs2", (V9FCMPQ FCC0, QFPRegs:$rs1, QFPRegs:$rs2)>, + Requires<[HasHardQuad]>; diff --git a/lib/Target/Sparc/SparcInstrFormats.td b/lib/Target/Sparc/SparcInstrFormats.td index 761ff15d04f..39ff325abcc 100644 --- a/lib/Target/Sparc/SparcInstrFormats.td +++ b/lib/Target/Sparc/SparcInstrFormats.td @@ -153,7 +153,6 @@ class F3_3c opVal, bits<6> op3val, bits<9> opfval, dag outs, dag ins, let op = opVal; let op3 = op3val; - let rd = 0; let Inst{13-5} = opfval; // fp opcode let Inst{4-0} = rs2; diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td index 690a5bf8184..638e9d53582 100644 --- a/lib/Target/Sparc/SparcInstrInfo.td +++ b/lib/Target/Sparc/SparcInstrInfo.td @@ -864,7 +864,7 @@ def FDIVQ : F3_3<2, 0b110100, 0b001001111, // This behavior is modeled with a forced noop after the instruction in // DelaySlotFiller. -let Defs = [FCC0] in { +let Defs = [FCC0], rd = 0, isCodeGenOnly = 1 in { def FCMPS : F3_3c<2, 0b110101, 0b001010001, (outs), (ins FPRegs:$rs1, FPRegs:$rs2), "fcmps $rs1, $rs2", @@ -1014,6 +1014,19 @@ let Predicates = [HasV9] in { Requires<[HasHardQuad]>; } +// Floating-point compare instruction with %fcc0-%fcc1 +def V9FCMPS : F3_3c<2, 0b110101, 0b001010001, + (outs FCCRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2), + "fcmps $rd, $rs1, $rs2", []>; +def V9FCMPD : F3_3c<2, 0b110101, 0b001010010, + (outs FCCRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), + "fcmpd $rd, $rs1, $rs2", []>; +def V9FCMPQ : F3_3c<2, 0b110101, 0b001010011, + (outs FCCRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2), + "fcmpq $rd, $rs1, $rs2", []>, + Requires<[HasHardQuad]>; + + // POPCrr - This does a ctpop of a 64-bit register. As such, we have to clear // the top 32-bits before using it. To do this clearing, we use a SRLri X,0. let rs1 = 0 in diff --git a/test/MC/Disassembler/Sparc/sparc-fp.txt b/test/MC/Disassembler/Sparc/sparc-fp.txt index b8a5017383d..b279da86a52 100644 --- a/test/MC/Disassembler/Sparc/sparc-fp.txt +++ b/test/MC/Disassembler/Sparc/sparc-fp.txt @@ -120,13 +120,13 @@ # CHECK: fdivq %f0, %f4, %f8 0x91 0xa0 0x09 0xe4 -# CHECK: fcmps %f0, %f4 +# CHECK: fcmps %fcc0, %f0, %f4 0x81 0xa8 0x0a 0x24 -# CHECK: fcmpd %f0, %f4 +# CHECK: fcmpd %fcc0, %f0, %f4 0x81 0xa8 0x0a 0x44 -# CHECK: fcmpq %f0, %f4 +# CHECK: fcmpq %fcc0, %f0, %f4 0x81 0xa8 0x0a 0x64 # CHECK: fxtos %f0, %f4 diff --git a/test/MC/Sparc/sparc-fp-instructions.s b/test/MC/Sparc/sparc-fp-instructions.s index 7435a0a5e83..88a055d7fcc 100644 --- a/test/MC/Sparc/sparc-fp-instructions.s +++ b/test/MC/Sparc/sparc-fp-instructions.s @@ -96,13 +96,20 @@ fdivd %f0, %f4, %f8 fdivq %f0, %f4, %f8 - ! CHECK: fcmps %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x24] - ! CHECK: fcmpd %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x44] - ! CHECK: fcmpq %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x64] + ! CHECK: fcmps %fcc0, %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x24] + ! CHECK: fcmpd %fcc0, %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x44] + ! CHECK: fcmpq %fcc0, %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x64] fcmps %f0, %f4 fcmpd %f0, %f4 fcmpq %f0, %f4 + ! CHECK: fcmps %fcc2, %f0, %f4 ! encoding: [0x85,0xa8,0x0a,0x24] + ! CHECK: fcmpd %fcc2, %f0, %f4 ! encoding: [0x85,0xa8,0x0a,0x44] + ! CHECK: fcmpq %fcc2, %f0, %f4 ! encoding: [0x85,0xa8,0x0a,0x64] + fcmps %fcc2, %f0, %f4 + fcmpd %fcc2, %f0, %f4 + fcmpq %fcc2, %f0, %f4 + ! CHECK: fxtos %f0, %f4 ! encoding: [0x89,0xa0,0x10,0x80] ! CHECK: fxtod %f0, %f4 ! encoding: [0x89,0xa0,0x11,0x00] ! CHECK: fxtoq %f0, %f4 ! encoding: [0x89,0xa0,0x11,0x80] diff --git a/test/MC/Sparc/sparcv8-instructions.s b/test/MC/Sparc/sparcv8-instructions.s new file mode 100644 index 00000000000..27b32976f37 --- /dev/null +++ b/test/MC/Sparc/sparcv8-instructions.s @@ -0,0 +1,8 @@ +! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s + + ! CHECK: fcmps %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x24] + ! CHECK: fcmpd %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x44] + ! CHECK: fcmpq %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x64] + fcmps %f0, %f4 + fcmpd %f0, %f4 + fcmpq %f0, %f4