Skip to content

[SPARC] Print target address when disassembling branches and calls #140340

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 19, 2025

Conversation

koachan
Copy link
Contributor

@koachan koachan commented May 17, 2025

Similar to https://reviews.llvm.org/D93241, print target addresses instead of raw offset values when disassembling branches and calls.

Should fix #122196 and #139284.

Similar to https://reviews.llvm.org/D93241, print target addresses
instead of raw offset values when disassembling branches and calls.

Should fix llvm#122196
and llvm#139284.
@llvmbot llvmbot added backend:Sparc mc Machine (object) code labels May 17, 2025
@koachan
Copy link
Contributor Author

koachan commented May 17, 2025

Pinging @Rot127 too

@llvmbot
Copy link
Member

llvmbot commented May 17, 2025

@llvm/pr-subscribers-mc

Author: Koakuma (koachan)

Changes

Similar to https://reviews.llvm.org/D93241, print target addresses instead of raw offset values when disassembling branches and calls.

Should fix #122196 and #139284.


Full diff: https://github.com/llvm/llvm-project/pull/140340.diff

9 Files Affected:

  • (modified) llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp (+19-6)
  • (modified) llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp (+20)
  • (modified) llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h (+2)
  • (modified) llvm/lib/Target/Sparc/SparcInstrInfo.td (+11)
  • (modified) llvm/test/MC/Disassembler/Sparc/sparc.txt (+45-45)
  • (modified) llvm/test/MC/Sparc/Misc/little-endian.s (+1-1)
  • (modified) llvm/test/MC/Sparc/Relocations/expr.s (+1-1)
  • (modified) llvm/test/MC/Sparc/Relocations/relocation.s (+8-8)
  • (modified) llvm/test/MC/Sparc/sparc64-bpr-offset.s (+12-12)
diff --git a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
index 220e4d4e6e56e..b8ac5159411e8 100644
--- a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
+++ b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
@@ -263,7 +263,10 @@ static DecodeStatus DecodeCall(MCInst &Inst, unsigned insn, uint64_t Address,
                                const MCDisassembler *Decoder);
 static DecodeStatus DecodeSIMM13(MCInst &Inst, unsigned insn, uint64_t Address,
                                  const MCDisassembler *Decoder);
-
+template <unsigned N>
+constexpr static DecodeStatus DecodeDisp(MCInst &MI, uint32_t ImmVal,
+                                         uint64_t Address,
+                                         const MCDisassembler *Decoder);
 #include "SparcGenDisassemblerTables.inc"
 
 /// Read four bytes from the ArrayRef and return 32 bit word.
@@ -326,11 +329,10 @@ static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
 
 static DecodeStatus DecodeCall(MCInst &MI, unsigned insn, uint64_t Address,
                                const MCDisassembler *Decoder) {
-  unsigned tgt = fieldFromInstruction(insn, 0, 30);
-  tgt <<= 2;
-  if (!tryAddingSymbolicOperand(tgt+Address, false, Address,
-                                0, 30, MI, Decoder))
-    MI.addOperand(MCOperand::createImm(tgt));
+  unsigned Offset = fieldFromInstruction(insn, 0, 30);
+  int64_t CallTarget = Address + (SignExtend64(Offset, 30) * 4);
+  if (!tryAddingSymbolicOperand(CallTarget, false, Address, 0, 30, MI, Decoder))
+    MI.addOperand(MCOperand::createImm(CallTarget));
   return MCDisassembler::Success;
 }
 
@@ -340,3 +342,14 @@ static DecodeStatus DecodeSIMM13(MCInst &MI, unsigned insn, uint64_t Address,
   MI.addOperand(MCOperand::createImm(SignExtend64<13>(insn)));
   return MCDisassembler::Success;
 }
+
+template <unsigned N>
+constexpr static DecodeStatus DecodeDisp(MCInst &MI, uint32_t ImmVal,
+                                         uint64_t Address,
+                                         const MCDisassembler *Decoder) {
+  int64_t BranchTarget = Address + (SignExtend64(ImmVal, N) * 4);
+  if (!tryAddingSymbolicOperand(BranchTarget, false, Address, 0, N, MI,
+                                Decoder))
+    MI.addOperand(MCOperand::createImm(BranchTarget));
+  return MCDisassembler::Success;
+}
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
index 4cb1df29ca6d2..3b48f6b844474 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
@@ -263,3 +263,23 @@ void SparcInstPrinter::printPrefetchTag(const MCInst *MI, int opNum,
   else
     O << Imm;
 }
