30
30
#include " llvm/MC/MCSectionMachO.h"
31
31
#include " llvm/MC/MCSubtargetInfo.h"
32
32
#include " llvm/MC/TargetRegistry.h"
33
+ #include " llvm/Support/Debug.h"
33
34
#include " llvm/Support/ErrorHandling.h"
34
35
#include " llvm/Support/MathExtras.h"
35
36
#include " llvm/Support/raw_ostream.h"
36
37
37
38
using namespace llvm ;
38
39
40
+ #define DEBUG_TYPE " M68k-asm-backend"
41
+
39
42
namespace {
40
43
41
44
class M68kAsmBackend : public MCAsmBackend {
45
+ bool Allows32BitBranch;
42
46
43
47
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 )) {}
45
53
46
54
unsigned getNumFixupKinds () const override { return 0 ; }
47
55
@@ -51,14 +59,26 @@ class M68kAsmBackend : public MCAsmBackend {
51
59
const MCSubtargetInfo *STI) const override {
52
60
unsigned Size = 1 << getFixupKindLog2Size (Fixup.getKind ());
53
61
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
+ }
55
69
56
70
// Check that uppper bits are either all zeros or all ones.
57
71
// Specifically ignore overflow/underflow as long as the leakage is
58
72
// limited to the lower bits. This is to remain compatible with
59
73
// 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
+ }
62
82
63
83
// Write in Big Endian
64
84
for (unsigned i = 0 ; i != Size; ++i)
@@ -99,6 +119,8 @@ static unsigned getRelaxedOpcodeBranch(const MCInst &Inst) {
99
119
switch (Op) {
100
120
default :
101
121
return Op;
122
+
123
+ // 8 -> 16
102
124
case M68k::BRA8:
103
125
return M68k::BRA16;
104
126
case M68k::Bcc8:
@@ -129,6 +151,38 @@ static unsigned getRelaxedOpcodeBranch(const MCInst &Inst) {
129
151
return M68k::Ble16;
130
152
case M68k::Bvs8:
131
153
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;
132
186
}
133
187
}
134
188
@@ -167,8 +221,7 @@ bool M68kAsmBackend::mayNeedRelaxation(const MCInst &Inst,
167
221
168
222
bool M68kAsmBackend::fixupNeedsRelaxation (const MCFixup &Fixup,
169
223
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))) {
172
225
llvm_unreachable (" Cannot relax the instruction, value does not fit" );
173
226
}
174
227
// 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,
178
231
// A branch to the immediately following instruction automatically
179
232
// uses the 16-bit displacement format because the 8-bit
180
233
// 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;
182
243
}
183
244
184
245
// NOTE Can tblgen help at all here to verify there aren't other instructions
@@ -218,8 +279,8 @@ namespace {
218
279
class M68kELFAsmBackend : public M68kAsmBackend {
219
280
public:
220
281
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) {}
223
284
224
285
std::unique_ptr<MCObjectTargetWriter>
225
286
createObjectTargetWriter () const override {
@@ -235,5 +296,5 @@ MCAsmBackend *llvm::createM68kAsmBackend(const Target &T,
235
296
const MCTargetOptions &Options) {
236
297
const Triple &TheTriple = STI.getTargetTriple ();
237
298
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI (TheTriple.getOS ());
238
- return new M68kELFAsmBackend (T, OSABI);
299
+ return new M68kELFAsmBackend (T, STI, OSABI);
239
300
}
0 commit comments