1 //===- XtensaInstPrinter.cpp - Convert Xtensa MCInst to asm syntax --------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 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-exception 8 // 9 //===----------------------------------------------------------------------===// 10 // 11 // This class prints an Xtensa MCInst to a .s file. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "XtensaInstPrinter.h" 16 #include "llvm/CodeGen/MachineOperand.h" 17 #include "llvm/MC/MCExpr.h" 18 #include "llvm/MC/MCInstrInfo.h" 19 #include "llvm/MC/MCRegister.h" 20 #include "llvm/MC/MCSymbol.h" 21 #include "llvm/Support/Casting.h" 22 #include "llvm/Support/raw_ostream.h" 23 24 using namespace llvm; 25 26 #define DEBUG_TYPE "asm-printer" 27 28 #include "XtensaGenAsmWriter.inc" 29 30 static void printExpr(const MCExpr *Expr, raw_ostream &OS) { 31 int Offset = 0; 32 const MCSymbolRefExpr *SRE; 33 34 if (!(SRE = cast<MCSymbolRefExpr>(Expr))) 35 assert(false && "Unexpected MCExpr type."); 36 37 MCSymbolRefExpr::VariantKind Kind = SRE->getKind(); 38 39 switch (Kind) { 40 case MCSymbolRefExpr::VK_None: 41 break; 42 // TODO 43 default: 44 report_fatal_error("Invalid kind!"); 45 } 46 47 OS << SRE->getSymbol(); 48 49 if (Offset) { 50 if (Offset > 0) 51 OS << '+'; 52 OS << Offset; 53 } 54 55 if (Kind != MCSymbolRefExpr::VK_None) 56 OS << ')'; 57 } 58 59 void XtensaInstPrinter::printOperand(const MCOperand &MC, raw_ostream &O) { 60 if (MC.isReg()) 61 O << getRegisterName(MC.getReg()); 62 else if (MC.isImm()) 63 O << MC.getImm(); 64 else if (MC.isExpr()) 65 printExpr(MC.getExpr(), O); 66 else 67 report_fatal_error("Invalid operand"); 68 } 69 70 void XtensaInstPrinter::printInst(const MCInst *MI, uint64_t Address, 71 StringRef Annot, const MCSubtargetInfo &STI, 72 raw_ostream &O) { 73 printInstruction(MI, Address, O); 74 printAnnotation(O, Annot); 75 } 76 77 void XtensaInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) const { 78 O << getRegisterName(Reg); 79 } 80 81 void XtensaInstPrinter::printOperand(const MCInst *MI, int OpNum, 82 raw_ostream &O) { 83 printOperand(MI->getOperand(OpNum), O); 84 } 85 86 void XtensaInstPrinter::printMemOperand(const MCInst *MI, int OpNum, 87 raw_ostream &OS) { 88 OS << getRegisterName(MI->getOperand(OpNum).getReg()); 89 OS << ", "; 90 printOperand(MI, OpNum + 1, OS); 91 } 92 93 void XtensaInstPrinter::printBranchTarget(const MCInst *MI, int OpNum, 94 raw_ostream &OS) { 95 const MCOperand &MC = MI->getOperand(OpNum); 96 if (MI->getOperand(OpNum).isImm()) { 97 int64_t Val = MC.getImm() + 4; 98 OS << ". "; 99 if (Val > 0) 100 OS << '+'; 101 OS << Val; 102 } else if (MC.isExpr()) 103 MC.getExpr()->print(OS, &MAI, true); 104 else 105 llvm_unreachable("Invalid operand"); 106 } 107 108 void XtensaInstPrinter::printJumpTarget(const MCInst *MI, int OpNum, 109 raw_ostream &OS) { 110 const MCOperand &MC = MI->getOperand(OpNum); 111 if (MC.isImm()) { 112 int64_t Val = MC.getImm() + 4; 113 OS << ". "; 114 if (Val > 0) 115 OS << '+'; 116 OS << Val; 117 } else if (MC.isExpr()) 118 MC.getExpr()->print(OS, &MAI, true); 119 else 120 llvm_unreachable("Invalid operand"); 121 ; 122 } 123 124 void XtensaInstPrinter::printCallOperand(const MCInst *MI, int OpNum, 125 raw_ostream &OS) { 126 const MCOperand &MC = MI->getOperand(OpNum); 127 if (MC.isImm()) { 128 int64_t Val = MC.getImm() + 4; 129 OS << ". "; 130 if (Val > 0) 131 OS << '+'; 132 OS << Val; 133 } else if (MC.isExpr()) 134 MC.getExpr()->print(OS, &MAI, true); 135 else 136 llvm_unreachable("Invalid operand"); 137 } 138 139 void XtensaInstPrinter::printL32RTarget(const MCInst *MI, int OpNum, 140 raw_ostream &O) { 141 const MCOperand &MC = MI->getOperand(OpNum); 142 if (MC.isImm()) { 143 int64_t Value = MI->getOperand(OpNum).getImm(); 144 int64_t InstrOff = Value & 0x3; 145 Value -= InstrOff; 146 assert((Value >= -262144 && Value <= -4) && 147 "Invalid argument, value must be in ranges [-262144,-4]"); 148 Value += ((InstrOff + 0x3) & 0x4) - InstrOff; 149 O << ". "; 150 O << Value; 151 } else if (MC.isExpr()) 152 MC.getExpr()->print(O, &MAI, true); 153 else 154 llvm_unreachable("Invalid operand"); 155 } 156 157 void XtensaInstPrinter::printImm8_AsmOperand(const MCInst *MI, int OpNum, 158 raw_ostream &O) { 159 if (MI->getOperand(OpNum).isImm()) { 160 int64_t Value = MI->getOperand(OpNum).getImm(); 161 assert(isInt<8>(Value) && 162 "Invalid argument, value must be in ranges [-128,127]"); 163 O << Value; 164 } else { 165 printOperand(MI, OpNum, O); 166 } 167 } 168 169 void XtensaInstPrinter::printImm8_sh8_AsmOperand(const MCInst *MI, int OpNum, 170 raw_ostream &O) { 171 if (MI->getOperand(OpNum).isImm()) { 172 int64_t Value = MI->getOperand(OpNum).getImm(); 173 assert((isInt<16>(Value) && ((Value & 0xFF) == 0)) && 174 "Invalid argument, value must be multiples of 256 in range " 175 "[-32768,32512]"); 176 O << Value; 177 } else 178 printOperand(MI, OpNum, O); 179 } 180 181 void XtensaInstPrinter::printImm12_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((Value >= -2048 && Value <= 2047) && 186 "Invalid argument, value must be in ranges [-2048,2047]"); 187 O << Value; 188 } else 189 printOperand(MI, OpNum, O); 190 } 191 192 void XtensaInstPrinter::printImm12m_AsmOperand(const MCInst *MI, int OpNum, 193 raw_ostream &O) { 194 if (MI->getOperand(OpNum).isImm()) { 195 int64_t Value = MI->getOperand(OpNum).getImm(); 196 assert((Value >= -2048 && Value <= 2047) && 197 "Invalid argument, value must be in ranges [-2048,2047]"); 198 O << Value; 199 } else 200 printOperand(MI, OpNum, O); 201 } 202 203 void XtensaInstPrinter::printUimm4_AsmOperand(const MCInst *MI, int OpNum, 204 raw_ostream &O) { 205 if (MI->getOperand(OpNum).isImm()) { 206 int64_t Value = MI->getOperand(OpNum).getImm(); 207 assert((Value >= 0 && Value <= 15) && "Invalid argument"); 208 O << Value; 209 } else 210 printOperand(MI, OpNum, O); 211 } 212 213 void XtensaInstPrinter::printUimm5_AsmOperand(const MCInst *MI, int OpNum, 214 raw_ostream &O) { 215 if (MI->getOperand(OpNum).isImm()) { 216 int64_t Value = MI->getOperand(OpNum).getImm(); 217 assert((Value >= 0 && Value <= 31) && "Invalid argument"); 218 O << Value; 219 } else 220 printOperand(MI, OpNum, O); 221 } 222 223 void XtensaInstPrinter::printShimm1_31_AsmOperand(const MCInst *MI, int OpNum, 224 raw_ostream &O) { 225 if (MI->getOperand(OpNum).isImm()) { 226 int64_t Value = MI->getOperand(OpNum).getImm(); 227 assert((Value >= 1 && Value <= 31) && 228 "Invalid argument, value must be in range [1,31]"); 229 O << Value; 230 } else 231 printOperand(MI, OpNum, O); 232 } 233 234 void XtensaInstPrinter::printImm1_16_AsmOperand(const MCInst *MI, int OpNum, 235 raw_ostream &O) { 236 if (MI->getOperand(OpNum).isImm()) { 237 int64_t Value = MI->getOperand(OpNum).getImm(); 238 assert((Value >= 1 && Value <= 16) && 239 "Invalid argument, value must be in range [1,16]"); 240 O << Value; 241 } else 242 printOperand(MI, OpNum, O); 243 } 244 245 void XtensaInstPrinter::printOffset8m8_AsmOperand(const MCInst *MI, int OpNum, 246 raw_ostream &O) { 247 if (MI->getOperand(OpNum).isImm()) { 248 int64_t Value = MI->getOperand(OpNum).getImm(); 249 assert((Value >= 0 && Value <= 255) && 250 "Invalid argument, value must be in range [0,255]"); 251 O << Value; 252 } else 253 printOperand(MI, OpNum, O); 254 } 255 256 void XtensaInstPrinter::printOffset8m16_AsmOperand(const MCInst *MI, int OpNum, 257 raw_ostream &O) { 258 if (MI->getOperand(OpNum).isImm()) { 259 int64_t Value = MI->getOperand(OpNum).getImm(); 260 assert((Value >= 0 && Value <= 510 && ((Value & 0x1) == 0)) && 261 "Invalid argument, value must be multiples of two in range [0,510]"); 262 O << Value; 263 } else 264 printOperand(MI, OpNum, O); 265 } 266 267 void XtensaInstPrinter::printOffset8m32_AsmOperand(const MCInst *MI, int OpNum, 268 raw_ostream &O) { 269 if (MI->getOperand(OpNum).isImm()) { 270 int64_t Value = MI->getOperand(OpNum).getImm(); 271 assert( 272 (Value >= 0 && Value <= 1020 && ((Value & 0x3) == 0)) && 273 "Invalid argument, value must be multiples of four in range [0,1020]"); 274 O << Value; 275 } else 276 printOperand(MI, OpNum, O); 277 } 278 279 void XtensaInstPrinter::printOffset4m32_AsmOperand(const MCInst *MI, int OpNum, 280 raw_ostream &O) { 281 if (MI->getOperand(OpNum).isImm()) { 282 int64_t Value = MI->getOperand(OpNum).getImm(); 283 assert((Value >= 0 && Value <= 60 && ((Value & 0x3) == 0)) && 284 "Invalid argument, value must be multiples of four in range [0,60]"); 285 O << Value; 286 } else 287 printOperand(MI, OpNum, O); 288 } 289 290 void XtensaInstPrinter::printB4const_AsmOperand(const MCInst *MI, int OpNum, 291 raw_ostream &O) { 292 if (MI->getOperand(OpNum).isImm()) { 293 int64_t Value = MI->getOperand(OpNum).getImm(); 294 295 switch (Value) { 296 case -1: 297 case 1: 298 case 2: 299 case 3: 300 case 4: 301 case 5: 302 case 6: 303 case 7: 304 case 8: 305 case 10: 306 case 12: 307 case 16: 308 case 32: 309 case 64: 310 case 128: 311 case 256: 312 break; 313 default: 314 assert((0) && "Invalid B4const argument"); 315 } 316 O << Value; 317 } else 318 printOperand(MI, OpNum, O); 319 } 320 321 void XtensaInstPrinter::printB4constu_AsmOperand(const MCInst *MI, int OpNum, 322 raw_ostream &O) { 323 if (MI->getOperand(OpNum).isImm()) { 324 int64_t Value = MI->getOperand(OpNum).getImm(); 325 326 switch (Value) { 327 case 32768: 328 case 65536: 329 case 2: 330 case 3: 331 case 4: 332 case 5: 333 case 6: 334 case 7: 335 case 8: 336 case 10: 337 case 12: 338 case 16: 339 case 32: 340 case 64: 341 case 128: 342 case 256: 343 break; 344 default: 345 assert((0) && "Invalid B4constu argument"); 346 } 347 O << Value; 348 } else 349 printOperand(MI, OpNum, O); 350 } 351