diff --git a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp index 8f96951e2697..9fb37c58e85f 100644 --- a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp +++ b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp @@ -60,6 +60,14 @@ extern "C" void LLVMInitializePowerPCDisassembler() { createPPCLEDisassembler); } +static DecodeStatus DecodePCRel24BranchTarget(MCInst &Inst, unsigned Imm, + uint64_t Addr, + const void *Decoder) { + int32_t Offset = SignExtend32<24>(Imm); + Inst.addOperand(MCOperand::createImm(Offset)); + return MCDisassembler::Success; +} + // FIXME: These can be generated by TableGen from the existing register // encoding values! diff --git a/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp b/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp index f4fcf58cedcb..49e73891bc30 100644 --- a/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp +++ b/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp @@ -381,8 +381,11 @@ void PPCInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo, // Branches can take an immediate operand. This is used by the branch // selection pass to print .+8, an eight byte displacement from the PC. - O << ".+"; - printAbsBranchOperand(MI, OpNo, O); + O << "."; + int32_t Imm = MI->getOperand(OpNo).getImm() << 2; + if (Imm >= 0) + O << "+"; + O << Imm; } void PPCInstPrinter::printAbsBranchOperand(const MCInst *MI, unsigned OpNo, diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index 7672f8da0fce..e54292aee286 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -736,7 +736,9 @@ def abscondbrtarget : Operand { def calltarget : Operand { let PrintMethod = "printBranchOperand"; let EncoderMethod = "getDirectBrEncoding"; + let DecoderMethod = "DecodePCRel24BranchTarget"; let ParserMatchClass = PPCDirectBrAsmOperand; + let OperandType = "OPERAND_PCREL"; } def abscalltarget : Operand { let PrintMethod = "printAbsBranchOperand"; diff --git a/llvm/test/tools/llvm-objdump/PowerPC/branch-offset.s b/llvm/test/tools/llvm-objdump/PowerPC/branch-offset.s new file mode 100644 index 000000000000..b0b3f05f9cdb --- /dev/null +++ b/llvm/test/tools/llvm-objdump/PowerPC/branch-offset.s @@ -0,0 +1,43 @@ +# RUN: llvm-mc -triple=powerpc64le-unknown-linux -filetype=obj %s -o %t.o +# RUN: llvm-objdump -d %t.o | FileCheck %s + +# RUN: llvm-mc -triple=powerpc64-unknown-linux -filetype=obj %s -o %t.o +# RUN: llvm-objdump -d %t.o | FileCheck %s + +# RUN: llvm-mc -triple=powerpc-unknown-linux -filetype=obj %s -o %t.o +# RUN: llvm-objdump -d %t.o | FileCheck %s + +# CHECK: 0000000000000000 callee_back: +# CHECK: 18: {{.*}} bl .-24 +# CHECK: 20: {{.*}} bl .+16 +# CHECK: 0000000000000030 callee_forward: + + .text + .global caller + .type caller,@function + .type callee_forward,@function + .type callee_back,@function + + .p2align 4 +callee_back: + li 3, 55 + blr + + .p2align 4 +caller: +.Lgep: + addis 2, 12, .TOC.-.Lgep@ha + addi 2, 2, .TOC.-.Lgep@l +.Llep: + .localentry caller, .Llep-.Lgep + bl callee_back + mr 31, 3 + bl callee_forward + add 3, 3, 31 + blr + + .p2align 4 +callee_forward: + li 3, 66 + blr + diff --git a/llvm/test/tools/llvm-objdump/PowerPC/lit.local.cfg b/llvm/test/tools/llvm-objdump/PowerPC/lit.local.cfg new file mode 100644 index 000000000000..b77510721e10 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/PowerPC/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'PowerPC' in config.root.targets: + config.unsupported = True