Skip to content

Commit 9400bff

Browse files
committed
[M68k] add 32 bit branch instrs and allow x20 and later CPUs to relax to 32 bit versions
1 parent 2e30df7 commit 9400bff

File tree

6 files changed

+184
-23
lines changed

6 files changed

+184
-23
lines changed

llvm/lib/Target/M68k/M68kInstrControl.td

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ class MxBcc<string cc, Operand TARGET, dag disp_8, dag disp_16_32>
179179
(descend 0b0110, !cast<MxEncCondOp>("MxCC"#cc).Value, disp_8),
180180
disp_16_32
181181
);
182+
183+
let Predicates = !if(!eq(TARGET, MxBrTarget32), [AtLeastM68020], []);
182184
}
183185

184186
foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge",
@@ -190,6 +192,10 @@ foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge",
190192
def B#cc#"16"
191193
: MxBcc<cc, MxBrTarget16, (descend 0b0000, 0b0000),
192194
(operand "$dst", 16, (encoder "encodePCRelImm<16>"))>;
195+
196+
def B#cc#"32"
197+
: MxBcc<cc, MxBrTarget32, (descend 0b1111, 0b1111),
198+
(operand "$dst", 32, (encoder "encodePCRelImm<32>"))>;
193199
}
194200

195201
foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge",
@@ -215,6 +221,8 @@ class MxBra<Operand TARGET, dag disp_8, dag disp_16_32>
215221
(descend 0b0110, 0b0000, disp_8),
216222
disp_16_32
217223
);
224+
225+
let Predicates = !if(!eq(TARGET, MxBrTarget32), [AtLeastM68020], []);
218226
}
219227

220228
def BRA8 : MxBra<MxBrTarget8,
@@ -223,6 +231,10 @@ def BRA8 : MxBra<MxBrTarget8,
223231
def BRA16 : MxBra<MxBrTarget16, (descend 0b0000, 0b0000),
224232
(operand "$dst", 16, (encoder "encodePCRelImm<16>"))>;
225233

234+
def BRA32 : MxBra<MxBrTarget32, (descend 0b1111, 0b1111),
235+
(operand "$dst", 32, (encoder "encodePCRelImm<32>"),
236+
(decoder "DecodeImm32"))>;
237+
226238
def : Pat<(br bb:$target), (BRA8 MxBrTarget8:$target)>;
227239

228240
/// -------------------------------------------------
@@ -242,6 +254,7 @@ class MxBsr<Operand TARGET, MxType TYPE, dag disp_8, dag disp_16_32>
242254
(descend 0b0110, 0b0001, disp_8),
243255
disp_16_32
244256
);
257+
let Predicates = !if(!eq(TARGET, MxBrTarget32), [AtLeastM68020], []);
245258
}
246259

247260
def BSR8 : MxBsr<MxBrTarget8, MxType8,

llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,26 @@
3030
#include "llvm/MC/MCSectionMachO.h"
3131
#include "llvm/MC/MCSubtargetInfo.h"
3232
#include "llvm/MC/TargetRegistry.h"
33+
#include "llvm/Support/Debug.h"
3334
#include "llvm/Support/ErrorHandling.h"
3435
#include "llvm/Support/MathExtras.h"
3536
#include "llvm/Support/raw_ostream.h"
3637

3738
using namespace llvm;
3839

