Skip to content

Commit

Permalink
[SPARC][MC] Fix encoding of backwards BPr branches
Browse files Browse the repository at this point in the history
Make sure that the upper bits of the offset is placed in bits 20-21 of the
instruction word.

This fixes the encoding of backwards (negative offset) BPr branches.

(Previously, the upper two bits of the offset would overwrite parts of the rs1
field, causing it to branch on the wrong register, with the wrong offset)

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D144012
  • Loading branch information
brad0 committed May 5, 2023
1 parent 38007dd commit 776d50d
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 48 deletions.
19 changes: 10 additions & 9 deletions llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
Expand Up @@ -41,11 +41,14 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
case Sparc::fixup_sparc_br19:
return (Value >> 2) & 0x7ffff;

case Sparc::fixup_sparc_br16_2:
return (Value >> 2) & 0xc000;

case Sparc::fixup_sparc_br16_14:
return (Value >> 2) & 0x3fff;
case Sparc::fixup_sparc_br16: {
// A.3 Branch on Integer Register with Prediction (BPr)
// Inst{21-20} = d16hi;
// Inst{13-0} = d16lo;
unsigned d16hi = (Value >> 16) & 0x3;
unsigned d16lo = (Value >> 2) & 0x3fff;
return (d16hi << 20) | d16lo;
}

