mirror of
https://github.com/intel/llvm.git
synced 2026-01-21 04:14:03 +08:00
[SPARC][MC] Fix encoding of backwards BPr branches
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
This commit is contained in:
@@ -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;
|
||||
@@ -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 },
|
||||
@@ -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 },
|
||||
@@ -345,9 +346,16 @@ namespace {
|
||||
|
||||
if (Fixup.getKind() >= FirstLiteralRelocationKind)
|
||||
return;
|
||||
MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
|
||||
Value = adjustFixupValue(Fixup.getKind(), Value);
|
||||
if (!Value) return; // Doesn't change encoding.
|
||||
|
||||
// Shift the value into position.
|
||||
if (Endian == support::little)
|
||||
Value <<= Info.TargetOffset;
|
||||
else
|
||||
Value <<= 32 - Info.TargetOffset - Info.TargetSize;
|
||||
|
||||
unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
|
||||
unsigned Offset = Fixup.getOffset();
|
||||
// For each byte of the fragment that the fixup touches, mask in the bits
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
31
llvm/test/MC/Sparc/sparc64-bpr-offset.s
Normal file
31
llvm/test/MC/Sparc/sparc64-bpr-offset.s
Normal file
@@ -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
|
||||
@@ -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
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user