29
29
#include " llvm/MC/MCSectionELF.h"
30
30
#include " llvm/MC/MCSectionMachO.h"
31
31
#include " llvm/MC/MCSubtargetInfo.h"
32
+ #include " llvm/MC/MCValue.h"
32
33
#include " llvm/MC/TargetRegistry.h"
34
+ #include " llvm/Support/Debug.h"
33
35
#include " llvm/Support/ErrorHandling.h"
34
36
#include " llvm/Support/MathExtras.h"
35
37
#include " llvm/Support/raw_ostream.h"
36
38
37
39
using namespace llvm ;
38
40
41
+ #define DEBUG_TYPE " M68k-asm-backend"
42
+
39
43
namespace {
40
44
41
45
class M68kAsmBackend : public MCAsmBackend {
46
+ bool Allows32BitBranch;
42
47
43
48
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 )) {}
45
54
46
55
unsigned getNumFixupKinds () const override { return 0 ; }
47
56
@@ -51,18 +60,34 @@ class M68kAsmBackend : public MCAsmBackend {
51
60
const MCSubtargetInfo *STI) const override {
52
61
unsigned Size = 1 << getFixupKindLog2Size (Fixup.getKind ());
53
62
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
+ }
55
70
56
71
// Check that uppper bits are either all zeros or all ones.
57
72
// Specifically ignore overflow/underflow as long as the leakage is
58
73
// limited to the lower bits. This is to remain compatible with
59
74
// 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
+ }
62
86
63
87
// Write in Big Endian
64
88
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 ));
66
91
}
67
92
68
93
bool mayNeedRelaxation (const MCInst &Inst,
@@ -99,6 +124,8 @@ static unsigned getRelaxedOpcodeBranch(const MCInst &Inst) {
99
124
switch (Op) {
100
125
default :
101
126
return Op;
127
+
128
+ // 8 -> 16
102
129
case M68k::BRA8:
103
130
return M68k::BRA16;
104
131
case M68k::Bcc8:
@@ -129,6 +156,38 @@ static unsigned getRelaxedOpcodeBranch(const MCInst &Inst) {
129
156
return M68k::Ble16;
130
157
case M68k::Bvs8:
131
158
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;
132
191
}
133
192
}
134
193
@@ -166,26 +225,35 @@ bool M68kAsmBackend::mayNeedRelaxation(const MCInst &Inst,
166
225
}
167
226
168
227
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)))
172
232
llvm_unreachable (" Cannot relax the instruction, value does not fit" );
173
- }
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
- //
233
+
234
+ // Relax if the value is too big for a (signed) i8
235
+ // (or signed i16 if 32 bit branches can be used). This means
236
+ // that byte-wide instructions have to matched by default
237
+ unsigned KindLog2Size = getFixupKindLog2Size (Fixup.getKind ());
238
+ bool FixupFieldTooSmall = false ;
239
+ if (!isInt<8 >(Value) && KindLog2Size == 0 )
240
+ FixupFieldTooSmall = true ;
241
+ else if (!isInt<16 >(Value) && KindLog2Size <= 1 )
242
+ FixupFieldTooSmall = true ;
243
+
177
244
// NOTE
178
245
// A branch to the immediately following instruction automatically
179
246
// uses the 16-bit displacement format because the 8-bit
180
247
// displacement field contains $00 (zero offset).
181
- return Value == 0 || !isInt<8 >(Value);
248
+ bool ZeroDisplacementNeedsFixup = Value == 0 && KindLog2Size == 0 ;
249
+
250
+ return ZeroDisplacementNeedsFixup || FixupFieldTooSmall;
182
251
}
183
252
184
253
// NOTE Can tblgen help at all here to verify there aren't other instructions
185
254
// we can relax?
186
255
void M68kAsmBackend::relaxInstruction (MCInst &Inst,
187
256
const MCSubtargetInfo &STI) const {
188
- // The only relaxations M68k does is from a 1byte pcrel to a 2byte PCRel.
189
257
unsigned RelaxedOp = getRelaxedOpcode (Inst);
190
258
191
259
if (RelaxedOp == Inst.getOpcode ()) {
@@ -218,8 +286,8 @@ namespace {
218
286
class M68kELFAsmBackend : public M68kAsmBackend {
219
287
public:
220
288
uint8_t OSABI;
221
- M68kELFAsmBackend (const Target &T, uint8_t OSABI)
222
- : M68kAsmBackend(T), OSABI(OSABI) {}
289
+ M68kELFAsmBackend (const Target &T, const MCSubtargetInfo &STI, uint8_t OSABI)
290
+ : M68kAsmBackend(T, STI ), OSABI(OSABI) {}
223
291
224
292
std::unique_ptr<MCObjectTargetWriter>
225
293
createObjectTargetWriter () const override {
@@ -235,5 +303,5 @@ MCAsmBackend *llvm::createM68kAsmBackend(const Target &T,
235
303
const MCTargetOptions &Options) {
236
304
const Triple &TheTriple = STI.getTargetTriple ();
237
305
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI (TheTriple.getOS ());
238
- return new M68kELFAsmBackend (T, OSABI);
306
+ return new M68kELFAsmBackend (T, STI, OSABI);
239
307
}
0 commit comments