Skip to content

Commit ea5fef9

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 ea5fef9

File tree

14 files changed

+421
-29
lines changed

14 files changed

+421
-29
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: 86 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,28 @@
2929
#include "llvm/MC/MCSectionELF.h"
3030
#include "llvm/MC/MCSectionMachO.h"
3131
#include "llvm/MC/MCSubtargetInfo.h"
32+
#include "llvm/MC/MCValue.h"
3233
#include "llvm/MC/TargetRegistry.h"
34+
#include "llvm/Support/Debug.h"
3335
#include "llvm/Support/ErrorHandling.h"
3436
#include "llvm/Support/MathExtras.h"
3537
#include "llvm/Support/raw_ostream.h"
3638

3739
using namespace llvm;
3840

41+
#define DEBUG_TYPE "M68k-asm-backend"
42+
3943
namespace {
4044

4145
class M68kAsmBackend : public MCAsmBackend {
46+
bool Allows32BitBranch;
4247

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

4655
unsigned getNumFixupKinds() const override { return 0; }
4756

@@ -51,18 +60,34 @@ class M68kAsmBackend : public MCAsmBackend {
5160
const MCSubtargetInfo *STI) const override {
5261
unsigned Size = 1 << getFixupKindLog2Size(Fixup.getKind());
5362

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

5671
// Check that uppper bits are either all zeros or all ones.
5772
// Specifically ignore overflow/underflow as long as the leakage is
5873
// limited to the lower bits. This is to remain compatible with
5974
// other assemblers.
60-
assert(isIntN(Size * 8 + 1, Value) &&
61-
"Value does not fit in the Fixup field");
75+
if (!(isIntN(Size * 8 + 1, static_cast<int64_t>(Value)) || IsResolved)) {
76+
LLVM_DEBUG(dbgs() << "Fixup.getOffset(): " << Fixup.getOffset() << '\n');
77+
LLVM_DEBUG(dbgs() << "Size: " << Size << '\n');
78+
LLVM_DEBUG(dbgs() << "Data.size(): " << Data.size() << '\n');
79+
LLVM_DEBUG(dbgs() << "Value: " << Value << '\n');
80+
LLVM_DEBUG(dbgs() << "Target: ");
81+
LLVM_DEBUG(Target.print(dbgs()));
82+
LLVM_DEBUG(dbgs() << '\n');
83+
assert(isIntN(Size * 8 + 1, static_cast<int64_t>(Value)) &&
84+
"Value does not fit in the Fixup field");
85+
}
6286

6387
// Write in Big Endian
6488
for (unsigned i = 0; i != Size; ++i)
65-
Data[Fixup.getOffset() + i] = uint8_t(Value >> ((Size - i - 1) * 8));
89+
Data[Fixup.getOffset() + i] =
90+
uint8_t(static_cast<int64_t>(Value) >> ((Size - i - 1) * 8));
6691
}
6792

6893
bool mayNeedRelaxation(const MCInst &Inst,
@@ -99,6 +124,8 @@ static unsigned getRelaxedOpcodeBranch(const MCInst &Inst) {
99124
switch (Op) {
100125
default:
101126
return Op;
127+
128+
// 8 -> 16
102129
case M68k::BRA8:
103130
return M68k::BRA16;
104131
case M68k::Bcc8:
@@ -129,6 +156,38 @@ static unsigned getRelaxedOpcodeBranch(const MCInst &Inst) {
129156
return M68k::Ble16;
130157
case M68k::Bvs8:
131158
return M68k::Bvs16;
159+
160+
// 16 -> 32
161+
case M68k::BRA16:
162+
return M68k::BRA32;
163+
case M68k::Bcc16:
164+
return M68k::Bcc32;
165+
case M68k::Bls16:
166+
return M68k::Bls32;
167+
case M68k::Blt16:
168+
return M68k::Blt32;
169+
case M68k::Beq16:
170+
return M68k::Beq32;
171+
case M68k::Bmi16:
172+
return M68k::Bmi32;
173+
case M68k::Bne16:
174+
return M68k::Bne32;
175+
case M68k::Bge16:
176+
return M68k::Bge32;
177+
case M68k::Bcs16:
178+
return M68k::Bcs32;
179+
case M68k::Bpl16:
180+
return M68k::Bpl32;
181+
case M68k::Bgt16:
182+
return M68k::Bgt32;
183+
case M68k::Bhi16:
184+
return M68k::Bhi32;
185+
case M68k::Bvc16:
186+
return M68k::Bvc32;
187+
case M68k::Ble16:
188+
return M68k::Ble32;
189+
case M68k::Bvs16:
190+
return M68k::Bvs32;
132191
}
133192
}
134193

@@ -166,26 +225,37 @@ bool M68kAsmBackend::mayNeedRelaxation(const MCInst &Inst,
166225
}
167226

168227
bool M68kAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
169-
uint64_t Value) const {
170-
// TODO Newer CPU can use 32 bit offsets, so check for this when ready
171-
if (!isInt<16>(Value)) {
228+
uint64_t UnsignedValue) const {
229+
int64_t Value = static_cast<int64_t>(UnsignedValue);
230+
231+
if (!isInt<32>(Value) || (!Allows32BitBranch && !isInt<16>(Value))) {
172232
llvm_unreachable("Cannot relax the instruction, value does not fit");
173233
}
174-
// Relax if the value is too big for a (signed) i8. This means that byte-wide
175-
// instructions have to matched by default
176-
//
234+
235+
// Relax if the value is too big for a (signed) i8
236+
// (or signed i16 if 32 bit branches can be used). This means
237+
// that byte-wide instructions have to matched by default
238+
unsigned KindLog2Size = getFixupKindLog2Size(Fixup.getKind());
239+
bool FixupFieldTooSmall = false;
240+
if (!isInt<8>(Value) && KindLog2Size == 0) {
241+
FixupFieldTooSmall = true;
242+
} else if (!isInt<16>(Value) && KindLog2Size <= 1) {
243+
FixupFieldTooSmall = true;
244+
}
245+
177246
// NOTE
178247
// A branch to the immediately following instruction automatically
179248
// uses the 16-bit displacement format because the 8-bit
180249
// displacement field contains $00 (zero offset).
181-
return Value == 0 || !isInt<8>(Value);
250+
bool ZeroDisplacementNeedsFixup = Value == 0 && KindLog2Size == 0;
251+
252+
return ZeroDisplacementNeedsFixup || FixupFieldTooSmall;
182253
}
183254

184255
// NOTE Can tblgen help at all here to verify there aren't other instructions
185256
// we can relax?
186257
void M68kAsmBackend::relaxInstruction(MCInst &Inst,
187258
const MCSubtargetInfo &STI) const {
188-
// The only relaxations M68k does is from a 1byte pcrel to a 2byte PCRel.
189259
unsigned RelaxedOp = getRelaxedOpcode(Inst);
190260

191261
if (RelaxedOp == Inst.getOpcode()) {
@@ -218,8 +288,8 @@ namespace {
218288
class M68kELFAsmBackend : public M68kAsmBackend {
219289
public:
220290
uint8_t OSABI;
221-
M68kELFAsmBackend(const Target &T, uint8_t OSABI)
222-
: M68kAsmBackend(T), OSABI(OSABI) {}
291+
M68kELFAsmBackend(const Target &T, const MCSubtargetInfo &STI, uint8_t OSABI)
292+
: M68kAsmBackend(T, STI), OSABI(OSABI) {}
223293

224294
std::unique_ptr<MCObjectTargetWriter>
225295
createObjectTargetWriter() const override {
@@ -235,5 +305,5 @@ MCAsmBackend *llvm::createM68kAsmBackend(const Target &T,
235305
const MCTargetOptions &Options) {
236306
const Triple &TheTriple = STI.getTargetTriple();
237307
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
238-
return new M68kELFAsmBackend(T, OSABI);
308+
return new M68kELFAsmBackend(T, STI, OSABI);
239309
}

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: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
; RUN: llvm-mc -triple=m68k -motorola-integers -filetype=obj --position-independent < %s \
2+
; RUN: | llvm-objdump -d - | FileCheck %s
3+
; RUN: llvm-mc -triple m68k -show-encoding --position-independent %s -o - \
4+
; RUN: | FileCheck -check-prefix=INSTR -check-prefix=FIXUP %s
5+
6+
; CHECK-LABEL: <TIGHT>:
7+
TIGHT:
8+
; CHECK: bra $7f
9+
; INSTR: bra .LBB0_2 ; encoding: [0x60,A]
10+
; FIXUP: fixup A - offset: 1, value: .LBB0_2-1, kind: FK_PCRel_1
11+
bra .LBB0_2
12+
.space 0x7F ; i8::MAX
13+
.LBB0_2:
14+
add.l #0, %d0
15+
rts
16+
17+
; CHECK-LABEL: <RELAXED>:
18+
RELAXED:
19+
; CHECK: bra $82
20+
; INSTR: bra .LBB1_2 ; encoding: [0x60,A]
21+
; FIXUP: fixup A - offset: 1, value: .LBB1_2-1, kind: FK_PCRel_1
22+
bra .LBB1_2
23+
.space 0x80 ; Greater than i8::MAX
24+
.LBB1_2:
25+
add.l #0, %d0
26+
rts
27+
28+
; CHECK-LABEL: <ZERO>:
29+
ZERO:
30+
; CHECK: bra $2
31+
; INSTR: bra .LBB3_1 ; encoding: [0x60,A]
32+
; FIXUP: fixup A - offset: 1, value: .LBB3_1-1, kind: FK_PCRel_1
33+
bra .LBB3_1
34+
.LBB3_1:
35+
add.l #0, %d0
36+
rts
37+
38+
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
; RUN: llvm-mc -triple=m68k --mcpu=M68020 -motorola-integers -filetype=obj --position-independent < %s \
2+
; RUN: | llvm-objdump -d - | FileCheck %s
3+
; RUN: llvm-mc -triple m68k --mcpu=M68020 -show-encoding --position-independent %s -o - \
4+
; RUN: | FileCheck -check-prefix=INSTR -check-prefix=FIXUP %s
5+
6+
; Branch relocations are relaxed as part of object layout, so -show-encoding still
7+
; shows them as 1-byte relocactions
8+
9+
; CHECK-LABEL: <TIGHT>:
10+
TIGHT:
11+
; CHECK: bra $7f
12+
; INSTR: bra .LBB0_2 ; encoding: [0x60,A]
13+
; FIXUP: fixup A - offset: 1, value: .LBB0_2-1, kind: FK_PCRel_1
14+
bra .LBB0_2
15+
.space 0x7F ; i8::MAX
16+
.LBB0_2:
17+
add.l #0, %d0
18+
rts
19+
20+
; CHECK-LABEL: <RELAXED>:
21+
RELAXED:
22+
; CHECK: bra $82
23+
; INSTR: bra .LBB1_2 ; encoding: [0x60,A]
24+
; FIXUP: fixup A - offset: 1, value: .LBB1_2-1, kind: FK_PCRel_1
25+
bra .LBB1_2
26+
.space 0x80 ; Greater than i8::MAX
27+
.LBB1_2:
28+
add.l #0, %d0
29+
rts
30+
31+
; CHECK-LABEL: <RELAXED_32>:
32+
RELAXED_32:
33+
; CHECK: bra $ff
34+
; CHECK-NEXT: 00 00
35+
; CHECK-NEXT: 80 04
36+
; INSTR: bra .LBB2_1 ; encoding: [0x60,A]
37+
; FIXUP: fixup A - offset: 1, value: .LBB2_1-1, kind: FK_PCRel_1
38+
bra .LBB2_1
39+
.space 0x8000 ; Greater than i16::MAX.
40+
.LBB2_1:
41+
add.l #0, %d0
42+
rts
43+
44+
; CHECK-LABEL: <ZERO>:
45+
ZERO:
46+
; CHECK: bra $2
47+
; INSTR: bra .LBB3_1 ; encoding: [0x60,A]
48+
; FIXUP: fixup A - offset: 1, value: .LBB3_1-1, kind: FK_PCRel_1
49+
bra .LBB3_1
50+
.LBB3_1:
51+
add.l #0, %d0
52+
rts
53+

0 commit comments

Comments
 (0)