diff --git a/llvm/lib/Target/M68k/CMakeLists.txt b/llvm/lib/Target/M68k/CMakeLists.txt --- a/llvm/lib/Target/M68k/CMakeLists.txt +++ b/llvm/lib/Target/M68k/CMakeLists.txt @@ -7,7 +7,6 @@ tablegen(LLVM M68kGenRegisterBank.inc -gen-register-bank) tablegen(LLVM M68kGenInstrInfo.inc -gen-instr-info) tablegen(LLVM M68kGenSubtargetInfo.inc -gen-subtarget) -tablegen(LLVM M68kGenMCCodeBeads.inc -gen-code-beads) tablegen(LLVM M68kGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM M68kGenMCPseudoLowering.inc -gen-pseudo-lowering) tablegen(LLVM M68kGenDAGISel.inc -gen-dag-isel) diff --git a/llvm/lib/Target/M68k/M68kInstrInfo.cpp b/llvm/lib/Target/M68k/M68kInstrInfo.cpp --- a/llvm/lib/Target/M68k/M68kInstrInfo.cpp +++ b/llvm/lib/Target/M68k/M68kInstrInfo.cpp @@ -26,6 +26,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Regex.h" #include @@ -601,40 +602,26 @@ bool M68kInstrInfo::isPCRelRegisterOperandLegal( const MachineOperand &MO) const { assert(MO.isReg()); - const auto *MI = MO.getParent(); - const uint8_t *Beads = M68k::getMCInstrBeads(MI->getOpcode()); - assert(*Beads); - - // Only addressing mode k has (non-pc) register with PCRel - // So we're looking for EA Beads equal to - // `3Bits<011>_1Bit<1>_2Bits<11>` - // FIXME: There is an important caveat and two assumptions - // here: The caveat is that EA encoding always sit on the LSB. - // Where the assumptions are that if there are more than one - // operands, the EA encoding for the source operand always sit - // on the LSB. At the same time, k addressing mode can not be used - // on destination operand. - // The last assumption is kinda dirty so we need to find a way around - // it - const uint8_t EncEAk[3] = {0b011, 0b1, 0b11}; - for (const uint8_t Pat : EncEAk) { - uint8_t Bead = *(Beads++); - if (!Bead) - return false; - switch (Bead & 0xF) { - default: - return false; - case M68kBeads::Bits1: - case M68kBeads::Bits2: - case M68kBeads::Bits3: { - uint8_t Val = (Bead & 0xF0) >> 4; - if (Val != Pat) - return false; - } - } - } - return true; + // Check whether this MO belongs to an instruction with addressing mode 'k', + // Refer to TargetInstrInfo.h for more information about this function. + + const MachineInstr *MI = MO.getParent(); + const unsigned NameIndices = M68kInstrNameIndices[MI->getOpcode()]; + StringRef InstrName(&M68kInstrNameData[NameIndices]); + const unsigned OperandNo = MI->getOperandNo(&MO); + + // If this machine operand is the 2nd operand, then check + // whether the instruction has destination addressing mode 'k'. + if (OperandNo == 1) + return Regex("[A-Z]+(8|16|32)k[a-z](_TC)?$").match(InstrName); + + // If this machine operand is the last one, then check + // whether the instruction has source addressing mode 'k'. + if (OperandNo == MI->getNumExplicitOperands() - 1) + return Regex("[A-Z]+(8|16|32)[a-z]k(_TC)?$").match(InstrName); + + return false; } void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB, diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp --- a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp +++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp @@ -65,26 +65,6 @@ ~M68kMCCodeEmitter() override {} - // TableGen'erated function - const uint8_t *getGenInstrBeads(const MCInst &MI) const { - return M68k::getMCInstrBeads(MI.getOpcode()); - } - - unsigned encodeBits(unsigned ThisByte, uint8_t Bead, const MCInst &MI, - const MCInstrDesc &Desc, uint64_t &Buffer, - unsigned Offset, SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned encodeReg(unsigned ThisByte, uint8_t Bead, const MCInst &MI, - const MCInstrDesc &Desc, uint64_t &Buffer, unsigned Offset, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned encodeImm(unsigned ThisByte, uint8_t Bead, const MCInst &MI, - const MCInstrDesc &Desc, uint64_t &Buffer, unsigned Offset, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - void encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const override; @@ -237,246 +217,6 @@ } } -unsigned M68kMCCodeEmitter::encodeBits(unsigned ThisByte, uint8_t Bead, - const MCInst &MI, - const MCInstrDesc &Desc, - uint64_t &Buffer, unsigned Offset, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const { - unsigned Num = 0; - switch (Bead & 0xF) { - case M68kBeads::Bits1: - Num = 1; - break; - case M68kBeads::Bits2: - Num = 2; - break; - case M68kBeads::Bits3: - Num = 3; - break; - case M68kBeads::Bits4: - Num = 4; - break; - } - unsigned char Val = (Bead & 0xF0) >> 4; - - LLVM_DEBUG(dbgs() << "\tEncodeBits" - << " Num: " << Num << " Val: 0x"); - LLVM_DEBUG(dbgs().write_hex(Val) << "\n"); - - Buffer |= (Val << Offset); - - return Num; -} - -unsigned M68kMCCodeEmitter::encodeReg(unsigned ThisByte, uint8_t Bead, - const MCInst &MI, const MCInstrDesc &Desc, - uint64_t &Buffer, unsigned Offset, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const { - bool DA, Reg; - switch (Bead & 0xF) { - default: - llvm_unreachable("Unrecognized Bead code for register type"); - case M68kBeads::DAReg: - Reg = true; - DA = true; - break; - case M68kBeads::DA: - Reg = false; - DA = true; - break; - case M68kBeads::DReg: - case M68kBeads::Reg: - Reg = true; - DA = false; - break; - } - - unsigned Op = (Bead & 0x70) >> 4; - bool Alt = (Bead & 0x80); - LLVM_DEBUG(dbgs() << "\tEncodeReg" - << " Op: " << Op << ", DA: " << DA << ", Reg: " << Reg - << ", Alt: " << Alt << "\n"); - - auto MIOpIdx = M68k::getLogicalOperandIdx(MI.getOpcode(), Op); - bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL; - - MCOperand MCO; - if (M68kII::hasMultiMIOperands(MI.getOpcode(), Op)) { - if (IsPCRel) { - assert(Alt && - "PCRel addresses use Alt bead register encoding by default"); - MCO = MI.getOperand(MIOpIdx + M68k::PCRelIndex); - } else { - MCO = MI.getOperand(MIOpIdx + (Alt ? M68k::MemIndex : M68k::MemBase)); - } - } else { - assert(!Alt && "You cannot use Alt register with a simple operand"); - MCO = MI.getOperand(MIOpIdx); - } - - unsigned RegNum = MCO.getReg(); - auto RI = Ctx.getRegisterInfo(); - - unsigned Written = 0; - if (Reg) { - uint32_t Val = RI->getEncodingValue(RegNum); - Buffer |= (Val & 7) << Offset; - Offset += 3; - Written += 3; - } - - if (DA) { - Buffer |= (uint64_t)M68kII::isAddressRegister(RegNum) << Offset; - Written++; - } - - return Written; -} - -static unsigned EmitConstant(uint64_t Val, unsigned Size, unsigned Pad, - uint64_t &Buffer, unsigned Offset) { - assert(Size + Offset <= 64 && isUIntN(Size, Val) && "Value does not fit"); - - // Writing Value in host's endianness - Buffer |= (Val & ((1ULL << Size) - 1)) << Offset; - return Size + Pad; -} - -unsigned M68kMCCodeEmitter::encodeImm(unsigned ThisByte, uint8_t Bead, - const MCInst &MI, const MCInstrDesc &Desc, - uint64_t &Buffer, unsigned Offset, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const { - unsigned ThisWord = ThisByte / 2; - unsigned Size = 0; - unsigned Pad = 0; - unsigned FixOffset = 0; - int64_t Addendum = 0; - bool NoExpr = false; - - unsigned Type = Bead & 0xF; - unsigned Op = (Bead & 0x70) >> 4; - bool Alt = (Bead & 0x80); - - auto MIOpIdx = M68k::getLogicalOperandIdx(MI.getOpcode(), Op); - bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL; - - // The PC value upon instruction reading of a short jump will point to the - // next instruction, thus we need to compensate 2 bytes, which is the diff - // between the patch point and the PC. - if (IsPCRel && ThisWord == 0) - Addendum -= 2; - - switch (Type) { - // ??? what happens if it is not byte aligned - // ??? is it even possible - case M68kBeads::Disp8: - Size = 8; - Pad = 0; - FixOffset = ThisByte + 1; - Addendum += 1; - break; - case M68kBeads::Imm8: - Size = 8; - Pad = 8; - FixOffset = ThisByte; - break; - case M68kBeads::Imm16: - Size = 16; - Pad = 0; - FixOffset = ThisByte; - break; - case M68kBeads::Imm32: - Size = 32; - Pad = 0; - FixOffset = ThisByte; - break; - case M68kBeads::Imm3: - Size = 3; - Pad = 0; - NoExpr = true; - break; - } - - LLVM_DEBUG(dbgs() << "\tEncodeImm" - << " Op: " << Op << ", Size: " << Size << ", Alt: " << Alt - << "\n"); - - MCOperand MCO; - if (M68kII::hasMultiMIOperands(MI.getOpcode(), Op)) { - - if (IsPCRel) { - assert(!Alt && "You cannot use ALT operand with PCRel"); - MCO = MI.getOperand(MIOpIdx + M68k::PCRelDisp); - } else { - MCO = MI.getOperand(MIOpIdx + (Alt ? M68k::MemOuter : M68k::MemDisp)); - } - - if (MCO.isExpr()) { - assert(!NoExpr && "Cannot use expression here"); - const MCExpr *Expr = MCO.getExpr(); - - // This only makes sense for PCRel instructions since PC points to the - // extension word and Disp8 for example is right justified and requires - // correction. E.g. R_68K_PC32 is calculated as S + A - P, P for Disp8 - // will be EXTENSION_WORD + 1 thus we need to have A equal to 1 to - // compensate. - // TODO count extension words - if (IsPCRel && Addendum != 0) { - Expr = MCBinaryExpr::createAdd( - Expr, MCConstantExpr::create(Addendum, Ctx), Ctx); - } - - Fixups.push_back(MCFixup::create( - FixOffset, Expr, getFixupForSize(Size, IsPCRel), MI.getLoc())); - // Write zeros - return EmitConstant(0, Size, Pad, Buffer, Offset); - } - - } else { - MCO = MI.getOperand(MIOpIdx); - if (MCO.isExpr()) { - assert(!NoExpr && "Cannot use expression here"); - const MCExpr *Expr = MCO.getExpr(); - - if (Addendum != 0) { - Expr = MCBinaryExpr::createAdd( - Expr, MCConstantExpr::create(Addendum, Ctx), Ctx); - } - - Fixups.push_back(MCFixup::create( - FixOffset, Expr, getFixupForSize(Size, IsPCRel), MI.getLoc())); - // Write zeros - return EmitConstant(0, Size, Pad, Buffer, Offset); - } - } - - int64_t I = MCO.getImm(); - - // Store 8 as 0, thus making range 1-8 - if (Type == M68kBeads::Imm3 && Alt) { - assert(I && "Cannot encode Alt Imm3 zero value"); - I %= 8; - } else { - assert(isIntN(Size, I)); - } - - uint64_t Imm = I; - - // 32 bit Imm requires HI16 first then LO16 - if (Size == 32) { - Offset += EmitConstant((Imm >> 16) & 0xFFFF, 16, Pad, Buffer, Offset); - EmitConstant(Imm & 0xFFFF, 16, Pad, Buffer, Offset); - return Size; - } - - return EmitConstant(Imm & ((1ULL << Size) - 1), Size, Pad, Buffer, Offset); -} - -#include "M68kGenMCCodeBeads.inc" - void M68kMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { @@ -490,79 +230,16 @@ APInt EncodedInst(16, 0U); APInt Scratch(16, 0U); getBinaryCodeForInstr(MI, Fixups, EncodedInst, Scratch, STI); - if (EncodedInst.getBitWidth()) { - LLVM_DEBUG(dbgs() << "Instruction " << MCII.getName(Opcode) << "(" << Opcode - << ") is using the new code emitter\n"); - ArrayRef Data(EncodedInst.getRawData(), - EncodedInst.getNumWords()); - int64_t InstSize = EncodedInst.getBitWidth(); - for (uint64_t Word : Data) { - for (int i = 0; i < 4 && InstSize > 0; ++i, InstSize -= 16) { - support::endian::write(OS, static_cast(Word), - support::big); - Word >>= 16; - } - } - return; - } - - const uint8_t *Beads = getGenInstrBeads(MI); - if (!Beads || !*Beads) { - llvm_unreachable("*** Instruction does not have Beads defined"); - } - uint64_t Buffer = 0; - unsigned Offset = 0; - unsigned ThisByte = 0; - - for (uint8_t Bead = *Beads; Bead; Bead = *++Beads) { - // Check for control beads - if (!(Bead & 0xF)) { - switch (Bead >> 4) { - case M68kBeads::Ignore: - continue; - } - } - - switch (Bead & 0xF) { - default: - llvm_unreachable("Unknown Bead code"); - break; - case M68kBeads::Bits1: - case M68kBeads::Bits2: - case M68kBeads::Bits3: - case M68kBeads::Bits4: - Offset += - encodeBits(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI); - break; - case M68kBeads::DAReg: - case M68kBeads::DA: - case M68kBeads::DReg: - case M68kBeads::Reg: - Offset += - encodeReg(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI); - break; - case M68kBeads::Disp8: - case M68kBeads::Imm8: - case M68kBeads::Imm16: - case M68kBeads::Imm32: - case M68kBeads::Imm3: - Offset += - encodeImm(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI); - break; - } - - // Since M68k is Big Endian we need to rotate each instruction word - while (Offset / 16) { - support::endian::write(OS, Buffer, support::big); - Buffer >>= 16; - Offset -= 16; - ThisByte += 2; + ArrayRef Data(EncodedInst.getRawData(), EncodedInst.getNumWords()); + int64_t InstSize = EncodedInst.getBitWidth(); + for (uint64_t Word : Data) { + for (int i = 0; i < 4 && InstSize > 0; ++i, InstSize -= 16) { + support::endian::write(OS, static_cast(Word), + support::big); + Word >>= 16; } } - - assert(Offset == 0 && "M68k Instructions are % 2 bytes"); - assert((ThisByte && !(ThisByte % 2)) && "M68k Instructions are % 2 bytes"); } MCCodeEmitter *llvm::createM68kMCCodeEmitter(const MCInstrInfo &MCII, diff --git a/llvm/test/CodeGen/M68k/is-pcrel-register-operand-legal.mir b/llvm/test/CodeGen/M68k/is-pcrel-register-operand-legal.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/M68k/is-pcrel-register-operand-legal.mir @@ -0,0 +1,10 @@ +# RUN: llc -O0 -mtriple=m68k -start-after=prologepilog -verify-machineinstrs %s -o - | FileCheck %s + +name: is-pcrel-register-operand-legal +body: | + bb.0.entry: + ; CHECK: move.l (0,%pc,%a0), (%a1) + ; CHECK: move.l (%a0), (0,%pc,%a1) + + MOV32jk $a1, 0, $a0, implicit-def $ccr + MOV32kj 0, $a1, $a0, implicit-def $ccr \ No newline at end of file diff --git a/llvm/utils/TableGen/CMakeLists.txt b/llvm/utils/TableGen/CMakeLists.txt --- a/llvm/utils/TableGen/CMakeLists.txt +++ b/llvm/utils/TableGen/CMakeLists.txt @@ -8,7 +8,6 @@ AsmWriterInst.cpp Attributes.cpp CallingConvEmitter.cpp - CodeBeadsGen.cpp CodeEmitterGen.cpp CodeGenDAGPatterns.cpp CodeGenHwModes.cpp diff --git a/llvm/utils/TableGen/CodeBeadsGen.cpp b/llvm/utils/TableGen/CodeBeadsGen.cpp deleted file mode 100644 --- a/llvm/utils/TableGen/CodeBeadsGen.cpp +++ /dev/null @@ -1,135 +0,0 @@ -//===---------- CodeBeadsGen.cpp - Code Beads Generator -------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// CodeBeads are data fields carrying auxiliary information for instructions. -// -// Under the hood it's simply implemented by a `bits` field (with arbitrary -// length) in each TG instruction description, where this TG backend will -// generate a helper function to access it. -// -// This is especially useful for expressing variable length encoding -// instructions and complex addressing modes. Since in those cases each -// instruction is usually associated with large amount of information like -// addressing mode details used on a specific operand. Instead of retreating to -// ad-hoc methods to figure out these information when encoding an instruction, -// CodeBeads provide a clean table for the instruction encoder to lookup. -//===----------------------------------------------------------------------===// - -#include "CodeGenInstruction.h" -#include "CodeGenTarget.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/TableGen/Error.h" -#include "llvm/TableGen/Record.h" -#include "llvm/TableGen/TableGenBackend.h" -#include -using namespace llvm; - -namespace { - -class CodeBeadsGen { - RecordKeeper &Records; - -public: - CodeBeadsGen(RecordKeeper &R) : Records(R) {} - void run(raw_ostream &OS); -}; - -void CodeBeadsGen::run(raw_ostream &OS) { - CodeGenTarget Target(Records); - std::vector Insts = Records.getAllDerivedDefinitions("Instruction"); - - // For little-endian instruction bit encodings, reverse the bit order - Target.reverseBitsForLittleEndianEncoding(); - - ArrayRef NumberedInstructions = - Target.getInstructionsByEnumValue(); - - // Emit function declaration - OS << "const uint8_t *llvm::" << Target.getInstNamespace(); - OS << "::getMCInstrBeads(unsigned Opcode) {\n"; - - // First, get the maximum bit length among all beads. And do some - // simple validation - unsigned MaxBitLength = 0; - - for (const CodeGenInstruction *CGI : NumberedInstructions) { - Record *R = CGI->TheDef; - if (!R->getValue("Beads")) - continue; - - BitsInit *BI = R->getValueAsBitsInit("Beads"); - if (!BI->isComplete()) { - PrintFatalError(R->getLoc(), "Record `" + R->getName() + - "', bit field 'Beads' is not complete"); - } - - MaxBitLength = std::max(MaxBitLength, BI->getNumBits()); - } - - // Number of bytes - unsigned Parts = MaxBitLength / 8; - - // Emit instruction base values - OS << " static const uint8_t InstBits[][" << Parts << "] = {\n"; - for (const CodeGenInstruction *CGI : NumberedInstructions) { - Record *R = CGI->TheDef; - - if (R->getValueAsString("Namespace") == "TargetOpcode" || - !R->getValue("Beads")) { - OS << "\t{ 0x0 },\t// "; - if (R->getValueAsBit("isPseudo")) - OS << "(Pseudo) "; - OS << R->getName() << "\n"; - continue; - } - - BitsInit *BI = R->getValueAsBitsInit("Beads"); - - // Convert to byte array: - // [dcba] -> [a][b][c][d] - OS << "\t{"; - for (unsigned p = 0; p < Parts; ++p) { - unsigned Right = 8 * p; - unsigned Left = Right + 8; - - uint8_t Value = 0; - for (unsigned i = Right; i != Left; ++i) { - unsigned Shift = i % 8; - if (auto *B = dyn_cast(BI->getBit(i))) { - Value |= (static_cast(B->getValue()) << Shift); - } else { - PrintFatalError(R->getLoc(), "Record `" + R->getName() + - "', bit 'Beads[" + Twine(i) + - "]' is not defined"); - } - } - - if (p) - OS << ','; - OS << " 0x"; - OS.write_hex(Value); - OS << ""; - } - OS << " }," << '\t' << "// " << R->getName() << "\n"; - } - OS << "\t{ 0x0 }\n };\n"; - - // Emit initial function code - OS << " return InstBits[Opcode];\n" - << "}\n\n"; -} - -} // End anonymous namespace - -namespace llvm { - -void EmitCodeBeads(RecordKeeper &RK, raw_ostream &OS) { - emitSourceFileHeader("Machine Code Beads", OS); - CodeBeadsGen(RK).run(OS); -} - -} // namespace llvm diff --git a/llvm/utils/TableGen/TableGen.cpp b/llvm/utils/TableGen/TableGen.cpp --- a/llvm/utils/TableGen/TableGen.cpp +++ b/llvm/utils/TableGen/TableGen.cpp @@ -25,7 +25,6 @@ NullBackend, DumpJSON, GenEmitter, - GenCodeBeads, GenRegisterInfo, GenInstrInfo, GenInstrDocs, @@ -82,8 +81,6 @@ clEnumValN(DumpJSON, "dump-json", "Dump all records as machine-readable JSON"), clEnumValN(GenEmitter, "gen-emitter", "Generate machine code emitter"), - clEnumValN(GenCodeBeads, "gen-code-beads", - "Generate machine code beads"), clEnumValN(GenRegisterInfo, "gen-register-info", "Generate registers and register classes info"), clEnumValN(GenInstrInfo, "gen-instr-info", @@ -164,9 +161,6 @@ case GenEmitter: EmitCodeEmitter(Records, OS); break; - case GenCodeBeads: - EmitCodeBeads(Records, OS); - break; case GenRegisterInfo: EmitRegisterInfo(Records, OS); break; diff --git a/llvm/utils/TableGen/TableGenBackends.h b/llvm/utils/TableGen/TableGenBackends.h --- a/llvm/utils/TableGen/TableGenBackends.h +++ b/llvm/utils/TableGen/TableGenBackends.h @@ -67,7 +67,6 @@ void EmitAsmWriter(RecordKeeper &RK, raw_ostream &OS); void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS); void EmitCodeEmitter(RecordKeeper &RK, raw_ostream &OS); -void EmitCodeBeads(RecordKeeper &RK, raw_ostream &OS); void EmitDAGISel(RecordKeeper &RK, raw_ostream &OS); void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS); void EmitDisassembler(RecordKeeper &RK, raw_ostream &OS);