40+
#define DEBUG_TYPE "M68k-asm-backend"
41+
3942
namespace {
4043

4144
class M68kAsmBackend : public MCAsmBackend {
45+
bool Allows32BitBranch;
4246

4347
public:
44-
M68kAsmBackend(const Target &T) : MCAsmBackend(llvm::endianness::big) {}
48+
M68kAsmBackend(const Target &T, const MCSubtargetInfo &STI)
49+
: MCAsmBackend(llvm::endianness::big),
50+
Allows32BitBranch(llvm::StringSwitch<bool>(STI.getCPU())
51+
.CasesLower("m68020", "m68030", "m68040", true)
52+
.Default(false)) {}
4553

4654
unsigned getNumFixupKinds() const override { return 0; }
4755

@@ -51,14 +59,26 @@ class M68kAsmBackend : public MCAsmBackend {
5159
const MCSubtargetInfo *STI) const override {
5260
unsigned Size = 1 << getFixupKindLog2Size(Fixup.getKind());
5361

54-
assert(Fixup.getOffset() + Size <= Data.size() && "Invalid fixup offset!");
62+
if (Fixup.getOffset() + Size > Data.size()) {
63+
LLVM_DEBUG(dbgs() << "Fixup.getOffset(): " << Fixup.getOffset() << '\n');
64+
LLVM_DEBUG(dbgs() << "Size: " << Size << '\n');
65+
LLVM_DEBUG(dbgs() << "Data.size(): " << Data.size() << '\n');
66+
assert(Fixup.getOffset() + Size <= Data.size() &&
67+
"Invalid fixup offset!");
68+
}
5569

5670
// Check that uppper bits are either all zeros or all ones.
5771
// Specifically ignore overflow/underflow as long as the leakage is
5872
// limited to the lower bits. This is to remain compatible with
5973
// other assemblers.
60-
assert(isIntN(Size * 8 + 1, Value) &&
61-
"Value does not fit in the Fixup field");
74+
if (!isIntN(Size * 8 + 1, Value)) {
75+
LLVM_DEBUG(dbgs() << "Fixup.getOffset(): " << Fixup.getOffset() << '\n');
76+
LLVM_DEBUG(dbgs() << "Size: " << Size << '\n');
77+
LLVM_DEBUG(dbgs() << "Data.size(): " << Data.size() << '\n');
78+
LLVM_DEBUG(dbgs() << "Value: " << Value << '\n');
79+
assert(isIntN(Size * 8 + 1, Value) &&
80+
"Value does not fit in the Fixup field");
81+
}
6282

6383
// Write in Big Endian
6484
for (unsigned i = 0; i != Size; ++i)
@@ -99,6 +119,8 @@ static unsigned getRelaxedOpcodeBranch(const MCInst &Inst) {
99119
switch (Op) {
100120
default:
101121
return Op;
122+
123+
// 8 -> 16
102124
case M68k::BRA8:
103125
return M68k::BRA16;
104126
case M68k::Bcc8:
@@ -129,6 +151,38 @@ static unsigned getRelaxedOpcodeBranch(const MCInst &Inst) {
129151
return M68k::Ble16;
130152
case M68k::Bvs8:
131153
return M68k::Bvs16;
154+
155+
// 16 -> 32
156+
case M68k::BRA16:
157+
return M68k::BRA32;
158+
case M68k::Bcc16:
159+
return M68k::Bcc32;
160+
case M68k::Bls16:
161+
return M68k::Bls32;
162+
case M68k::Blt16:
163+
return M68k::Blt32;
164+
case M68k::Beq16:
165+
return M68k::Beq32;
166+
case M68k::Bmi16:
167+
return M68k::Bmi32;
168+
case M68k::Bne16:
169+
return M68k::Bne32;
170+
case M68k::Bge16:
171+
return M68k::Bge32;
172+
case M68k::Bcs16:
173+
return M68k::Bcs32;
174+
case M68k::Bpl16:
175+
return M68k::Bpl32;
176+
case M68k::Bgt16:
177+
return M68k::Bgt32;
178+
case M68k::Bhi16:
179+
return M68k::Bhi32;
180+
case M68k::Bvc16:
181+
return M68k::Bvc32;
182+
case M68k::Ble16:
183+
return M68k::Ble32;
184+
case M68k::Bvs16:
185+
return M68k::Bvs32;
132186
}
133187
}
134188

@@ -167,8 +221,7 @@ bool M68kAsmBackend::mayNeedRelaxation(const MCInst &Inst,
167221

168222
bool M68kAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
169223
uint64_t Value) const {
170-
// TODO Newer CPU can use 32 bit offsets, so check for this when ready
171-
if (!isInt<16>(Value)) {
224+
if (!isInt<32>(Value) || (!Allows32BitBranch && !isInt<16>(Value))) {
172225
llvm_unreachable("Cannot relax the instruction, value does not fit");
173226
}
174227
// Relax if the value is too big for a (signed) i8. This means that byte-wide
@@ -178,7 +231,15 @@ bool M68kAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
178231
// A branch to the immediately following instruction automatically
179232
// uses the 16-bit displacement format because the 8-bit
180233
// displacement field contains $00 (zero offset).
181-
return Value == 0 || !isInt<8>(Value);
234+
unsigned int KindLog2Size = getFixupKindLog2Size(Fixup.getKind());
235+
bool FixupFieldTooSmall = false;
236+
if (!isInt<8>(Value) && KindLog2Size == 0) {
237+
FixupFieldTooSmall |= true;
238+
} else if (!isInt<16>(Value) && KindLog2Size <= 1) {
239+
FixupFieldTooSmall |= true;
240+
}
241+
242+
return Value == 0 || FixupFieldTooSmall;
182243
}
183244

184245
// NOTE Can tblgen help at all here to verify there aren't other instructions
@@ -218,8 +279,8 @@ namespace {
218279
class M68kELFAsmBackend : public M68kAsmBackend {
219280
public:
220281
uint8_t OSABI;
221-
M68kELFAsmBackend(const Target &T, uint8_t OSABI)
222-
: M68kAsmBackend(T), OSABI(OSABI) {}
282+
M68kELFAsmBackend(const Target &T, const MCSubtargetInfo &STI, uint8_t OSABI)
283+
: M68kAsmBackend(T, STI), OSABI(OSABI) {}
223284

224285
std::unique_ptr<MCObjectTargetWriter>
225286
createObjectTargetWriter() const override {
@@ -235,5 +296,5 @@ MCAsmBackend *llvm::createM68kAsmBackend(const Target &T,
235296
const MCTargetOptions &Options) {
236297
const Triple &TheTriple = STI.getTargetTriple();
237298
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
238-
return new M68kELFAsmBackend(T, OSABI);
299+
return new M68kELFAsmBackend(T, STI, OSABI);
239300
}

llvm/test/MC/M68k/Control/bsr.s

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88
; CHECK-SAME: encoding: [0x61,0x00,A,A]
99
; CHECK: fixup A - offset: 2, value: .LBB0_2, kind: FK_PCRel_2
1010
bsr.w .LBB0_2
11-
; CHECK: bsr.l .LBB0_3
12-
; CHECK-SAME: encoding: [0x61,0xff,A,A,A,A]
13-
; CHECK: fixup A - offset: 2, value: .LBB0_3, kind: FK_PCRel_4
14-
bsr.l .LBB0_3
1511
.LBB0_1:
1612
; CHECK: add.l #0, %d0
1713
; CHECK-SAME: encoding: [0xd0,0xbc,0x00,0x00,0x00,0x00]
@@ -26,10 +22,3 @@
2622
; CHECK: rts
2723
; CHECK-SAME: encoding: [0x4e,0x75]
2824
rts
29-
.LBB0_3:
30-
; CHECK: add.l #1, %d0
31-
; CHECK-SAME: encoding: [0xd0,0xbc,0x00,0x00,0x00,0x01]
32-
add.l #1, %d0
33-
; CHECK: rts
34-
; CHECK-SAME: encoding: [0x4e,0x75]
35-
rts

llvm/test/MC/M68k/Control/bsr32.s

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
; RUN: llvm-mc -triple=m68k --mcpu=M68020 -show-encoding %s | FileCheck %s
2+
3+
; CHECK: bsr.b .LBB0_1
4+
; CHECK-SAME: encoding: [0x61,A]
5+
; CHECK: fixup A - offset: 1, value: .LBB0_1-1, kind: FK_PCRel_1
6+
bsr.b .LBB0_1
7+
; CHECK: bsr.w .LBB0_2
8+
; CHECK-SAME: encoding: [0x61,0x00,A,A]
9+
; CHECK: fixup A - offset: 2, value: .LBB0_2, kind: FK_PCRel_2
10+
bsr.w .LBB0_2
11+
; CHECK: bsr.l .LBB0_3
12+
; CHECK-SAME: encoding: [0x61,0xff,A,A,A,A]
13+
; CHECK: fixup A - offset: 2, value: .LBB0_3, kind: FK_PCRel_4
14+
bsr.l .LBB0_3
15+
.LBB0_1:
16+
; CHECK: add.l #0, %d0
17+
; CHECK-SAME: encoding: [0xd0,0xbc,0x00,0x00,0x00,0x00]
18+
add.l #0, %d0
19+
; CHECK: rts
20+
; CHECK-SAME: encoding: [0x4e,0x75]
21+
rts
22+
.LBB0_2:
23+
; CHECK: add.l #1, %d0
24+
; CHECK-SAME: encoding: [0xd0,0xbc,0x00,0x00,0x00,0x01]
25+
add.l #1, %d0
26+
; CHECK: rts
27+
; CHECK-SAME: encoding: [0x4e,0x75]
28+
rts
29+
.LBB0_3:
30+
; CHECK: add.l #1, %d0
31+
; CHECK-SAME: encoding: [0xd0,0xbc,0x00,0x00,0x00,0x01]
32+
add.l #1, %d0
33+
; CHECK: rts
34+
; CHECK-SAME: encoding: [0x4e,0x75]
35+
rts
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
; RUN: llvm-mc -triple=m68k --mcpu=M68020 -motorola-integers -filetype=obj < %s \
2+
; RUN: | llvm-objdump -d - | FileCheck %s
3+
4+
; CHECK-LABEL: <TIGHT>:
5+
TIGHT:
6+
; CHECK: bra $78
7+
bra .LBB0_2
8+
move.l $0, $0
9+
move.l $0, $0
10+
move.l $0, $0
11+
move.l $0, $0
12+
move.l $0, $0
13+
move.l $0, $0
14+
move.l $0, $0
15+
move.l $0, $0
16+
move.l $0, $0
17+
move.l $0, $0
18+
move.l $0, $0
19+
move.l $0, $0
20+
.LBB0_2:
21+
add.l #0, %d0
22+
rts
23+
24+
; CHECK-LABEL: <RELAXED>:
25+
RELAXED:
26+
; CHECK: bra $84
27+
bra .LBB1_2
28+
move.l $0, $0
29+
move.l $0, $0
30+
move.l $0, $0
31+
move.l $0, $0
32+
move.l $0, $0
33+
move.l $0, $0
34+
move.l $0, $0
35+
move.l $0, $0
36+
move.l $0, $0
37+
move.l $0, $0
38+
move.l $0, $0
39+
move.l $0, $0
40+
move.l $0, $0
41+
.LBB1_2:
42+
add.l #0, %d0
43+
rts
44+
45+
; CHECK-LABEL: <RELAXED_32>:
46+
RELAXED_32:
47+
; CHECK: bra $ff
48+
; CHECK-NEXT: 00 02
49+
; CHECK-NEXT: 00 00
50+
bra .LBB3_1
51+
.space 0x20000 ; Greater than u16::MAX.
52+
.LBB2_1:
53+
add.l #0, %d0
54+
rts
55+
56+
; CHECK-LABEL: <ZERO>:
57+
ZERO:
58+
; CHECK: bra $2
59+
bra .LBB3_1
60+
.LBB3_1:
61+
add.l #0, %d0
62+
rts
63+

llvm/test/MC/M68k/Relocations/text-plt.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
; RUN: llvm-mc -triple m68k -filetype=obj %s -o - \
1+
; RUN: llvm-mc -triple m68k --mcpu=M68020 -filetype=obj %s -o - \
22
; RUN: | llvm-readobj -r - | FileCheck -check-prefix=RELOC %s
3-
; RUN: llvm-mc -triple m68k -show-encoding %s -o - \
3+
; RUN: llvm-mc -triple m68k --mcpu=M68020 -show-encoding %s -o - \
44
; RUN: | FileCheck -check-prefix=INSTR -check-prefix=FIXUP %s
55

66
; RELOC: R_68K_PLT16 target 0x0

0 commit comments

Comments
 (0)