summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVenkatraman Govindaraju <venkatra@cs.wisc.edu>2014-01-10 01:48:17 +0000
committerVenkatraman Govindaraju <venkatra@cs.wisc.edu>2014-01-10 01:48:17 +0000
commit8ce28c812bdd11f5bb8d35d84b3ab97a4ad9ffd1 (patch)
tree862526347d40b77a85794013e2ef6dd533597188
parent0f09c9f5ac4017f4accda3691832e71ba7158c2c (diff)
downloadllvm-8ce28c812bdd11f5bb8d35d84b3ab97a4ad9ffd1.tar.gz
llvm-8ce28c812bdd11f5bb8d35d84b3ab97a4ad9ffd1.tar.bz2
llvm-8ce28c812bdd11f5bb8d35d84b3ab97a4ad9ffd1.tar.xz
[Sparc] Add support for parsing jmpl instruction and make indirect call and jmp instructions as aliases to jmpl.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198909 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/Sparc/AsmParser/SparcAsmParser.cpp1
-rw-r--r--lib/Target/Sparc/DelaySlotFiller.cpp16
-rw-r--r--lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp27
-rw-r--r--lib/Target/Sparc/InstPrinter/SparcInstPrinter.h2
-rw-r--r--lib/Target/Sparc/SparcInstrAliases.td11
-rw-r--r--lib/Target/Sparc/SparcInstrInfo.td35
-rw-r--r--test/MC/Sparc/sparc-ctrl-instructions.s13
7 files changed, 83 insertions, 22 deletions
diff --git a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
index cc6c983f58..a1c80e956f 100644
--- a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
+++ b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
@@ -453,6 +453,7 @@ parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
switch (getLexer().getKind()) {
default: return MatchOperand_NoMatch;
+ case AsmToken::Comma:
case AsmToken::RBrac:
case AsmToken::EndOfStatement:
Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E));
diff --git a/lib/Target/Sparc/DelaySlotFiller.cpp b/lib/Target/Sparc/DelaySlotFiller.cpp
index 9a0466aa69..b2d8b3fedb 100644
--- a/lib/Target/Sparc/DelaySlotFiller.cpp
+++ b/lib/Target/Sparc/DelaySlotFiller.cpp
@@ -278,19 +278,19 @@ void Filler::insertCallDefsUses(MachineBasicBlock::iterator MI,
switch(MI->getOpcode()) {
default: llvm_unreachable("Unknown opcode.");
case SP::CALL: break;
- case SP::JMPLrr:
- case SP::JMPLri:
+ case SP::CALLrr:
+ case SP::CALLri:
assert(MI->getNumOperands() >= 2);
const MachineOperand &Reg = MI->getOperand(0);
- assert(Reg.isReg() && "JMPL first operand is not a register.");
- assert(Reg.isUse() && "JMPL first operand is not a use.");
+ assert(Reg.isReg() && "CALL first operand is not a register.");
+ assert(Reg.isUse() && "CALL first operand is not a use.");
RegUses.insert(Reg.getReg());
const MachineOperand &RegOrImm = MI->getOperand(1);
if (RegOrImm.isImm())
break;
- assert(RegOrImm.isReg() && "JMPLrr second operand is not a register.");
- assert(RegOrImm.isUse() && "JMPLrr second operand is not a use.");
+ assert(RegOrImm.isReg() && "CALLrr second operand is not a register.");
+ assert(RegOrImm.isUse() && "CALLrr second operand is not a use.");
RegUses.insert(RegOrImm.getReg());
break;
}
@@ -353,8 +353,8 @@ bool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize)
switch (I->getOpcode()) {
default: llvm_unreachable("Unknown call opcode.");
case SP::CALL: structSizeOpNum = 1; break;
- case SP::JMPLrr:
- case SP::JMPLri: structSizeOpNum = 2; break;
+ case SP::CALLrr:
+ case SP::CALLri: structSizeOpNum = 2; break;
case SP::TLS_CALL: return false;
}
diff --git a/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp b/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
index 5e39bd6cb1..0228e61cf9 100644
--- a/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
+++ b/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
@@ -22,6 +22,7 @@
using namespace llvm;
#define GET_INSTRUCTION_NAME
+#define PRINT_ALIAS_INSTR
#include "SparcGenAsmWriter.inc"
void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
@@ -32,10 +33,34 @@ void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
void SparcInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
StringRef Annot)
{
- printInstruction(MI, O);
+ if (!printAliasInstr(MI, O) && !printSparcAliasInstr(MI, O))
+ printInstruction(MI, O);
printAnnotation(O, Annot);
}
+bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, raw_ostream &O)
+{
+ switch (MI->getOpcode()) {
+ default: return false;
+ case SP::JMPLrr:
+ case SP::JMPLri: {
+ if (MI->getNumOperands() != 3)
+ return false;
+ if (!MI->getOperand(0).isReg())
+ return false;
+ switch (MI->getOperand(0).getReg()) {
+ default: return false;
+ case SP::G0: // jmp $addr
+ O << "\tjmp "; printMemOperand(MI, 1, O);
+ return true;
+ case SP::O7: // call $addr
+ O << "\tcall "; printMemOperand(MI, 1, O);
+ return true;
+ }
+ }
+ }
+}
+
void SparcInstPrinter::printOperand(const MCInst *MI, int opNum,
raw_ostream &O)
{
diff --git a/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h b/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
index c6b57f826b..63ed41a4c1 100644
--- a/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
+++ b/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
@@ -29,9 +29,11 @@ public:
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);
// Autogenerated by tblgen.
void printInstruction(const MCInst *MI, raw_ostream &O);
+ bool printAliasInstr(const MCInst *MI, raw_ostream &O);
static const char *getRegisterName(unsigned RegNo);
void printOperand(const MCInst *MI, int opNum, raw_ostream &OS);
diff --git a/lib/Target/Sparc/SparcInstrAliases.td b/lib/Target/Sparc/SparcInstrAliases.td
index 3a489f40ad..06c9bf2cd4 100644
--- a/lib/Target/Sparc/SparcInstrAliases.td
+++ b/lib/Target/Sparc/SparcInstrAliases.td
@@ -117,3 +117,14 @@ defm : fp_cond_alias<"uge", 0b1100>;
defm : fp_cond_alias<"le", 0b1101>;
defm : fp_cond_alias<"ule", 0b1110>;
defm : fp_cond_alias<"o", 0b1111>;
+
+
+// Instruction aliases for JMPL.
+
+// jmp addr -> jmpl addr, %g0
+def : InstAlias<"jmp $addr", (JMPLrr G0, MEMrr:$addr)>;
+def : InstAlias<"jmp $addr", (JMPLri G0, MEMri:$addr)>;
+
+// call addr -> jmpl addr, %o7
+def : InstAlias<"call $addr", (JMPLrr O7, MEMrr:$addr)>;
+def : InstAlias<"call $addr", (JMPLri O7, MEMri:$addr)>;
diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td
index 2ef8729b0f..a3b36e039c 100644
--- a/lib/Target/Sparc/SparcInstrInfo.td
+++ b/lib/Target/Sparc/SparcInstrInfo.td
@@ -362,10 +362,18 @@ let usesCustomInserter = 1, Uses = [FCC] in {
[(set f128:$dst, (SPselectfcc f128:$T, f128:$F, imm:$Cond))]>;
}
+// JMPL Instruction.
+let isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in {
+ def JMPLrr: F3_1<2, 0b111000, (outs IntRegs:$dst), (ins MEMrr:$addr),
+ "jmpl $addr, $dst", []>;
+ def JMPLri: F3_2<2, 0b111000, (outs IntRegs:$dst), (ins MEMri:$addr),
+ "jmpl $addr, $dst", []>;
+}
// Section A.3 - Synthetic Instructions, p. 85
// special cases of JMPL:
-let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in {
+let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1,
+ isCodeGenOnly = 1 in {
let rd = 0, rs1 = 15 in
def RETL: F3_2<2, 0b111000, (outs), (ins i32imm:$val),
"jmp %o7+$val", [(retflag simm13:$val)]>;
@@ -519,9 +527,8 @@ class BranchSP<dag ins, string asmstr, list<dag> pattern>
}
// Indirect branch instructions.
-let isTerminator = 1, isBarrier = 1,
- hasDelaySlot = 1, isBranch =1,
- isIndirectBranch = 1, rd = 0 in {
+let isTerminator = 1, isBarrier = 1, hasDelaySlot = 1, isBranch =1,
+ isIndirectBranch = 1, rd = 0, isCodeGenOnly = 1 in {
def BINDrr : F3_1<2, 0b111000,
(outs), (ins MEMrr:$ptr),
"jmp $ptr",
@@ -564,15 +571,17 @@ let Uses = [O6],
let Inst{29-0} = disp;
}
- // indirect calls
- def JMPLrr : F3_1<2, 0b111000,
- (outs), (ins MEMrr:$ptr, variable_ops),
- "call $ptr",
- [(call ADDRrr:$ptr)]> { let rd = 15; }
- def JMPLri : F3_2<2, 0b111000,
- (outs), (ins MEMri:$ptr, variable_ops),
- "call $ptr",
- [(call ADDRri:$ptr)]> { let rd = 15; }
+ // indirect calls: special cases of JMPL.
+ let isCodeGenOnly = 1, rd = 15 in {
+ def CALLrr : F3_1<2, 0b111000,
+ (outs), (ins MEMrr:$ptr, variable_ops),
+ "call $ptr",
+ [(call ADDRrr:$ptr)]>;
+ def CALLri : F3_2<2, 0b111000,
+ (outs), (ins MEMri:$ptr, variable_ops),
+ "call $ptr",
+ [(call ADDRri:$ptr)]>;
+ }
}
// Section B.28 - Read State Register Instructions
diff --git a/test/MC/Sparc/sparc-ctrl-instructions.s b/test/MC/Sparc/sparc-ctrl-instructions.s
index acedcb46cc..f713276747 100644
--- a/test/MC/Sparc/sparc-ctrl-instructions.s
+++ b/test/MC/Sparc/sparc-ctrl-instructions.s
@@ -31,6 +31,19 @@
! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10
jmp %g1+%lo(sym)
+ ! CHECK: jmpl %g1+%i2, %g2 ! encoding: [0x85,0xc0,0x40,0x1a]
+ jmpl %g1 + %i2, %g2
+
+ ! CHECK: jmpl %o1+8, %g2 ! encoding: [0x85,0xc2,0x60,0x08]
+ jmpl %o1 + 8, %g2
+
+ ! CHECK: jmpl %g1, %g2 ! encoding: [0x85,0xc0,0x60,0x00]
+ jmpl %g1, %g2
+
+ ! CHECK: jmpl %g1+%lo(sym), %g2 ! encoding: [0x85,0xc0,0b011000AA,A]
+ ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10
+ jmpl %g1+%lo(sym), %g2
+
! CHECK: ba .BB0 ! encoding: [0x10,0b10AAAAAA,A,A]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
ba .BB0