summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVenkatraman Govindaraju <venkatra@cs.wisc.edu>2014-03-02 03:39:39 +0000
committerVenkatraman Govindaraju <venkatra@cs.wisc.edu>2014-03-02 03:39:39 +0000
commitafad335cae8d1c811e2d4a9de843a36d36b4e8c5 (patch)
tree3635fcf8152acb693c12bfadec4981b48f9ac5d2
parent80949c599fb8b2c5d14c517d2ef94ad974989a37 (diff)
[Sparc] Add support for parsing fcmp with %fcc registers.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202610 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/Sparc/AsmParser/SparcAsmParser.cpp21
-rw-r--r--lib/Target/Sparc/Disassembler/SparcDisassembler.cpp13
-rw-r--r--lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp24
-rw-r--r--lib/Target/Sparc/InstPrinter/SparcInstPrinter.h8
-rw-r--r--lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp2
-rw-r--r--lib/Target/Sparc/SparcInstrAliases.td6
-rw-r--r--lib/Target/Sparc/SparcInstrFormats.td1
-rw-r--r--lib/Target/Sparc/SparcInstrInfo.td15
-rw-r--r--test/MC/Disassembler/Sparc/sparc-fp.txt6
-rw-r--r--test/MC/Sparc/sparc-fp-instructions.s13
-rw-r--r--test/MC/Sparc/sparcv8-instructions.s8
11 files changed, 99 insertions, 18 deletions
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<MCParsedAsmOperand*> &Operands);
@@ -631,7 +632,10 @@ parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<bits<2> 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