+
+void SparcInstPrinter::printCTILabel(const MCInst *MI, uint64_t Address,
+                                     unsigned OpNum, const MCSubtargetInfo &STI,
+                                     raw_ostream &O) {
+  const MCOperand &Op = MI->getOperand(OpNum);
+
+  // If the label has already been resolved to an immediate offset (say, when
+  // we're running the disassembler), just print the immediate.
+  if (Op.isImm()) {
+    const int64_t Offset = Op.getImm();
+    if (PrintBranchImmAsAddress)
+      O << formatHex(Offset);
+    else
+      O << Offset;
+    return;
+  }
+
+  // Otherwise, just print the expression.
+  Op.getExpr()->print(O, &MAI);
+}
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h
index 6a1d2394d488e..a6d7f9236f552 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h
@@ -37,6 +37,8 @@ class SparcInstPrinter : public MCInstPrinter {
   getMnemonic(const MCInst &MI) const override;
   void printInstruction(const MCInst *MI, uint64_t Address,
                         const MCSubtargetInfo &STI, raw_ostream &O);
+  void printCTILabel(const MCInst *MI, uint64_t Address, unsigned OpNum,
+                     const MCSubtargetInfo &STI, raw_ostream &O);
   bool printAliasInstr(const MCInst *MI, uint64_t Address,
                        const MCSubtargetInfo &STI, raw_ostream &O);
   void printCustomAliasOperand(const MCInst *MI, uint64_t Address,
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td
index dd77432c8e8d9..21379950485e6 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.td
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td
@@ -227,14 +227,23 @@ def PrefetchTag : Operand<i32> {
 // Branch targets have OtherVT type.
 def brtarget : Operand<OtherVT> {
   let EncoderMethod = "getBranchTargetOpValue";
+  let DecoderMethod = "DecodeDisp<22>";
+  let PrintMethod = "printCTILabel";
+  let OperandType = "OPERAND_PCREL";
 }
 
 def bprtarget : Operand<OtherVT> {
   let EncoderMethod = "getBranchPredTargetOpValue";
+  let DecoderMethod = "DecodeDisp<19>";
+  let PrintMethod = "printCTILabel";
+  let OperandType = "OPERAND_PCREL";
 }
 
 def bprtarget16 : Operand<OtherVT> {
   let EncoderMethod = "getBranchOnRegTargetOpValue";
+  let DecoderMethod = "DecodeDisp<16>";
+  let PrintMethod = "printCTILabel";
+  let OperandType = "OPERAND_PCREL";
 }
 
 def SparcCallTargetAsmOperand : AsmOperandClass {
@@ -246,6 +255,8 @@ def calltarget : Operand<i32> {
   let EncoderMethod = "getCallTargetOpValue";
   let DecoderMethod = "DecodeCall";
   let ParserMatchClass = SparcCallTargetAsmOperand;
+  let PrintMethod = "printCTILabel";
+  let OperandType = "OPERAND_PCREL";
 }
 
 // Operand for printing out a condition code.
diff --git a/llvm/test/MC/Disassembler/Sparc/sparc.txt b/llvm/test/MC/Disassembler/Sparc/sparc.txt
index da1ac062f7220..64db30bf791b3 100644
--- a/llvm/test/MC/Disassembler/Sparc/sparc.txt
+++ b/llvm/test/MC/Disassembler/Sparc/sparc.txt
@@ -81,142 +81,142 @@
 # CHECK: subxcc %g1, %g2, %g3
 0x86 0xe0 0x40 0x02
 
-# CHECK: ba 4194303
+# CHECK: ba 104
 0x10 0xbf 0xff 0xff
 
-# CHECK: bne 4194303
+# CHECK: bne 108
 0x12 0xbf 0xff 0xff
 
-# CHECK: be 4194303
+# CHECK: be 112
 0x02 0xbf 0xff 0xff
 
-# CHECK: bg 4194303
+# CHECK: bg 116
 0x14 0xbf 0xff 0xff
 
-# CHECK: ble 4194303
+# CHECK: ble 120
 0x04 0xbf 0xff 0xff
 
-# CHECK: bge 4194303
+# CHECK: bge 124
 0x16 0xbf 0xff 0xff
 
-# CHECK: bl 4194303
+# CHECK: bl 128
 0x06 0xbf 0xff 0xff
 
-# CHECK: bgu 4194303
+# CHECK: bgu 132
 0x18 0xbf 0xff 0xff
 
-# CHECK: bleu 4194303
+# CHECK: bleu 136
 0x08 0xbf 0xff 0xff
 
-# CHECK: bcc 4194303
+# CHECK: bcc 140
 0x1a 0xbf 0xff 0xff
 
-# CHECK: bcs 4194303
+# CHECK: bcs 144
 0x0a 0xbf 0xff 0xff
 
-# CHECK: bpos 4194303
+# CHECK: bpos 148
 0x1c 0xbf 0xff 0xff
 
-# CHECK: bneg 4194303
+# CHECK: bneg 152
 0x0c 0xbf 0xff 0xff
 
-# CHECK: bvc 4194303
+# CHECK: bvc 156
 0x1e 0xbf 0xff 0xff
 
-# CHECK: bvs 4194303
+# CHECK: bvs 160
 0x0e 0xbf 0xff 0xff
 
-# CHECK: fbu 4194303
+# CHECK: fbu 164
 0x0f 0xbf 0xff 0xff
 
-# CHECK: fbg 4194303
+# CHECK: fbg 168
 0x0d 0xbf 0xff 0xff
 
-# CHECK: fbug 4194303
+# CHECK: fbug 172
 0x0b 0xbf 0xff 0xff
 
-# CHECK: fbl 4194303
+# CHECK: fbl 176
 0x09 0xbf 0xff 0xff
 
-# CHECK: fbul 4194303
+# CHECK: fbul 180
 0x07 0xbf 0xff 0xff
 
-# CHECK: fblg 4194303
+# CHECK: fblg 184
 0x05 0xbf 0xff 0xff
 
-# CHECK: fbne 4194303
+# CHECK: fbne 188
 0x03 0xbf 0xff 0xff
 
-# CHECK: fbe 4194303
+# CHECK: fbe 192
 0x13 0xbf 0xff 0xff
 
-# CHECK: fbue 4194303
+# CHECK: fbue 196
 0x15 0xbf 0xff 0xff
 
-# CHECK: fbge 4194303
+# CHECK: fbge 200
 0x17 0xbf 0xff 0xff
 
-# CHECK: fbuge 4194303
+# CHECK: fbuge 204
 0x19 0xbf 0xff 0xff
 
-# CHECK: fble 4194303
+# CHECK: fble 208
 0x1b 0xbf 0xff 0xff
 
-# CHECK: fbule 4194303
+# CHECK: fbule 212
 0x1d 0xbf 0xff 0xff
 
-# CHECK: fbo 4194303
+# CHECK: fbo 216
 0x1f 0xbf 0xff 0xff
 
-# CHECK: cba 4194303
+# CHECK: cba 220
 0x11 0xff 0xff 0xff
 
-# CHECK: cbn 4194303
+# CHECK: cbn 224
 0x01 0xff 0xff 0xff
 
-# CHECK: cb3 4194303
+# CHECK: cb3 228
 0x0f 0xff 0xff 0xff
 
-# CHECK: cb2 4194303
+# CHECK: cb2 232
 0x0d 0xff 0xff 0xff
 
-# CHECK: cb23 4194303
+# CHECK: cb23 236
 0x0b 0xff 0xff 0xff
 
-# CHECK: cb1 4194303
+# CHECK: cb1 240
 0x09 0xff 0xff 0xff
 
-# CHECK: cb13 4194303
+# CHECK: cb13 244
 0x07 0xff 0xff 0xff
 
-# CHECK: cb12 4194303
+# CHECK: cb12 248
 0x05 0xff 0xff 0xff
 
-# CHECK: cb123 4194303
+# CHECK: cb123 252
 0x03 0xff 0xff 0xff
 
-# CHECK: cb03 4194303
+# CHECK: cb03 256
 0x15 0xff 0xff 0xff
 
-# CHECK: cb02 4194303
+# CHECK: cb02 260
 0x17 0xff 0xff 0xff
 
-# CHECK: cb023 4194303
+# CHECK: cb023 264
 0x19 0xff 0xff 0xff
 
-# CHECK: cb01 4194303
+# CHECK: cb01 268
 0x1b 0xff 0xff 0xff
 
-# CHECK: cb013 4194303
+# CHECK: cb013 272
 0x1d 0xff 0xff 0xff
 
-# CHECK: cb012 4194303
+# CHECK: cb012 276
 0x1f 0xff 0xff 0xff
 
 # CHECK: restore
 0x81 0xe8 0x00 0x00
 
-# CHECK: call 16
+# CHECK: call 304
 0x40 0x00 0x00 0x04
 
 # CHECK: add %g1, -10, %g2
diff --git a/llvm/test/MC/Sparc/Misc/little-endian.s b/llvm/test/MC/Sparc/Misc/little-endian.s
index d02dfd40d195b..d30db6e6aa0d7 100644
--- a/llvm/test/MC/Sparc/Misc/little-endian.s
+++ b/llvm/test/MC/Sparc/Misc/little-endian.s
@@ -13,5 +13,5 @@
         ! ...and that fixups are applied to the correct bytes.
 
         ! CHECK: ba .BB0      ! encoding: [A,A,0b10AAAAAA,0x10]
-        ! CHECK-OBJ: 4: ff ff bf 10  ba 0x3fffff
+        ! CHECK-OBJ: 4: ff ff bf 10  ba 0x0
         ba .BB0
diff --git a/llvm/test/MC/Sparc/Relocations/expr.s b/llvm/test/MC/Sparc/Relocations/expr.s
index 68ea447a226d6..fcde7d6a1d905 100644
--- a/llvm/test/MC/Sparc/Relocations/expr.s
+++ b/llvm/test/MC/Sparc/Relocations/expr.s
@@ -7,7 +7,7 @@
         mov      ((12+3)<<2), %o2
 
         ! CHECK:   ba      symStart+4
-        ! OBJDUMP: ba    0x1
+        ! OBJDUMP: ba    0xc
 symStart:
         b        symStart + 4
 
diff --git a/llvm/test/MC/Sparc/Relocations/relocation.s b/llvm/test/MC/Sparc/Relocations/relocation.s
index 30c2b9409e765..8e632e05def7e 100644
--- a/llvm/test/MC/Sparc/Relocations/relocation.s
+++ b/llvm/test/MC/Sparc/Relocations/relocation.s
@@ -7,9 +7,9 @@
 # ASM:      call local1
 # ASM-NEXT: call undef
 # OBJDUMP:      call 0x14
-# OBJDUMP-NEXT: call 0x0
+# OBJDUMP-NEXT: call 0x4
 # OBJDUMP-NEXT:   R_SPARC_WDISP30 .text1+0x4
-# OBJDUMP-NEXT: call 0x0
+# OBJDUMP-NEXT: call 0x8
 # OBJDUMP-NEXT:   R_SPARC_WDISP30 undef{{$}}
 call local
 call local1
@@ -28,15 +28,15 @@ local:
 
 # ASM:      brz %g1, undef
 # ASM:      brlz %g1, .Ltmp{{.}}-8
-# OBJDUMP:      brz %g1, 0x0
+# OBJDUMP:      brz %g1, 0x14
 # OBJDUMP-NEXT:   R_SPARC_WDISP16 undef
-# OBJDUMP-NEXT: brlz %g1, 0xfffe
-# OBJDUMP-NEXT: bg %icc, 0x0
+# OBJDUMP-NEXT: brlz %g1, 0x10
+# OBJDUMP-NEXT: bg %icc, 0x1c
 # OBJDUMP-NEXT:   R_SPARC_WDISP19 undef
-# OBJDUMP-NEXT: bg %icc, 0x7fffe
-# OBJDUMP-NEXT: cbn 0x0
+# OBJDUMP-NEXT: bg %icc, 0x18
+# OBJDUMP-NEXT: cbn 0x24
 # OBJDUMP-NEXT:   R_SPARC_WDISP22 undef
-# OBJDUMP-NEXT: cbn 0x3ffffe
+# OBJDUMP-NEXT: cbn 0x20
 brz %g1, undef
 brlz %g1, .-8
 bg %icc, undef
diff --git a/llvm/test/MC/Sparc/sparc64-bpr-offset.s b/llvm/test/MC/Sparc/sparc64-bpr-offset.s
index 37453567924f3..3abae6a5b5710 100644
--- a/llvm/test/MC/Sparc/sparc64-bpr-offset.s
+++ b/llvm/test/MC/Sparc/sparc64-bpr-offset.s
@@ -4,12 +4,12 @@
         !! make sure that our offset bits don't trample on other fields.
         !! This is particularly important with backwards branches.
 
-        ! BIN:  0: 02 c8 40 01  	brz %g1, 1
-        ! BIN:  4: 04 c8 40 01  	brlez %g1, 1
-        ! BIN:  8: 06 c8 40 01  	brlz %g1, 1
-        ! BIN:  c: 0a c8 40 01  	brnz %g1, 1
-        ! BIN: 10: 0c c8 40 01  	brgz %g1, 1
-        ! BIN: 14: 0e c8 40 01  	brgez %g1, 1
+        ! BIN:  0: 02 c8 40 01  	brz %g1, 0x4
+        ! BIN:  4: 04 c8 40 01  	brlez %g1, 0x8
+        ! BIN:  8: 06 c8 40 01  	brlz %g1, 0xc
+        ! BIN:  c: 0a c8 40 01  	brnz %g1, 0x10
+        ! BIN: 10: 0c c8 40 01  	brgz %g1, 0x14
+        ! BIN: 14: 0e c8 40 01  	brgez %g1, 0x18
         brz   %g1, .+4
         brlez %g1, .+4
         brlz  %g1, .+4
@@ -17,12 +17,12 @@
         brgz  %g1, .+4
         brgez %g1, .+4
 
-        ! BIN: 18: 02 f8 7f ff  	brz %g1, 65535
-        ! BIN: 1c: 04 f8 7f ff  	brlez %g1, 65535
-        ! BIN: 20: 06 f8 7f ff  	brlz %g1, 65535
-        ! BIN: 24: 0a f8 7f ff  	brnz %g1, 65535
-        ! BIN: 28: 0c f8 7f ff  	brgz %g1, 65535
-        ! BIN: 2c: 0e f8 7f ff  	brgez %g1, 65535
+        ! BIN: 18: 02 f8 7f ff  	brz %g1, 0x14
+        ! BIN: 1c: 04 f8 7f ff  	brlez %g1, 0x18
+        ! BIN: 20: 06 f8 7f ff  	brlz %g1, 0x1c
+        ! BIN: 24: 0a f8 7f ff  	brnz %g1, 0x20
+        ! BIN: 28: 0c f8 7f ff  	brgz %g1, 0x24
+        ! BIN: 2c: 0e f8 7f ff  	brgez %g1, 0x28
         brz   %g1, .-4
         brlez %g1, .-4
         brlz  %g1, .-4

@llvmbot
Copy link
Member

llvmbot commented May 17, 2025

@llvm/pr-subscribers-backend-sparc

Author: Koakuma (koachan)

Changes

Similar to https://reviews.llvm.org/D93241, print target addresses instead of raw offset values when disassembling branches and calls.

Should fix #122196 and #139284.


Full diff: https://github.com/llvm/llvm-project/pull/140340.diff

9 Files Affected:

  • (modified) llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp (+19-6)
  • (modified) llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp (+20)
  • (modified) llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h (+2)
  • (modified) llvm/lib/Target/Sparc/SparcInstrInfo.td (+11)
  • (modified) llvm/test/MC/Disassembler/Sparc/sparc.txt (+45-45)
  • (modified) llvm/test/MC/Sparc/Misc/little-endian.s (+1-1)
  • (modified) llvm/test/MC/Sparc/Relocations/expr.s (+1-1)
  • (modified) llvm/test/MC/Sparc/Relocations/relocation.s (+8-8)
  • (modified) llvm/test/MC/Sparc/sparc64-bpr-offset.s (+12-12)
diff --git a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
index 220e4d4e6e56e..b8ac5159411e8 100644
--- a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
+++ b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
@@ -263,7 +263,10 @@ static DecodeStatus DecodeCall(MCInst &Inst, unsigned insn, uint64_t Address,
                                const MCDisassembler *Decoder);
 static DecodeStatus DecodeSIMM13(MCInst &Inst, unsigned insn, uint64_t Address,
                                  const MCDisassembler *Decoder);
-
+template <unsigned N>
+constexpr static DecodeStatus DecodeDisp(MCInst &MI, uint32_t ImmVal,
+                                         uint64_t Address,
+                                         const MCDisassembler *Decoder);
 #include "SparcGenDisassemblerTables.inc"
 
 /// Read four bytes from the ArrayRef and return 32 bit word.
@@ -326,11 +329,10 @@ static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
 
 static DecodeStatus DecodeCall(MCInst &MI, unsigned insn, uint64_t Address,
                                const MCDisassembler *Decoder) {
-  unsigned tgt = fieldFromInstruction(insn, 0, 30);
-  tgt <<= 2;
-  if (!tryAddingSymbolicOperand(tgt+Address, false, Address,
-                                0, 30, MI, Decoder))
-    MI.addOperand(MCOperand::createImm(tgt));
+  unsigned Offset = fieldFromInstruction(insn, 0, 30);
+  int64_t CallTarget = Address + (SignExtend64(Offset, 30) * 4);
+  if (!tryAddingSymbolicOperand(CallTarget, false, Address, 0, 30, MI, Decoder))
+    MI.addOperand(MCOperand::createImm(CallTarget));
   return MCDisassembler::Success;
 }
 
@@ -340,3 +342,14 @@ static DecodeStatus DecodeSIMM13(MCInst &MI, unsigned insn, uint64_t Address,
   MI.addOperand(MCOperand::createImm(SignExtend64<13>(insn)));
   return MCDisassembler::Success;
 }
+
+template <unsigned N>
+constexpr static DecodeStatus DecodeDisp(MCInst &MI, uint32_t ImmVal,
+                                         uint64_t Address,
+                                         const MCDisassembler *Decoder) {
+  int64_t BranchTarget = Address + (SignExtend64(ImmVal, N) * 4);
+  if (!tryAddingSymbolicOperand(BranchTarget, false, Address, 0, N, MI,
+                                Decoder))
+    MI.addOperand(MCOperand::createImm(BranchTarget));
+  return MCDisassembler::Success;
+}
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
index 4cb1df29ca6d2..3b48f6b844474 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
@@ -263,3 +263,23 @@ void SparcInstPrinter::printPrefetchTag(const MCInst *MI, int opNum,
   else
     O << Imm;
 }
+
+void SparcInstPrinter::printCTILabel(const MCInst *MI, uint64_t Address,
+                                     unsigned OpNum, const MCSubtargetInfo &STI,
+                                     raw_ostream &O) {
+  const MCOperand &Op = MI->getOperand(OpNum);
+
+  // If the label has already been resolved to an immediate offset (say, when
+  // we're running the disassembler), just print the immediate.
+  if (Op.isImm()) {
+    const int64_t Offset = Op.getImm();
+    if (PrintBranchImmAsAddress)
+      O << formatHex(Offset);
+    else
+      O << Offset;
+    return;
+  }
+
+  // Otherwise, just print the expression.
+  Op.getExpr()->print(O, &MAI);
+}
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h
index 6a1d2394d488e..a6d7f9236f552 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h
@@ -37,6 +37,8 @@ class SparcInstPrinter : public MCInstPrinter {
   getMnemonic(const MCInst &MI) const override;
   void printInstruction(const MCInst *MI, uint64_t Address,
                         const MCSubtargetInfo &STI, raw_ostream &O);
+  void printCTILabel(const MCInst *MI, uint64_t Address, unsigned OpNum,
+                     const MCSubtargetInfo &STI, raw_ostream &O);
   bool printAliasInstr(const MCInst *MI, uint64_t Address,
                        const MCSubtargetInfo &STI, raw_ostream &O);
   void printCustomAliasOperand(const MCInst *MI, uint64_t Address,
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td
index dd77432c8e8d9..21379950485e6 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.td
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td
@@ -227,14 +227,23 @@ def PrefetchTag : Operand<i32> {
 // Branch targets have OtherVT type.
 def brtarget : Operand<OtherVT> {
   let EncoderMethod = "getBranchTargetOpValue";
+  let DecoderMethod = "DecodeDisp<22>";
+  let PrintMethod = "printCTILabel";
+  let OperandType = "OPERAND_PCREL";
 }
 
 def bprtarget : Operand<OtherVT> {
   let EncoderMethod = "getBranchPredTargetOpValue";
+  let DecoderMethod = "DecodeDisp<19>";
+  let PrintMethod = "printCTILabel";
+  let OperandType = "OPERAND_PCREL";
 }
 
 def bprtarget16 : Operand<OtherVT> {
   let EncoderMethod = "getBranchOnRegTargetOpValue";
+  let DecoderMethod = "DecodeDisp<16>";
+  let PrintMethod = "printCTILabel";
+  let OperandType = "OPERAND_PCREL";
 }
 
 def SparcCallTargetAsmOperand : AsmOperandClass {
@@ -246,6 +255,8 @@ def calltarget : Operand<i32> {
   let EncoderMethod = "getCallTargetOpValue";
   let DecoderMethod = "DecodeCall";
   let ParserMatchClass = SparcCallTargetAsmOperand;
+  let PrintMethod = "printCTILabel";
+  let OperandType = "OPERAND_PCREL";
 }
 
 // Operand for printing out a condition code.
diff --git a/llvm/test/MC/Disassembler/Sparc/sparc.txt b/llvm/test/MC/Disassembler/Sparc/sparc.txt
index da1ac062f7220..64db30bf791b3 100644
--- a/llvm/test/MC/Disassembler/Sparc/sparc.txt
+++ b/llvm/test/MC/Disassembler/Sparc/sparc.txt
@@ -81,142 +81,142 @@
 # CHECK: subxcc %g1, %g2, %g3
 0x86 0xe0 0x40 0x02
 
-# CHECK: ba 4194303
+# CHECK: ba 104
 0x10 0xbf 0xff 0xff
 
-# CHECK: bne 4194303
+# CHECK: bne 108
 0x12 0xbf 0xff 0xff
 
-# CHECK: be 4194303
+# CHECK: be 112
 0x02 0xbf 0xff 0xff
 
-# CHECK: bg 4194303
+# CHECK: bg 116
 0x14 0xbf 0xff 0xff
 
-# CHECK: ble 4194303
+# CHECK: ble 120
 0x04 0xbf 0xff 0xff
 
-# CHECK: bge 4194303
+# CHECK: bge 124
 0x16 0xbf 0xff 0xff
 
-# CHECK: bl 4194303
+# CHECK: bl 128
 0x06 0xbf 0xff 0xff
 
-# CHECK: bgu 4194303
+# CHECK: bgu 132
 0x18 0xbf 0xff 0xff
 
-# CHECK: bleu 4194303
+# CHECK: bleu 136
 0x08 0xbf 0xff 0xff
 
-# CHECK: bcc 4194303
+# CHECK: bcc 140
 0x1a 0xbf 0xff 0xff
 
-# CHECK: bcs 4194303
+# CHECK: bcs 144
 0x0a 0xbf 0xff 0xff
 
-# CHECK: bpos 4194303
+# CHECK: bpos 148
 0x1c 0xbf 0xff 0xff
 
-# CHECK: bneg 4194303
+# CHECK: bneg 152
 0x0c 0xbf 0xff 0xff
 
-# CHECK: bvc 4194303
+# CHECK: bvc 156
 0x1e 0xbf 0xff 0xff
 
-# CHECK: bvs 4194303
+# CHECK: bvs 160
 0x0e 0xbf 0xff 0xff
 
-# CHECK: fbu 4194303
+# CHECK: fbu 164
 0x0f 0xbf 0xff 0xff
 
-# CHECK: fbg 4194303
+# CHECK: fbg 168
 0x0d 0xbf 0xff 0xff
 
-# CHECK: fbug 4194303
+# CHECK: fbug 172
 0x0b 0xbf 0xff 0xff
 
-# CHECK: fbl 4194303
+# CHECK: fbl 176
 0x09 0xbf 0xff 0xff
 
-# CHECK: fbul 4194303
+# CHECK: fbul 180
 0x07 0xbf 0xff 0xff
 
-# CHECK: fblg 4194303
+# CHECK: fblg 184
 0x05 0xbf 0xff 0xff
 
-# CHECK: fbne 4194303
+# CHECK: fbne 188
 0x03 0xbf 0xff 0xff
 
-# CHECK: fbe 4194303
+# CHECK: fbe 192
 0x13 0xbf 0xff 0xff
 
-# CHECK: fbue 4194303
+# CHECK: fbue 196
 0x15 0xbf 0xff 0xff
 
-# CHECK: fbge 4194303
+# CHECK: fbge 200
 0x17 0xbf 0xff 0xff
 
-# CHECK: fbuge 4194303
+# CHECK: fbuge 204
 0x19 0xbf 0xff 0xff
 
-# CHECK: fble 4194303
+# CHECK: fble 208
 0x1b 0xbf 0xff 0xff
 
-# CHECK: fbule 4194303
+# CHECK: fbule 212
 0x1d 0xbf 0xff 0xff
 
-# CHECK: fbo 4194303
+# CHECK: fbo 216
 0x1f 0xbf 0xff 0xff
 
-# CHECK: cba 4194303
+# CHECK: cba 220
 0x11 0xff 0xff 0xff
 
-# CHECK: cbn 4194303
+# CHECK: cbn 224
 0x01 0xff 0xff 0xff
 
-# CHECK: cb3 4194303
+# CHECK: cb3 228
 0x0f 0xff 0xff 0xff
 
-# CHECK: cb2 4194303
+# CHECK: cb2 232
 0x0d 0xff 0xff 0xff
 
-# CHECK: cb23 4194303
+# CHECK: cb23 236
 0x0b 0xff 0xff 0xff
 
-# CHECK: cb1 4194303
+# CHECK: cb1 240
 0x09 0xff 0xff 0xff
 
-# CHECK: cb13 4194303
+# CHECK: cb13 244
 0x07 0xff 0xff 0xff
 
-# CHECK: cb12 4194303
+# CHECK: cb12 248
 0x05 0xff 0xff 0xff
 
-# CHECK: cb123 4194303
+# CHECK: cb123 252
 0x03 0xff 0xff 0xff
 
-# CHECK: cb03 4194303
+# CHECK: cb03 256
 0x15 0xff 0xff 0xff
 
-# CHECK: cb02 4194303
+# CHECK: cb02 260
 0x17 0xff 0xff 0xff
 
-# CHECK: cb023 4194303
+# CHECK: cb023 264
 0x19 0xff 0xff 0xff
 
-# CHECK: cb01 4194303
+# CHECK: cb01 268
 0x1b 0xff 0xff 0xff
 
-# CHECK: cb013 4194303
+# CHECK: cb013 272
 0x1d 0xff 0xff 0xff
 
-# CHECK: cb012 4194303
+# CHECK: cb012 276
 0x1f 0xff 0xff 0xff
 
 # CHECK: restore
 0x81 0xe8 0x00 0x00
 
-# CHECK: call 16
+# CHECK: call 304
 0x40 0x00 0x00 0x04
 
 # CHECK: add %g1, -10, %g2
diff --git a/llvm/test/MC/Sparc/Misc/little-endian.s b/llvm/test/MC/Sparc/Misc/little-endian.s
index d02dfd40d195b..d30db6e6aa0d7 100644
--- a/llvm/test/MC/Sparc/Misc/little-endian.s
+++ b/llvm/test/MC/Sparc/Misc/little-endian.s
@@ -13,5 +13,5 @@
         ! ...and that fixups are applied to the correct bytes.
 
         ! CHECK: ba .BB0      ! encoding: [A,A,0b10AAAAAA,0x10]
-        ! CHECK-OBJ: 4: ff ff bf 10  ba 0x3fffff
+        ! CHECK-OBJ: 4: ff ff bf 10  ba 0x0
         ba .BB0
diff --git a/llvm/test/MC/Sparc/Relocations/expr.s b/llvm/test/MC/Sparc/Relocations/expr.s
index 68ea447a226d6..fcde7d6a1d905 100644
--- a/llvm/test/MC/Sparc/Relocations/expr.s
+++ b/llvm/test/MC/Sparc/Relocations/expr.s
@@ -7,7 +7,7 @@
         mov      ((12+3)<<2), %o2
 
         ! CHECK:   ba      symStart+4
-        ! OBJDUMP: ba    0x1
+        ! OBJDUMP: ba    0xc
 symStart:
         b        symStart + 4
 
diff --git a/llvm/test/MC/Sparc/Relocations/relocation.s b/llvm/test/MC/Sparc/Relocations/relocation.s
index 30c2b9409e765..8e632e05def7e 100644
--- a/llvm/test/MC/Sparc/Relocations/relocation.s
+++ b/llvm/test/MC/Sparc/Relocations/relocation.s
@@ -7,9 +7,9 @@
 # ASM:      call local1
 # ASM-NEXT: call undef
 # OBJDUMP:      call 0x14
-# OBJDUMP-NEXT: call 0x0
+# OBJDUMP-NEXT: call 0x4
 # OBJDUMP-NEXT:   R_SPARC_WDISP30 .text1+0x4
-# OBJDUMP-NEXT: call 0x0
+# OBJDUMP-NEXT: call 0x8
 # OBJDUMP-NEXT:   R_SPARC_WDISP30 undef{{$}}
 call local
 call local1
@@ -28,15 +28,15 @@ local:
 
 # ASM:      brz %g1, undef
 # ASM:      brlz %g1, .Ltmp{{.}}-8
-# OBJDUMP:      brz %g1, 0x0
+# OBJDUMP:      brz %g1, 0x14
 # OBJDUMP-NEXT:   R_SPARC_WDISP16 undef
-# OBJDUMP-NEXT: brlz %g1, 0xfffe
-# OBJDUMP-NEXT: bg %icc, 0x0
+# OBJDUMP-NEXT: brlz %g1, 0x10
+# OBJDUMP-NEXT: bg %icc, 0x1c
 # OBJDUMP-NEXT:   R_SPARC_WDISP19 undef
-# OBJDUMP-NEXT: bg %icc, 0x7fffe
-# OBJDUMP-NEXT: cbn 0x0
+# OBJDUMP-NEXT: bg %icc, 0x18
+# OBJDUMP-NEXT: cbn 0x24
 # OBJDUMP-NEXT:   R_SPARC_WDISP22 undef
-# OBJDUMP-NEXT: cbn 0x3ffffe
+# OBJDUMP-NEXT: cbn 0x20
 brz %g1, undef
 brlz %g1, .-8
 bg %icc, undef
diff --git a/llvm/test/MC/Sparc/sparc64-bpr-offset.s b/llvm/test/MC/Sparc/sparc64-bpr-offset.s
index 37453567924f3..3abae6a5b5710 100644
--- a/llvm/test/MC/Sparc/sparc64-bpr-offset.s
+++ b/llvm/test/MC/Sparc/sparc64-bpr-offset.s
@@ -4,12 +4,12 @@
         !! make sure that our offset bits don't trample on other fields.
         !! This is particularly important with backwards branches.
 
-        ! BIN:  0: 02 c8 40 01  	brz %g1, 1
-        ! BIN:  4: 04 c8 40 01  	brlez %g1, 1
-        ! BIN:  8: 06 c8 40 01  	brlz %g1, 1
-        ! BIN:  c: 0a c8 40 01  	brnz %g1, 1
-        ! BIN: 10: 0c c8 40 01  	brgz %g1, 1
-        ! BIN: 14: 0e c8 40 01  	brgez %g1, 1
+        ! BIN:  0: 02 c8 40 01  	brz %g1, 0x4
+        ! BIN:  4: 04 c8 40 01  	brlez %g1, 0x8
+        ! BIN:  8: 06 c8 40 01  	brlz %g1, 0xc
+        ! BIN:  c: 0a c8 40 01  	brnz %g1, 0x10
+        ! BIN: 10: 0c c8 40 01  	brgz %g1, 0x14
+        ! BIN: 14: 0e c8 40 01  	brgez %g1, 0x18
         brz   %g1, .+4
         brlez %g1, .+4
         brlz  %g1, .+4
@@ -17,12 +17,12 @@
         brgz  %g1, .+4
         brgez %g1, .+4
 
-        ! BIN: 18: 02 f8 7f ff  	brz %g1, 65535
-        ! BIN: 1c: 04 f8 7f ff  	brlez %g1, 65535
-        ! BIN: 20: 06 f8 7f ff  	brlz %g1, 65535
-        ! BIN: 24: 0a f8 7f ff  	brnz %g1, 65535
-        ! BIN: 28: 0c f8 7f ff  	brgz %g1, 65535
-        ! BIN: 2c: 0e f8 7f ff  	brgez %g1, 65535
+        ! BIN: 18: 02 f8 7f ff  	brz %g1, 0x14
+        ! BIN: 1c: 04 f8 7f ff  	brlez %g1, 0x18
+        ! BIN: 20: 06 f8 7f ff  	brlz %g1, 0x1c
+        ! BIN: 24: 0a f8 7f ff  	brnz %g1, 0x20
+        ! BIN: 28: 0c f8 7f ff  	brgz %g1, 0x24
+        ! BIN: 2c: 0e f8 7f ff  	brgez %g1, 0x28
         brz   %g1, .-4
         brlez %g1, .-4
         brlz  %g1, .-4

if (PrintBranchImmAsAddress)
O << formatHex(Offset);
else
O << Offset;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the isImm case when PrintBranchImmAsAddress is false, print .+imm or .-imm like PowerPC.

@koachan koachan requested a review from MaskRay May 18, 2025 10:10
@koachan koachan merged commit 21b4059 into llvm:main May 19, 2025
11 checks passed
sivan-shani pushed a commit to sivan-shani/llvm-project that referenced this pull request Jun 3, 2025
…lvm#140340)

Similar to https://reviews.llvm.org/D93241, print target addresses
instead of raw offset values when disassembling branches and calls.

Should fix llvm#122196 and
llvm#139284.
ajaden-codes pushed a commit to Jaddyen/llvm-project that referenced this pull request Jun 6, 2025
…lvm#140340)

Similar to https://reviews.llvm.org/D93241, print target addresses
instead of raw offset values when disassembling branches and calls.

Should fix llvm#122196 and
llvm#139284.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:Sparc mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[SPARC] llvm-objdump seem to mishandle backwards branches
3 participants