forked from OSchip/llvm-project
[Sparc] Add support for parsing fcmp with %fcc registers.
llvm-svn: 202610
This commit is contained in:
parent
871171a25b
commit
81aae57282
|
@ -68,7 +68,8 @@ class SparcAsmParser : public MCTargetAsmParser {
|
||||||
StringRef Name);
|
StringRef Name);
|
||||||
|
|
||||||
OperandMatchResultTy
|
OperandMatchResultTy
|
||||||
parseSparcAsmOperand(SparcOperand *&Operand, bool isCall = false);
|
parseSparcAsmOperand(SparcOperand *&Operand, bool isCall = false,
|
||||||
|
bool createTokenForFCC = true);
|
||||||
|
|
||||||
OperandMatchResultTy
|
OperandMatchResultTy
|
||||||
parseBranchModifiers(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
parseBranchModifiers(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||||
|
@ -631,7 +632,10 @@ parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||||
}
|
}
|
||||||
|
|
||||||
SparcOperand *Op = 0;
|
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)
|
if (ResTy != MatchOperand_Success || !Op)
|
||||||
return MatchOperand_ParseFail;
|
return MatchOperand_ParseFail;
|
||||||
|
|
||||||
|
@ -642,7 +646,8 @@ parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||||
}
|
}
|
||||||
|
|
||||||
SparcAsmParser::OperandMatchResultTy
|
SparcAsmParser::OperandMatchResultTy
|
||||||
SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op, bool isCall)
|
SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op, bool isCall,
|
||||||
|
bool createTokenForFCC)
|
||||||
{
|
{
|
||||||
|
|
||||||
SMLoc S = Parser.getTok().getLoc();
|
SMLoc S = Parser.getTok().getLoc();
|
||||||
|
@ -677,9 +682,11 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op, bool isCall)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Sparc::FCC0:
|
case Sparc::FCC0:
|
||||||
assert(name == "fcc0" && "Cannot handle %fcc other than %fcc0 yet");
|
if (createTokenForFCC) {
|
||||||
Op = SparcOperand::CreateToken("%fcc0", S);
|
assert(name == "fcc0" && "Cannot handle %fcc other than %fcc0 yet");
|
||||||
break;
|
Op = SparcOperand::CreateToken("%fcc0", S);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -783,7 +790,7 @@ bool SparcAsmParser::matchRegisterName(const AsmToken &Tok,
|
||||||
&& !name.substr(3).getAsInteger(10, intVal)
|
&& !name.substr(3).getAsInteger(10, intVal)
|
||||||
&& intVal < 4) {
|
&& intVal < 4) {
|
||||||
// FIXME: check 64bit and handle %fcc1 - %fcc3
|
// FIXME: check 64bit and handle %fcc1 - %fcc3
|
||||||
RegNo = Sparc::FCC0;
|
RegNo = Sparc::FCC0 + intVal;
|
||||||
RegKind = SparcOperand::rk_CCReg;
|
RegKind = SparcOperand::rk_CCReg;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,6 +113,9 @@ static const unsigned QFPRegDecoderTable[] = {
|
||||||
SP::Q6, SP::Q14, ~0U, ~0U,
|
SP::Q6, SP::Q14, ~0U, ~0U,
|
||||||
SP::Q7, SP::Q15, ~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,
|
static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst,
|
||||||
unsigned RegNo,
|
unsigned RegNo,
|
||||||
uint64_t Address,
|
uint64_t Address,
|
||||||
|
@ -174,6 +177,16 @@ static DecodeStatus DecodeQFPRegsRegisterClass(MCInst &Inst,
|
||||||
return MCDisassembler::Success;
|
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,
|
static DecodeStatus DecodeLoadInt(MCInst &Inst, unsigned insn, uint64_t Address,
|
||||||
const void *Decoder);
|
const void *Decoder);
|
||||||
static DecodeStatus DecodeLoadFP(MCInst &Inst, unsigned insn, uint64_t Address,
|
static DecodeStatus DecodeLoadFP(MCInst &Inst, unsigned insn, uint64_t Address,
|
||||||
|
|
|
@ -32,6 +32,10 @@ namespace Sparc {
|
||||||
#define PRINT_ALIAS_INSTR
|
#define PRINT_ALIAS_INSTR
|
||||||
#include "SparcGenAsmWriter.inc"
|
#include "SparcGenAsmWriter.inc"
|
||||||
|
|
||||||
|
bool SparcInstPrinter::isV9() const {
|
||||||
|
return (STI.getFeatureBits() & Sparc::FeatureV9) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
|
void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
|
||||||
{
|
{
|
||||||
OS << '%' << StringRef(getRegisterName(RegNo)).lower();
|
OS << '%' << StringRef(getRegisterName(RegNo)).lower();
|
||||||
|
@ -65,6 +69,26 @@ bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, raw_ostream &O)
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,21 +15,25 @@
|
||||||
#define SparcINSTPRINTER_H
|
#define SparcINSTPRINTER_H
|
||||||
|
|
||||||
#include "llvm/MC/MCInstPrinter.h"
|
#include "llvm/MC/MCInstPrinter.h"
|
||||||
|
#include "llvm/MC/MCSubtargetInfo.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class MCOperand;
|
class MCOperand;
|
||||||
|
|
||||||
class SparcInstPrinter : public MCInstPrinter {
|
class SparcInstPrinter : public MCInstPrinter {
|
||||||
|
const MCSubtargetInfo &STI;
|
||||||
public:
|
public:
|
||||||
SparcInstPrinter(const MCAsmInfo &MAI,
|
SparcInstPrinter(const MCAsmInfo &MAI,
|
||||||
const MCInstrInfo &MII,
|
const MCInstrInfo &MII,
|
||||||
const MCRegisterInfo &MRI)
|
const MCRegisterInfo &MRI,
|
||||||
: MCInstPrinter(MAI, MII, MRI) {}
|
const MCSubtargetInfo &sti)
|
||||||
|
: MCInstPrinter(MAI, MII, MRI), STI(sti) {}
|
||||||
|
|
||||||
virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
|
virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
|
||||||
virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
|
virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
|
||||||
bool printSparcAliasInstr(const MCInst *MI, raw_ostream &OS);
|
bool printSparcAliasInstr(const MCInst *MI, raw_ostream &OS);
|
||||||
|
bool isV9() const;
|
||||||
|
|
||||||
// Autogenerated by tblgen.
|
// Autogenerated by tblgen.
|
||||||
void printInstruction(const MCInst *MI, raw_ostream &O);
|
void printInstruction(const MCInst *MI, raw_ostream &O);
|
||||||
|
|
|
@ -153,7 +153,7 @@ static MCInstPrinter *createSparcMCInstPrinter(const Target &T,
|
||||||
const MCInstrInfo &MII,
|
const MCInstrInfo &MII,
|
||||||
const MCRegisterInfo &MRI,
|
const MCRegisterInfo &MRI,
|
||||||
const MCSubtargetInfo &STI) {
|
const MCSubtargetInfo &STI) {
|
||||||
return new SparcInstPrinter(MAI, MII, MRI);
|
return new SparcInstPrinter(MAI, MII, MRI, STI);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void LLVMInitializeSparcTargetMC() {
|
extern "C" void LLVMInitializeSparcTargetMC() {
|
||||||
|
|
|
@ -228,3 +228,9 @@ def : MnemonicAlias<"addccc", "addxcc">, Requires<[HasV9]>;
|
||||||
|
|
||||||
def : MnemonicAlias<"subc", "subx">, Requires<[HasV9]>;
|
def : MnemonicAlias<"subc", "subx">, Requires<[HasV9]>;
|
||||||
def : MnemonicAlias<"subccc", "subxcc">, 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]>;
|
||||||
|
|
|
@ -153,7 +153,6 @@ class F3_3c<bits<2> opVal, bits<6> op3val, bits<9> opfval, dag outs, dag ins,
|
||||||
|
|
||||||
let op = opVal;
|
let op = opVal;
|
||||||
let op3 = op3val;
|
let op3 = op3val;
|
||||||
let rd = 0;
|
|
||||||
|
|
||||||
let Inst{13-5} = opfval; // fp opcode
|
let Inst{13-5} = opfval; // fp opcode
|
||||||
let Inst{4-0} = rs2;
|
let Inst{4-0} = rs2;
|
||||||
|
|
|
@ -864,7 +864,7 @@ def FDIVQ : F3_3<2, 0b110100, 0b001001111,
|
||||||
// This behavior is modeled with a forced noop after the instruction in
|
// This behavior is modeled with a forced noop after the instruction in
|
||||||
// DelaySlotFiller.
|
// DelaySlotFiller.
|
||||||
|
|
||||||
let Defs = [FCC0] in {
|
let Defs = [FCC0], rd = 0, isCodeGenOnly = 1 in {
|
||||||
def FCMPS : F3_3c<2, 0b110101, 0b001010001,
|
def FCMPS : F3_3c<2, 0b110101, 0b001010001,
|
||||||
(outs), (ins FPRegs:$rs1, FPRegs:$rs2),
|
(outs), (ins FPRegs:$rs1, FPRegs:$rs2),
|
||||||
"fcmps $rs1, $rs2",
|
"fcmps $rs1, $rs2",
|
||||||
|
@ -1014,6 +1014,19 @@ let Predicates = [HasV9] in {
|
||||||
Requires<[HasHardQuad]>;
|
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
|
// 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.
|
// the top 32-bits before using it. To do this clearing, we use a SRLri X,0.
|
||||||
let rs1 = 0 in
|
let rs1 = 0 in
|
||||||
|
|
|
@ -120,13 +120,13 @@
|
||||||
# CHECK: fdivq %f0, %f4, %f8
|
# CHECK: fdivq %f0, %f4, %f8
|
||||||
0x91 0xa0 0x09 0xe4
|
0x91 0xa0 0x09 0xe4
|
||||||
|
|
||||||
# CHECK: fcmps %f0, %f4
|
# CHECK: fcmps %fcc0, %f0, %f4
|
||||||
0x81 0xa8 0x0a 0x24
|
0x81 0xa8 0x0a 0x24
|
||||||
|
|
||||||
# CHECK: fcmpd %f0, %f4
|
# CHECK: fcmpd %fcc0, %f0, %f4
|
||||||
0x81 0xa8 0x0a 0x44
|
0x81 0xa8 0x0a 0x44
|
||||||
|
|
||||||
# CHECK: fcmpq %f0, %f4
|
# CHECK: fcmpq %fcc0, %f0, %f4
|
||||||
0x81 0xa8 0x0a 0x64
|
0x81 0xa8 0x0a 0x64
|
||||||
|
|
||||||
# CHECK: fxtos %f0, %f4
|
# CHECK: fxtos %f0, %f4
|
||||||
|
|
|
@ -96,13 +96,20 @@
|
||||||
fdivd %f0, %f4, %f8
|
fdivd %f0, %f4, %f8
|
||||||
fdivq %f0, %f4, %f8
|
fdivq %f0, %f4, %f8
|
||||||
|
|
||||||
! CHECK: fcmps %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x24]
|
! CHECK: fcmps %fcc0, %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x24]
|
||||||
! CHECK: fcmpd %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x44]
|
! CHECK: fcmpd %fcc0, %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x44]
|
||||||
! CHECK: fcmpq %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x64]
|
! CHECK: fcmpq %fcc0, %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x64]
|
||||||
fcmps %f0, %f4
|
fcmps %f0, %f4
|
||||||
fcmpd %f0, %f4
|
fcmpd %f0, %f4
|
||||||
fcmpq %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: fxtos %f0, %f4 ! encoding: [0x89,0xa0,0x10,0x80]
|
||||||
! CHECK: fxtod %f0, %f4 ! encoding: [0x89,0xa0,0x11,0x00]
|
! CHECK: fxtod %f0, %f4 ! encoding: [0x89,0xa0,0x11,0x00]
|
||||||
! CHECK: fxtoq %f0, %f4 ! encoding: [0x89,0xa0,0x11,0x80]
|
! CHECK: fxtoq %f0, %f4 ! encoding: [0x89,0xa0,0x11,0x80]
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue