Skip to content

[MIPS]Initial support for MIPS16 assembly. #108681

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
447 changes: 439 additions & 8 deletions llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp

Large diffs are not rendered by default.

403 changes: 380 additions & 23 deletions llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ bool MipsAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
}
}

// FIXME: Is something similar needed for MIPS16?
bool MipsAsmBackend::isMicroMips(const MCSymbol *Sym) const {
if (const auto *ElfSym = dyn_cast<const MCSymbolELF>(Sym)) {
if (ElfSym->getOther() & ELF::STO_MIPS_MICROMIPS)
Expand Down
54 changes: 27 additions & 27 deletions llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,26 +88,6 @@ void MipsInstPrinter::printInst(const MCInst *MI, uint64_t Address,
O << "\t.set\tpush\n";
O << "\t.set\tmips32r2\n";
break;
case Mips::Save16:
O << "\tsave\t";
printSaveRestore(MI, STI, O);
O << " # 16 bit inst\n";
return;
case Mips::SaveX16:
O << "\tsave\t";
printSaveRestore(MI, STI, O);
O << "\n";
return;
case Mips::Restore16:
O << "\trestore\t";
printSaveRestore(MI, STI, O);
O << " # 16 bit inst\n";
return;
case Mips::RestoreX16:
O << "\trestore\t";
printSaveRestore(MI, STI, O);
O << "\n";
return;
}

// Try to print any aliases first.
Expand Down Expand Up @@ -230,6 +210,27 @@ void MipsInstPrinter::printMemOperandEA(const MCInst *MI, int opNum,
printOperand(MI, opNum + 1, STI, O);
}

void MipsInstPrinter::printPCPseudoReg(const MCInst *MI, int opNum,
const MCSubtargetInfo & /* STI */,
raw_ostream &O) {
// Not a real operand; instead indicates a PC-realtive MIPS16 instruction.
O << "$pc";
}

void MipsInstPrinter::printSPPseudoReg(const MCInst *MI, int opNum,
const MCSubtargetInfo & /* STI */,
raw_ostream &O) {
// Not a real operand; instead indicates an SP-realtive MIPS16 instruction.
O << "$sp";
}

void MipsInstPrinter::printRAPseudoReg(const MCInst *MI, int opNum,
const MCSubtargetInfo & /* STI */,
raw_ostream &O) {
// Not a real operand; instead indicates the MIPS16 instruction accesses RA.
O << "$ra";
}

void MipsInstPrinter::printFCCOperand(const MCInst *MI, int opNum,
const MCSubtargetInfo & /* STI */,
raw_ostream &O) {
Expand Down Expand Up @@ -338,15 +339,14 @@ bool MipsInstPrinter::printAlias(const MCInst &MI, uint64_t Address,
}
}

void MipsInstPrinter::printSaveRestore(const MCInst *MI,
void MipsInstPrinter::printSaveRestore(const MCInst *MI, int opNum,
const MCSubtargetInfo &STI,
raw_ostream &O) {
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
if (i != 0) O << ", ";
if (MI->getOperand(i).isReg())
printRegName(O, MI->getOperand(i).getReg());
else
printUImm<16>(MI, i, STI, O);
for (int i = opNum, e = MI->getNumOperands(); i != e; ++i) {
if (i != opNum)
O << ", ";

printOperand(MI, i, STI, O);
}
}

Expand Down
8 changes: 7 additions & 1 deletion llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ class MipsInstPrinter : public MCInstPrinter {
raw_ostream &O);
void printMemOperandEA(const MCInst *MI, int opNum,
const MCSubtargetInfo &STI, raw_ostream &O);
void printPCPseudoReg(const MCInst *MI, int opNum, const MCSubtargetInfo &STI,
raw_ostream &O);
void printSPPseudoReg(const MCInst *MI, int opNum, const MCSubtargetInfo &STI,
raw_ostream &O);
void printRAPseudoReg(const MCInst *MI, int opNum, const MCSubtargetInfo &STI,
raw_ostream &O);
void printFCCOperand(const MCInst *MI, int opNum, const MCSubtargetInfo &STI,
raw_ostream &O);
void printSHFMask(const MCInst *MI, int opNum, raw_ostream &O);
Expand All @@ -120,7 +126,7 @@ class MipsInstPrinter : public MCInstPrinter {
raw_ostream &OS, bool IsBranch = false);
bool printAlias(const MCInst &MI, uint64_t Address,
const MCSubtargetInfo &STI, raw_ostream &OS);
void printSaveRestore(const MCInst *MI, const MCSubtargetInfo &STI,
void printSaveRestore(const MCInst *MI, int opNum, const MCSubtargetInfo &STI,
raw_ostream &O);
void printRegisterList(const MCInst *MI, int opNum,
const MCSubtargetInfo &STI, raw_ostream &O);
Expand Down
218 changes: 217 additions & 1 deletion llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ void MipsMCCodeEmitter::LowerCompactBranch(MCInst& Inst) const {
Inst.getOperand(1).setReg(RegOp0);
}

bool MipsMCCodeEmitter::isMips16(const MCSubtargetInfo &STI) const {
return STI.hasFeature(Mips::FeatureMips16);
}

bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const {
return STI.hasFeature(Mips::FeatureMicroMips);
}
Expand Down Expand Up @@ -210,7 +214,7 @@ void MipsMCCodeEmitter::encodeInstruction(const MCInst &MI,
IsLittleEndian ? llvm::endianness::little : llvm::endianness::big;
if (Size == 2) {
support::endian::write<uint16_t>(CB, Binary, Endian);
} else if (IsLittleEndian && isMicroMips(STI)) {
} else if (IsLittleEndian && (isMips16(STI) || isMicroMips(STI))) {
support::endian::write<uint16_t>(CB, Binary >> 16, Endian);
support::endian::write<uint16_t>(CB, Binary & 0xffff, Endian);
} else {
Expand Down Expand Up @@ -372,6 +376,42 @@ getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo,
return 0;
}

/// getBranchTargetOpValueMips16 - Return binary encoding of the MIPS16
/// branch target operand. This is for the 16-bit instructions, which
/// do not support relocations.
unsigned MipsMCCodeEmitter::getBranchTargetOpValueMips16(
const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
const MCOperand &MO = MI.getOperand(OpNo);

// If the destination is an immediate, divide by 2.
if (MO.isImm())
return MO.getImm() >> 1;

assert(false &&
"getBranchTargetOpValueMips16 expects only constant immediates");

return 0;
}

/// getBranchTarget16OpValueMips16 - Return binary encoding of the MIPS16
/// branch target operand. If the machine operand requires relocation,
/// record the relocation and return zero.
unsigned MipsMCCodeEmitter::getBranchTarget16OpValueMips16(
const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
const MCOperand &MO = MI.getOperand(OpNo);

// If the destination is an immediate, divide by 2.
if (MO.isImm())
return MO.getImm() >> 1;
// FIXME: This should output a fixup, but MIPS16 fixups are not yet supported.
assert(false &&
"getBranchTarget16OpValueMips16 expects only constant immediates");

return 0;
}

/// getBranchTarget21OpValue - Return binary encoding of the branch
/// target operand. If the machine operand requires relocation,
/// record the relocation and return zero.
Expand Down Expand Up @@ -518,6 +558,21 @@ getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo,
return 0;
}

unsigned MipsMCCodeEmitter::getJumpTargetOpValueMips16(
const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
const MCOperand &MO = MI.getOperand(OpNo);
// If the destination is an immediate, divide by 4.
if (MO.isImm())
return MO.getImm() >> 2;

// FIXME: This should output a fixup, but MIPS16 fixups are not yet supported.
assert(false &&
"getJumpTargetOpValueMips16 expects only constant immediates");

return 0;
}

unsigned MipsMCCodeEmitter::
getUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
Expand Down Expand Up @@ -562,6 +617,58 @@ getUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo,
return 0;
}

unsigned
MipsMCCodeEmitter::getUImm8Lsl2Encoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
const MCOperand &MO = MI.getOperand(OpNo);
if (MO.isImm()) {
unsigned Value = MO.getImm();
return Value >> 2;
}

return 0;
}

unsigned
MipsMCCodeEmitter::getSImm8Lsl3Encoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
const MCOperand &MO = MI.getOperand(OpNo);
if (MO.isImm()) {
unsigned Value = MO.getImm();
return Value >> 3;
}

return 0;
}

unsigned
MipsMCCodeEmitter::getSImm11Lsl1Encoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
const MCOperand &MO = MI.getOperand(OpNo);
if (MO.isImm()) {
unsigned Value = MO.getImm();
return Value >> 1;
}

return 0;
}

