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
3738using namespace llvm ;
3839
40+ #define DEBUG_TYPE " M68k-asm-backend"
41+
3942namespace {
4043
4144class M68kAsmBackend : public MCAsmBackend {
45+ bool Allows32BitBranch;
4246
4347public:
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
168222bool 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 {
218279class M68kELFAsmBackend : public M68kAsmBackend {
219280public:
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}
0 commit comments