From 8ce28c812bdd11f5bb8d35d84b3ab97a4ad9ffd1 Mon Sep 17 00:00:00 2001 From: Venkatraman Govindaraju Date: Fri, 10 Jan 2014 01:48:17 +0000 Subject: [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 --- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp | 1 + lib/Target/Sparc/DelaySlotFiller.cpp | 16 +++++------ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp | 27 ++++++++++++++++- lib/Target/Sparc/InstPrinter/SparcInstPrinter.h | 2 ++ lib/Target/Sparc/SparcInstrAliases.td | 11 +++++++ lib/Target/Sparc/SparcInstrInfo.td | 35 ++++++++++++++--------- test/MC/Sparc/sparc-ctrl-instructions.s | 13 +++++++++ 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 &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 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 -- cgit v1.2.3