brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.4 KiB · f67356c Raw
364 lines · cpp
1//===-- MipsInstPrinter.cpp - Convert Mips MCInst to assembly syntax ------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This class prints an Mips MCInst to a .s file.10//11//===----------------------------------------------------------------------===//12 13#include "MipsInstPrinter.h"14#include "Mips.h"15#include "llvm/ADT/StringExtras.h"16#include "llvm/MC/MCAsmInfo.h"17#include "llvm/MC/MCExpr.h"18#include "llvm/MC/MCInst.h"19#include "llvm/MC/MCInstrInfo.h"20#include "llvm/MC/MCSubtargetInfo.h"21#include "llvm/MC/MCSymbol.h"22#include "llvm/Support/ErrorHandling.h"23#include "llvm/Support/raw_ostream.h"24using namespace llvm;25 26#define DEBUG_TYPE "asm-printer"27 28#define PRINT_ALIAS_INSTR29#include "MipsGenAsmWriter.inc"30 31template<unsigned R>32static bool isReg(const MCInst &MI, unsigned OpNo) {33  assert(MI.getOperand(OpNo).isReg() && "Register operand expected.");34  return MI.getOperand(OpNo).getReg() == R;35}36 37const char* Mips::MipsFCCToString(Mips::CondCode CC) {38  switch (CC) {39  case FCOND_F:40  case FCOND_T:   return "f";41  case FCOND_UN:42  case FCOND_OR:  return "un";43  case FCOND_OEQ:44  case FCOND_UNE: return "eq";45  case FCOND_UEQ:46  case FCOND_ONE: return "ueq";47  case FCOND_OLT:48  case FCOND_UGE: return "olt";49  case FCOND_ULT:50  case FCOND_OGE: return "ult";51  case FCOND_OLE:52  case FCOND_UGT: return "ole";53  case FCOND_ULE:54  case FCOND_OGT: return "ule";55  case FCOND_SF:56  case FCOND_ST:  return "sf";57  case FCOND_NGLE:58  case FCOND_GLE: return "ngle";59  case FCOND_SEQ:60  case FCOND_SNE: return "seq";61  case FCOND_NGL:62  case FCOND_GL:  return "ngl";63  case FCOND_LT:64  case FCOND_NLT: return "lt";65  case FCOND_NGE:66  case FCOND_GE:  return "nge";67  case FCOND_LE:68  case FCOND_NLE: return "le";69  case FCOND_NGT:70  case FCOND_GT:  return "ngt";71  }72  llvm_unreachable("Impossible condition code!");73}74 75void MipsInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {76  markup(OS, Markup::Register)77      << '$' << StringRef(getRegisterName(Reg)).lower();78}79 80void MipsInstPrinter::printInst(const MCInst *MI, uint64_t Address,81                                StringRef Annot, const MCSubtargetInfo &STI,82                                raw_ostream &O) {83  switch (MI->getOpcode()) {84  default:85    break;86  case Mips::RDHWR:87  case Mips::RDHWR64:88    O << "\t.set\tpush\n";89    O << "\t.set\tmips32r2\n";90    break;91  case Mips::Save16:92    O << "\tsave\t";93    printSaveRestore(MI, STI, O);94    O << " # 16 bit inst\n";95    return;96  case Mips::SaveX16:97    O << "\tsave\t";98    printSaveRestore(MI, STI, O);99    O << "\n";100    return;101  case Mips::Restore16:102    O << "\trestore\t";103    printSaveRestore(MI, STI, O);104    O << " # 16 bit inst\n";105    return;106  case Mips::RestoreX16:107    O << "\trestore\t";108    printSaveRestore(MI, STI, O);109    O << "\n";110    return;111  }112 113  // Try to print any aliases first.114  if (!printAliasInstr(MI, Address, STI, O) &&115      !printAlias(*MI, Address, STI, O))116    printInstruction(MI, Address, STI, O);117  printAnnotation(O, Annot);118 119  switch (MI->getOpcode()) {120  default:121    break;122  case Mips::RDHWR:123  case Mips::RDHWR64:124    O << "\n\t.set\tpop";125  }126}127 128void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,129                                   const MCSubtargetInfo &STI, raw_ostream &O) {130  const MCOperand &Op = MI->getOperand(OpNo);131  if (Op.isReg()) {132    printRegName(O, Op.getReg());133    return;134  }135 136  if (Op.isImm()) {137    markup(O, Markup::Immediate) << formatImm(Op.getImm());138    return;139  }140 141  assert(Op.isExpr() && "unknown operand kind in printOperand");142  MAI.printExpr(O, *Op.getExpr());143}144 145void MipsInstPrinter::printJumpOperand(const MCInst *MI, unsigned OpNo,146                                       const MCSubtargetInfo &STI,147                                       raw_ostream &O) {148  const MCOperand &Op = MI->getOperand(OpNo);149  if (!Op.isImm())150    return printOperand(MI, OpNo, STI, O);151 152  if (PrintBranchImmAsAddress)153    markup(O, Markup::Immediate) << formatHex(Op.getImm());154  else155    markup(O, Markup::Immediate) << formatImm(Op.getImm());156}157 158void MipsInstPrinter::printBranchOperand(const MCInst *MI, uint64_t Address,159                                         unsigned OpNo,160                                         const MCSubtargetInfo &STI,161                                         raw_ostream &O) {162  const MCOperand &Op = MI->getOperand(OpNo);163  if (!Op.isImm())164    return printOperand(MI, OpNo, STI, O);165 166  if (PrintBranchImmAsAddress) {167    uint64_t Target = Address + Op.getImm();168    if (STI.hasFeature(Mips::FeatureMips32))169      Target &= 0xffffffff;170    else if (STI.hasFeature(Mips::FeatureMips16))171      Target &= 0xffff;172    markup(O, Markup::Immediate) << formatHex(Target);173  } else {174    markup(O, Markup::Immediate) << formatImm(Op.getImm());175  }176}177 178template <unsigned Bits, unsigned Offset>179void MipsInstPrinter::printUImm(const MCInst *MI, int opNum,180                                const MCSubtargetInfo &STI, raw_ostream &O) {181  const MCOperand &MO = MI->getOperand(opNum);182  if (MO.isImm()) {183    uint64_t Imm = MO.getImm();184    Imm -= Offset;185    Imm &= (1 << Bits) - 1;186    Imm += Offset;187    markup(O, Markup::Immediate) << formatImm(Imm);188    return;189  }190 191  printOperand(MI, opNum, STI, O);192}193 194void MipsInstPrinter::printMemOperand(const MCInst *MI, int opNum,195                                      const MCSubtargetInfo &STI,196                                      raw_ostream &O) {197  // Load/Store memory operands -- imm($reg)198  // If PIC target the target is loaded as the199  // pattern lw $25,%call16($28)200 201  // opNum can be invalid if instruction had reglist as operand.202  // MemOperand is always last operand of instruction (base + offset).203  switch (MI->getOpcode()) {204  default:205    break;206  case Mips::SWM32_MM:207  case Mips::LWM32_MM:208  case Mips::SWM16_MM:209  case Mips::SWM16_MMR6:210  case Mips::LWM16_MM:211  case Mips::LWM16_MMR6:212    opNum = MI->getNumOperands() - 2;213    break;214  }215 216  WithMarkup M = markup(O, Markup::Memory);217  printOperand(MI, opNum + 1, STI, O);218  O << "(";219  printOperand(MI, opNum, STI, O);220  O << ")";221}222 223void MipsInstPrinter::printMemOperandEA(const MCInst *MI, int opNum,224                                        const MCSubtargetInfo &STI,225                                        raw_ostream &O) {226  // when using stack locations for not load/store instructions227  // print the same way as all normal 3 operand instructions.228  printOperand(MI, opNum, STI, O);229  O << ", ";230  printOperand(MI, opNum + 1, STI, O);231}232 233void MipsInstPrinter::printFCCOperand(const MCInst *MI, int opNum,234                                      const MCSubtargetInfo & /* STI */,235                                      raw_ostream &O) {236  const MCOperand &MO = MI->getOperand(opNum);237  O << MipsFCCToString((Mips::CondCode)MO.getImm());238}239 240void MipsInstPrinter::241printSHFMask(const MCInst *MI, int opNum, raw_ostream &O) {242  llvm_unreachable("TODO");243}244 245bool MipsInstPrinter::printAlias(const char *Str, const MCInst &MI,246                                 uint64_t Address, unsigned OpNo,247                                 const MCSubtargetInfo &STI, raw_ostream &OS,248                                 bool IsBranch) {249  OS << "\t" << Str << "\t";250  if (IsBranch)251    printBranchOperand(&MI, Address, OpNo, STI, OS);252  else253    printOperand(&MI, OpNo, STI, OS);254  return true;255}256 257bool MipsInstPrinter::printAlias(const char *Str, const MCInst &MI,258                                 uint64_t Address, unsigned OpNo0,259                                 unsigned OpNo1, const MCSubtargetInfo &STI,260                                 raw_ostream &OS, bool IsBranch) {261  printAlias(Str, MI, Address, OpNo0, STI, OS, IsBranch);262  OS << ", ";263  if (IsBranch)264    printBranchOperand(&MI, Address, OpNo1, STI, OS);265  else266    printOperand(&MI, OpNo1, STI, OS);267  return true;268}269 270bool MipsInstPrinter::printAlias(const MCInst &MI, uint64_t Address,271                                 const MCSubtargetInfo &STI, raw_ostream &OS) {272  switch (MI.getOpcode()) {273  case Mips::BEQ:274  case Mips::BEQ_MM:275    // beq $zero, $zero, $L2 => b $L2276    // beq $r0, $zero, $L2 => beqz $r0, $L2277    return (isReg<Mips::ZERO>(MI, 0) && isReg<Mips::ZERO>(MI, 1) &&278            printAlias("b", MI, Address, 2, STI, OS, true)) ||279           (isReg<Mips::ZERO>(MI, 1) &&280            printAlias("beqz", MI, Address, 0, 2, STI, OS, true));281  case Mips::BEQ64:282    // beq $r0, $zero, $L2 => beqz $r0, $L2283    return isReg<Mips::ZERO_64>(MI, 1) &&284           printAlias("beqz", MI, Address, 0, 2, STI, OS, true);285  case Mips::BNE:286  case Mips::BNE_MM:287    // bne $r0, $zero, $L2 => bnez $r0, $L2288    return isReg<Mips::ZERO>(MI, 1) &&289           printAlias("bnez", MI, Address, 0, 2, STI, OS, true);290  case Mips::BNE64:291    // bne $r0, $zero, $L2 => bnez $r0, $L2292    return isReg<Mips::ZERO_64>(MI, 1) &&293           printAlias("bnez", MI, Address, 0, 2, STI, OS, true);294  case Mips::BGEZAL:295    // bgezal $zero, $L1 => bal $L1296    return isReg<Mips::ZERO>(MI, 0) &&297           printAlias("bal", MI, Address, 1, STI, OS, true);298  case Mips::BC1T:299    // bc1t $fcc0, $L1 => bc1t $L1300    return isReg<Mips::FCC0>(MI, 0) &&301           printAlias("bc1t", MI, Address, 1, STI, OS, true);302  case Mips::BC1F:303    // bc1f $fcc0, $L1 => bc1f $L1304    return isReg<Mips::FCC0>(MI, 0) &&305           printAlias("bc1f", MI, Address, 1, STI, OS, true);306  case Mips::JALR:307    // jalr $zero, $r1 => jr $r1308    // jalr $ra, $r1 => jalr $r1309    return (isReg<Mips::ZERO>(MI, 0) &&310            printAlias("jr", MI, Address, 1, STI, OS)) ||311           (isReg<Mips::RA>(MI, 0) &&312            printAlias("jalr", MI, Address, 1, STI, OS));313  case Mips::JALR64:314    // jalr $zero, $r1 => jr $r1315    // jalr $ra, $r1 => jalr $r1316    return (isReg<Mips::ZERO_64>(MI, 0) &&317            printAlias("jr", MI, Address, 1, STI, OS)) ||318           (isReg<Mips::RA_64>(MI, 0) &&319            printAlias("jalr", MI, Address, 1, STI, OS));320  case Mips::NOR:321  case Mips::NOR_MM:322  case Mips::NOR_MMR6:323    // nor $r0, $r1, $zero => not $r0, $r1324    return isReg<Mips::ZERO>(MI, 2) &&325           printAlias("not", MI, Address, 0, 1, STI, OS);326  case Mips::NOR64:327    // nor $r0, $r1, $zero => not $r0, $r1328    return isReg<Mips::ZERO_64>(MI, 2) &&329           printAlias("not", MI, Address, 0, 1, STI, OS);330  case Mips::OR:331  case Mips::ADDu:332    // or $r0, $r1, $zero => move $r0, $r1333    // addu $r0, $r1, $zero => move $r0, $r1334    return isReg<Mips::ZERO>(MI, 2) &&335           printAlias("move", MI, Address, 0, 1, STI, OS);336  default:337    return false;338  }339}340 341void MipsInstPrinter::printSaveRestore(const MCInst *MI,342                                       const MCSubtargetInfo &STI,343                                       raw_ostream &O) {344  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {345    if (i != 0) O << ", ";346    if (MI->getOperand(i).isReg())347      printRegName(O, MI->getOperand(i).getReg());348    else349      printUImm<16>(MI, i, STI, O);350  }351}352 353void MipsInstPrinter::printRegisterList(const MCInst *MI, int opNum,354                                        const MCSubtargetInfo & /* STI */,355                                        raw_ostream &O) {356  // - 2 because register List is always first operand of instruction and it is357  // always followed by memory operand (base + offset).358  for (int i = opNum, e = MI->getNumOperands() - 2; i != e; ++i) {359    if (i != opNum)360      O << ", ";361    printRegName(O, MI->getOperand(i).getReg());362  }363}364