442 lines · cpp
1//===- XtensaInstPrinter.cpp - Convert Xtensa MCInst to asm syntax --------===//2//3// The LLVM Compiler Infrastructure4//5// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.6// See https://llvm.org/LICENSE.txt for license information.7// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception8//9//===----------------------------------------------------------------------===//10//11// This class prints an Xtensa MCInst to a .s file.12//13//===----------------------------------------------------------------------===//14 15#include "XtensaInstPrinter.h"16#include "MCTargetDesc/XtensaMCAsmInfo.h"17#include "llvm/CodeGen/MachineOperand.h"18#include "llvm/MC/MCAsmInfo.h"19#include "llvm/MC/MCExpr.h"20#include "llvm/MC/MCInstrInfo.h"21#include "llvm/MC/MCRegister.h"22#include "llvm/MC/MCSymbol.h"23#include "llvm/Support/Casting.h"24#include "llvm/Support/raw_ostream.h"25 26using namespace llvm;27 28#define DEBUG_TYPE "asm-printer"29 30#include "XtensaGenAsmWriter.inc"31 32static void printExpr(const MCExpr *Expr, raw_ostream &OS) {33 int Offset = 0;34 const MCSymbolRefExpr *SRE;35 36 if (!(SRE = cast<MCSymbolRefExpr>(Expr)))37 assert(false && "Unexpected MCExpr type.");38 39 assert(SRE->getSpecifier() == 0);40 41 OS << SRE->getSymbol();42 43 if (Offset) {44 if (Offset > 0)45 OS << '+';46 OS << Offset;47 }48}49 50void XtensaInstPrinter::printOperand(const MCOperand &MC, raw_ostream &O) {51 if (MC.isReg())52 O << getRegisterName(MC.getReg());53 else if (MC.isImm())54 O << MC.getImm();55 else if (MC.isExpr())56 printExpr(MC.getExpr(), O);57 else58 report_fatal_error("Invalid operand");59}60 61void XtensaInstPrinter::printInst(const MCInst *MI, uint64_t Address,62 StringRef Annot, const MCSubtargetInfo &STI,63 raw_ostream &O) {64 printInstruction(MI, Address, O);65 printAnnotation(O, Annot);66}67 68void XtensaInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) {69 O << getRegisterName(Reg);70}71 72void XtensaInstPrinter::printOperand(const MCInst *MI, int OpNum,73 raw_ostream &O) {74 printOperand(MI->getOperand(OpNum), O);75}76 77void XtensaInstPrinter::printMemOperand(const MCInst *MI, int OpNum,78 raw_ostream &OS) {79 OS << getRegisterName(MI->getOperand(OpNum).getReg());80 OS << ", ";81 printOperand(MI, OpNum + 1, OS);82}83 84void XtensaInstPrinter::printBranchTarget(const MCInst *MI, uint64_t Address,85 int OpNum, raw_ostream &O) {86 const MCOperand &MC = MI->getOperand(OpNum);87 if (MI->getOperand(OpNum).isImm()) {88 int64_t Val = MC.getImm() + 4;89 printPCRelImm(Address, Val, O);90 } else if (MC.isExpr())91 MAI.printExpr(O, *MC.getExpr());92 else93 llvm_unreachable("Invalid operand");94}95 96void XtensaInstPrinter::printLoopTarget(const MCInst *MI, uint64_t Address,97 int OpNum, raw_ostream &O) {98 const MCOperand &MC = MI->getOperand(OpNum);99 if (MI->getOperand(OpNum).isImm()) {100 int64_t Val = MC.getImm() + 4;101 printPCRelImm(Address, Val, O);102 } else if (MC.isExpr())103 MAI.printExpr(O, *MC.getExpr());104 else105 llvm_unreachable("Invalid operand");106}107 108void XtensaInstPrinter::printJumpTarget(const MCInst *MI, uint64_t Address,109 int OpNum, raw_ostream &O) {110 const MCOperand &MC = MI->getOperand(OpNum);111 if (MC.isImm()) {112 int64_t Val = MC.getImm() + 4;113 printPCRelImm(Address, Val, O);114 } else if (MC.isExpr())115 MAI.printExpr(O, *MC.getExpr());116 else117 llvm_unreachable("Invalid operand");118 ;119}120 121void XtensaInstPrinter::printCallOperand(const MCInst *MI, uint64_t Address,122 int OpNum, raw_ostream &O) {123 const MCOperand &MC = MI->getOperand(OpNum);124 if (MC.isImm()) {125 int64_t Val = MC.getImm() + 4;126 if (PrintBranchImmAsAddress) {127 uint64_t Target = Address;128 Target &= ~0x3;129 Target += Val & (~0x3);130 O << formatHex(Target);131 } else {132 O << ". ";133 if (Val > 0)134 O << '+';135 O << Val;136 }137 } else if (MC.isExpr())138 MAI.printExpr(O, *MC.getExpr());139 else140 llvm_unreachable("Invalid operand");141}142 143void XtensaInstPrinter::printL32RTarget(const MCInst *MI, uint64_t Address,144 int OpNum, raw_ostream &O) {145 const MCOperand &MC = MI->getOperand(OpNum);146 if (MC.isImm()) {147 int64_t Value = MI->getOperand(OpNum).getImm();148 if (PrintBranchImmAsAddress) {149 uint64_t Target = (Address + 0x3) & (~0x3);150 Value &= ~0x3;151 Target += Value;152 O << formatHex(Target);153 } else {154 int64_t InstrOff = Value & 0x3;155 Value -= InstrOff;156 assert((Value >= -262144 && Value <= -4) &&157 "Invalid argument, value must be in ranges [-262144,-4]");158 Value += ((InstrOff + 0x3) & 0x4) - InstrOff;159 printPCRelImm(Address, Value, O);160 }161 } else if (MC.isExpr())162 MAI.printExpr(O, *MC.getExpr());163 else164 llvm_unreachable("Invalid operand");165}166 167void XtensaInstPrinter::printPCRelImm(uint64_t Address, int64_t Offset,168 raw_ostream &O) {169 if (PrintBranchImmAsAddress) {170 uint64_t Target = Address + Offset;171 Target &= 0xffffffff;172 O << formatHex(Target);173 } else {174 O << ". ";175 if (Offset > 0)176 O << '+';177 O << Offset;178 }179}180 181void XtensaInstPrinter::printImm8_AsmOperand(const MCInst *MI, int OpNum,182 raw_ostream &O) {183 if (MI->getOperand(OpNum).isImm()) {184 int64_t Value = MI->getOperand(OpNum).getImm();185 assert(isInt<8>(Value) &&186 "Invalid argument, value must be in ranges [-128,127]");187 O << Value;188 } else {189 printOperand(MI, OpNum, O);190 }191}192 193void XtensaInstPrinter::printImm8_sh8_AsmOperand(const MCInst *MI, int OpNum,194 raw_ostream &O) {195 if (MI->getOperand(OpNum).isImm()) {196 int64_t Value = MI->getOperand(OpNum).getImm();197 assert((isInt<16>(Value) && ((Value & 0xFF) == 0)) &&198 "Invalid argument, value must be multiples of 256 in range "199 "[-32768,32512]");200 O << Value;201 } else202 printOperand(MI, OpNum, O);203}204 205void XtensaInstPrinter::printImm12_AsmOperand(const MCInst *MI, int OpNum,206 raw_ostream &O) {207 if (MI->getOperand(OpNum).isImm()) {208 int64_t Value = MI->getOperand(OpNum).getImm();209 assert((Value >= -2048 && Value <= 2047) &&210 "Invalid argument, value must be in ranges [-2048,2047]");211 O << Value;212 } else213 printOperand(MI, OpNum, O);214}215 216void XtensaInstPrinter::printImm12m_AsmOperand(const MCInst *MI, int OpNum,217 raw_ostream &O) {218 if (MI->getOperand(OpNum).isImm()) {219 int64_t Value = MI->getOperand(OpNum).getImm();220 assert((Value >= -2048 && Value <= 2047) &&221 "Invalid argument, value must be in ranges [-2048,2047]");222 O << Value;223 } else224 printOperand(MI, OpNum, O);225}226 227void XtensaInstPrinter::printUimm4_AsmOperand(const MCInst *MI, int OpNum,228 raw_ostream &O) {229 if (MI->getOperand(OpNum).isImm()) {230 int64_t Value = MI->getOperand(OpNum).getImm();231 assert((Value >= 0 && Value <= 15) && "Invalid argument");232 O << Value;233 } else234 printOperand(MI, OpNum, O);235}236 237void XtensaInstPrinter::printUimm5_AsmOperand(const MCInst *MI, int OpNum,238 raw_ostream &O) {239 if (MI->getOperand(OpNum).isImm()) {240 int64_t Value = MI->getOperand(OpNum).getImm();241 assert((Value >= 0 && Value <= 31) && "Invalid argument");242 O << Value;243 } else244 printOperand(MI, OpNum, O);245}246 247void XtensaInstPrinter::printShimm1_31_AsmOperand(const MCInst *MI, int OpNum,248 raw_ostream &O) {249 if (MI->getOperand(OpNum).isImm()) {250 int64_t Value = MI->getOperand(OpNum).getImm();251 assert((Value >= 1 && Value <= 31) &&252 "Invalid argument, value must be in range [1,31]");253 O << Value;254 } else255 printOperand(MI, OpNum, O);256}257 258void XtensaInstPrinter::printImm1_16_AsmOperand(const MCInst *MI, int OpNum,259 raw_ostream &O) {260 if (MI->getOperand(OpNum).isImm()) {261 int64_t Value = MI->getOperand(OpNum).getImm();262 assert((Value >= 1 && Value <= 16) &&263 "Invalid argument, value must be in range [1,16]");264 O << Value;265 } else266 printOperand(MI, OpNum, O);267}268 269void XtensaInstPrinter::printImm1n_15_AsmOperand(const MCInst *MI, int OpNum,270 raw_ostream &O) {271 if (MI->getOperand(OpNum).isImm()) {272 int64_t Value = MI->getOperand(OpNum).getImm();273 assert((Value >= -1 && (Value != 0) && Value <= 15) &&274 "Invalid argument, value must be in ranges <-1,-1> or <1,15>");275 O << Value;276 } else277 printOperand(MI, OpNum, O);278}279 280void XtensaInstPrinter::printImm32n_95_AsmOperand(const MCInst *MI, int OpNum,281 raw_ostream &O) {282 if (MI->getOperand(OpNum).isImm()) {283 int64_t Value = MI->getOperand(OpNum).getImm();284 assert((Value >= -32 && Value <= 95) &&285 "Invalid argument, value must be in ranges <-32,95>");286 O << Value;287 } else288 printOperand(MI, OpNum, O);289}290 291void XtensaInstPrinter::printImm8n_7_AsmOperand(const MCInst *MI, int OpNum,292 raw_ostream &O) {293 if (MI->getOperand(OpNum).isImm()) {294 int64_t Value = MI->getOperand(OpNum).getImm();295 assert((Value >= -8 && Value <= 7) &&296 "Invalid argument, value must be in ranges <-8,7>");297 O << Value;298 } else299 printOperand(MI, OpNum, O);300}301 302void XtensaInstPrinter::printImm64n_4n_AsmOperand(const MCInst *MI, int OpNum,303 raw_ostream &O) {304 if (MI->getOperand(OpNum).isImm()) {305 int64_t Value = MI->getOperand(OpNum).getImm();306 assert((Value >= -64 && Value <= -4) & ((Value & 0x3) == 0) &&307 "Invalid argument, value must be in ranges <-64,-4>");308 O << Value;309 } else310 printOperand(MI, OpNum, O);311}312 313void XtensaInstPrinter::printOffset8m8_AsmOperand(const MCInst *MI, int OpNum,314 raw_ostream &O) {315 if (MI->getOperand(OpNum).isImm()) {316 int64_t Value = MI->getOperand(OpNum).getImm();317 assert((Value >= 0 && Value <= 255) &&318 "Invalid argument, value must be in range [0,255]");319 O << Value;320 } else321 printOperand(MI, OpNum, O);322}323 324void XtensaInstPrinter::printOffset8m16_AsmOperand(const MCInst *MI, int OpNum,325 raw_ostream &O) {326 if (MI->getOperand(OpNum).isImm()) {327 int64_t Value = MI->getOperand(OpNum).getImm();328 assert((Value >= 0 && Value <= 510 && ((Value & 0x1) == 0)) &&329 "Invalid argument, value must be multiples of two in range [0,510]");330 O << Value;331 } else332 printOperand(MI, OpNum, O);333}334 335void XtensaInstPrinter::printOffset8m32_AsmOperand(const MCInst *MI, int OpNum,336 raw_ostream &O) {337 if (MI->getOperand(OpNum).isImm()) {338 int64_t Value = MI->getOperand(OpNum).getImm();339 assert(340 (Value >= 0 && Value <= 1020 && ((Value & 0x3) == 0)) &&341 "Invalid argument, value must be multiples of four in range [0,1020]");342 O << Value;343 } else344 printOperand(MI, OpNum, O);345}346 347void XtensaInstPrinter::printOffset4m32_AsmOperand(const MCInst *MI, int OpNum,348 raw_ostream &O) {349 if (MI->getOperand(OpNum).isImm()) {350 int64_t Value = MI->getOperand(OpNum).getImm();351 assert((Value >= 0 && Value <= 60 && ((Value & 0x3) == 0)) &&352 "Invalid argument, value must be multiples of four in range [0,60]");353 O << Value;354 } else355 printOperand(MI, OpNum, O);356}357 358void XtensaInstPrinter::printEntry_Imm12_AsmOperand(const MCInst *MI, int OpNum,359 raw_ostream &O) {360 if (MI->getOperand(OpNum).isImm()) {361 int64_t Value = MI->getOperand(OpNum).getImm();362 assert((Value >= 0 && Value <= 32760) &&363 "Invalid argument, value must be multiples of eight in range "364 "<0,32760>");365 O << Value;366 } else367 printOperand(MI, OpNum, O);368}369 370void XtensaInstPrinter::printB4const_AsmOperand(const MCInst *MI, int OpNum,371 raw_ostream &O) {372 if (MI->getOperand(OpNum).isImm()) {373 int64_t Value = MI->getOperand(OpNum).getImm();374 375 switch (Value) {376 case -1:377 case 1:378 case 2:379 case 3:380 case 4:381 case 5:382 case 6:383 case 7:384 case 8:385 case 10:386 case 12:387 case 16:388 case 32:389 case 64:390 case 128:391 case 256:392 break;393 default:394 assert((0) && "Invalid B4const argument");395 }396 O << Value;397 } else398 printOperand(MI, OpNum, O);399}400 401void XtensaInstPrinter::printB4constu_AsmOperand(const MCInst *MI, int OpNum,402 raw_ostream &O) {403 if (MI->getOperand(OpNum).isImm()) {404 int64_t Value = MI->getOperand(OpNum).getImm();405 406 switch (Value) {407 case 32768:408 case 65536:409 case 2:410 case 3:411 case 4:412 case 5:413 case 6:414 case 7:415 case 8:416 case 10:417 case 12:418 case 16:419 case 32:420 case 64:421 case 128:422 case 256:423 break;424 default:425 assert((0) && "Invalid B4constu argument");426 }427 O << Value;428 } else429 printOperand(MI, OpNum, O);430}431 432void XtensaInstPrinter::printImm7_22_AsmOperand(const MCInst *MI, int OpNum,433 raw_ostream &O) {434 if (MI->getOperand(OpNum).isImm()) {435 int64_t Value = MI->getOperand(OpNum).getImm();436 assert((Value >= 7 && Value <= 22) &&437 "Invalid argument, value must be in range <7,22>");438 O << Value;439 } else440 printOperand(MI, OpNum, O);441}442