case Sparc::fixup_sparc_hix22:
return (~Value >> 10) & 0x3fffff;
Expand Down Expand Up @@ -164,8 +167,7 @@ namespace {
{ "fixup_sparc_call30", 2, 30, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br22", 10, 22, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br19", 13, 19, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br16_2", 10, 2, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br16_14", 18, 14, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br16", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_13", 19, 13, 0 },
{ "fixup_sparc_hi22", 10, 22, 0 },
{ "fixup_sparc_lo10", 22, 10, 0 },
Expand Down Expand Up @@ -211,8 +213,7 @@ namespace {
{ "fixup_sparc_call30", 0, 30, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br22", 0, 22, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br16_2", 20, 2, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br16_14", 0, 14, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br16", 32, 0, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_13", 0, 13, 0 },
{ "fixup_sparc_hi22", 0, 22, 0 },
{ "fixup_sparc_lo10", 0, 10, 0 },
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
Expand Up @@ -62,6 +62,8 @@ unsigned SparcELFObjectWriter::getRelocType(MCContext &Ctx,
case Sparc::fixup_sparc_call30: return ELF::R_SPARC_WDISP30;
case Sparc::fixup_sparc_br22: return ELF::R_SPARC_WDISP22;
case Sparc::fixup_sparc_br19: return ELF::R_SPARC_WDISP19;
case Sparc::fixup_sparc_br16:
return ELF::R_SPARC_WDISP16;
case Sparc::fixup_sparc_pc22: return ELF::R_SPARC_PC22;
case Sparc::fixup_sparc_pc10: return ELF::R_SPARC_PC10;
case Sparc::fixup_sparc_wplt30: return ELF::R_SPARC_WPLT30;
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
Expand Up @@ -26,8 +26,7 @@ namespace llvm {
fixup_sparc_br19,

/// fixup_sparc_bpr - 16-bit fixup for bpr
fixup_sparc_br16_2,
fixup_sparc_br16_14,
fixup_sparc_br16,

/// fixup_sparc_13 - 13-bit fixup
fixup_sparc_13,
Expand Down
6 changes: 2 additions & 4 deletions llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
Expand Up @@ -235,10 +235,8 @@ getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
if (MO.isReg() || MO.isImm())
return getMachineOpValue(MI, MO, Fixups, STI);

Fixups.push_back(MCFixup::create(0, MO.getExpr(),
(MCFixupKind)Sparc::fixup_sparc_br16_2));
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
(MCFixupKind)Sparc::fixup_sparc_br16_14));
Fixups.push_back(
MCFixup::create(0, MO.getExpr(), (MCFixupKind)Sparc::fixup_sparc_br16));

return 0;
}
Expand Down
31 changes: 31 additions & 0 deletions llvm/test/MC/Sparc/sparc64-bpr-offset.s
@@ -0,0 +1,31 @@
! RUN: llvm-mc -arch=sparcv9 -filetype=obj %s | llvm-objdump -d - | FileCheck %s --check-prefix=BIN

!! SPARCv9/SPARC64 BPr branches have different offset encoding from the others,
!! 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
brz %g1, .+4
brlez %g1, .+4
brlz %g1, .+4
brnz %g1, .+4
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
brz %g1, .-4
brlez %g1, .-4
brlz %g1, .-4
brnz %g1, .-4
brgz %g1, .-4
brgez %g1, .-4
55 changes: 22 additions & 33 deletions llvm/test/MC/Sparc/sparc64-ctrl-instructions.s
Expand Up @@ -1150,24 +1150,18 @@
fbne,a,pn %fcc3, .BB0


! CHECK: brz %g1, .BB0 ! encoding: [0x02,0b11AA1000,0b01BBBBBB,B]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2
! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14
! CHECK: brlez %g1, .BB0 ! encoding: [0x04,0b11AA1000,0b01BBBBBB,B]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2
! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14
! CHECK: brlz %g1, .BB0 ! encoding: [0x06,0b11AA1000,0b01BBBBBB,B]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2
! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14
! CHECK: brnz %g1, .BB0 ! encoding: [0x0a,0b11AA1000,0b01BBBBBB,B]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2
! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14
! CHECK: brgz %g1, .BB0 ! encoding: [0x0c,0b11AA1000,0b01BBBBBB,B]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2
! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14
! CHECK: brgez %g1, .BB0 ! encoding: [0x0e,0b11AA1000,0b01BBBBBB,B]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2
! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14
! CHECK: brz %g1, .BB0 ! encoding: [0x02'A',0xc8'A',0x40'A',A]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16
! CHECK: brlez %g1, .BB0 ! encoding: [0x04'A',0xc8'A',0x40'A',A]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16
! CHECK: brlz %g1, .BB0 ! encoding: [0x06'A',0xc8'A',0x40'A',A]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16
! CHECK: brnz %g1, .BB0 ! encoding: [0x0a'A',0xc8'A',0x40'A',A]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16
! CHECK: brgz %g1, .BB0 ! encoding: [0x0c'A',0xc8'A',0x40'A',A]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16
! CHECK: brgez %g1, .BB0 ! encoding: [0x0e'A',0xc8'A',0x40'A',A]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16

brz %g1, .BB0
brlez %g1, .BB0
Expand All @@ -1176,29 +1170,24 @@
brgz %g1, .BB0
brgez %g1, .BB0

! CHECK: brz %g1, .BB0 ! encoding: [0x02,0b11AA1000,0b01BBBBBB,B]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2
! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14
! CHECK: brz %g1, .BB0 ! encoding: [0x02'A',0xc8'A',0x40'A',A]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16
brz,pt %g1, .BB0

! CHECK: brz,a %g1, .BB0 ! encoding: [0x22,0b11AA1000,0b01BBBBBB,B]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2
! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14
! CHECK: brz,a %g1, .BB0 ! encoding: [0x22'A',0xc8'A',0x40'A',A]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16
brz,a %g1, .BB0

! CHECK: brz,a %g1, .BB0 ! encoding: [0x22,0b11AA1000,0b01BBBBBB,B]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2
! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14
! CHECK: brz,a %g1, .BB0 ! encoding: [0x22'A',0xc8'A',0x40'A',A]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16
brz,a,pt %g1, .BB0

! CHECK: brz,pn %g1, .BB0 ! encoding: [0x02,0b11AA0000,0b01BBBBBB,B]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2
! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14
! CHECK: brz,pn %g1, .BB0 ! encoding: [0x02'A',0xc0'A',0x40'A',A]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16
brz,pn %g1, .BB0

! CHECK: brz,a,pn %g1, .BB0 ! encoding: [0x22,0b11AA0000,0b01BBBBBB,B]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2
! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14
! CHECK: brz,a,pn %g1, .BB0 ! encoding: [0x22'A',0xc0'A',0x40'A',A]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16
brz,a,pn %g1, .BB0

! CHECK: movrz %g1, %g2, %g3 ! encoding: [0x87,0x78,0x44,0x02]
Expand Down

0 comments on commit 776d50d

Please sign in to comment.