unsigned
MipsMCCodeEmitter::getSImm16Lsl1Encoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
const MCOperand &MO = MI.getOperand(OpNo);
if (MO.isImm()) {
unsigned Value = MO.getImm();
return Value >> 1;
}

return 0;
}

unsigned MipsMCCodeEmitter::
getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
Expand Down Expand Up @@ -598,6 +705,7 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
if (Kind == MCExpr::Target) {
const MipsMCExpr *MipsExpr = cast<MipsMCExpr>(Expr);

// FIXME: Need to add MIPS16 fixups to these cases once support is added.
Mips::Fixups FixupKind = Mips::Fixups(0);
switch (MipsExpr->getKind()) {
case MipsMCExpr::MEK_None:
Expand Down Expand Up @@ -737,6 +845,114 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
return getExprOpValue(MO.getExpr(),Fixups, STI);
}

/// Return binary encoding of MIPS16 save and restore operands.
unsigned
MipsMCCodeEmitter::getSaveRestoreEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
union {
struct {
unsigned framesize : 8;
unsigned s1 : 1;
unsigned s0 : 1;
unsigned ra : 1;
unsigned aregs : 4;
unsigned xsregs : 3;
} bits;
unsigned val;
} Encoding;

Encoding.val = 0;

// The number of caller-saved regs for 'aregs' and saved 'xsregs' is
// determined by the largest register number in the list. That is [$4-7] for
// 'aregs' and [$18-23, $30] for 'xsregs'. All other regs below those are
// implicitly handled. For example, reg $6 would also handle regs $4 and $5
// even if they were not called out in the assembly code.
// This is similar for the static registers in 'aregs', but the count is
// determined by the smallest register number. For example, if only reg $4
// were specified, then the other three argument regs would be handled.
unsigned NumAregArgs = 0;
unsigned NumAregStatics = 0;
unsigned NumXsRegs = 0;

// Get saved "$s_" regs (xsregs) and caller-saved argument regs.
while (OpNo < MI.getNumOperands() && MI.getOperand(OpNo).isReg()) {
switch (MI.getOperand(OpNo).getReg()) {
default: {
unsigned RegIdx = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
if (NumXsRegs < (RegIdx - 17))
NumXsRegs = RegIdx - 17;
break;
}
case Mips::A0:
case Mips::A0_64:
if (NumAregArgs < 1)
NumAregArgs = 1;
break;
case Mips::A1:
case Mips::A1_64:
if (NumAregArgs < 2)
NumAregArgs = 2;
break;
case Mips::A2:
case Mips::A2_64:
if (NumAregArgs < 3)
NumAregArgs = 3;
break;
case Mips::A3:
case Mips::A3_64:
NumAregArgs = 4;
break;
case Mips::S0:
case Mips::S0_64:
Encoding.bits.s0 = 1;
break;
case Mips::S1:
case Mips::S1_64:
Encoding.bits.s1 = 1;
break;
case Mips::FP:
case Mips::FP_64:
NumXsRegs = 7;
break;
case Mips::RA:
case Mips::RA_64:
Encoding.bits.ra = 1;
break;
}

++OpNo;
}

// Instruction multiplies framesize value by 8.
Encoding.bits.framesize = MI.getOperand(OpNo).getImm() >> 3;
++OpNo;

// Get static argument regs (ones saved at the end of the callee stack).
while (OpNo < MI.getNumOperands() && MI.getOperand(OpNo).isReg()) {
unsigned RegIdx = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
if (NumAregStatics < (8 - RegIdx))
NumAregStatics = 8 - RegIdx;

++OpNo;
}

// Determine 'aregs' encoding. There are two special cases for when all
// four argument regs are used.
if (NumAregStatics == 4) {
Encoding.bits.aregs = 0b1011;
} else if (NumAregArgs == 4) {
Encoding.bits.aregs = 0b1110;
} else {
Encoding.bits.aregs = (NumAregArgs << 2) | NumAregStatics;
}

Encoding.bits.xsregs = NumXsRegs;

return Encoding.val;
}

/// Return binary encoding of memory related operand.
/// If the offset operand requires relocation, record the relocation.
template <unsigned ShiftAmount>
Expand Down
Loading