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
3739using namespace llvm ;
3840
41+ #define DEBUG_TYPE " M68k-asm-backend"
42+
3943namespace {
4044
4145class M68kAsmBackend : public MCAsmBackend {
46+ bool Allows32BitBranch;
4247
4348public:
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,35 @@ bool M68kAsmBackend::mayNeedRelaxation(const MCInst &Inst,
166225}
167226
168227bool 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" );
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+
177244 // NOTE
178245 // A branch to the immediately following instruction automatically
179246 // uses the 16-bit displacement format because the 8-bit
180247 // 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;
182251}
183252
184253// NOTE Can tblgen help at all here to verify there aren't other instructions
185254// we can relax?
186255void M68kAsmBackend::relaxInstruction (MCInst &Inst,
187256 const MCSubtargetInfo &STI) const {
188- // The only relaxations M68k does is from a 1byte pcrel to a 2byte PCRel.
189257 unsigned RelaxedOp = getRelaxedOpcode (Inst);
190258
191259 if (RelaxedOp == Inst.getOpcode ()) {
@@ -218,8 +286,8 @@ namespace {
218286class M68kELFAsmBackend : public M68kAsmBackend {
219287public:
220288 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) {}
223291
224292 std::unique_ptr<MCObjectTargetWriter>
225293 createObjectTargetWriter () const override {
@@ -235,5 +303,5 @@ MCAsmBackend *llvm::createM68kAsmBackend(const Target &T,
235303 const MCTargetOptions &Options) {
236304 const Triple &TheTriple = STI.getTargetTriple ();
237305 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI (TheTriple.getOS ());
238- return new M68kELFAsmBackend (T, OSABI);
306+ return new M68kELFAsmBackend (T, STI, OSABI);
239307}
0 commit comments