1 //===-- PPCInstPrinter.cpp - Convert PPC MCInst to assembly syntax --------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This class prints an PPC MCInst to a .s file. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #define DEBUG_TYPE "asm-printer" 15 #include "PPCInstPrinter.h" 16 #include "MCTargetDesc/PPCMCTargetDesc.h" 17 #include "MCTargetDesc/PPCPredicates.h" 18 #include "llvm/MC/MCExpr.h" 19 #include "llvm/MC/MCInst.h" 20 #include "llvm/MC/MCInstrInfo.h" 21 #include "llvm/Support/raw_ostream.h" 22 using namespace llvm; 23 24 #include "PPCGenAsmWriter.inc" 25 26 void PPCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { 27 OS << getRegisterName(RegNo); 28 } 29 30 void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O, 31 StringRef Annot) { 32 // Check for slwi/srwi mnemonics. 33 if (MI->getOpcode() == PPC::RLWINM) { 34 unsigned char SH = MI->getOperand(2).getImm(); 35 unsigned char MB = MI->getOperand(3).getImm(); 36 unsigned char ME = MI->getOperand(4).getImm(); 37 bool useSubstituteMnemonic = false; 38 if (SH <= 31 && MB == 0 && ME == (31-SH)) { 39 O << "\tslwi "; useSubstituteMnemonic = true; 40 } 41 if (SH <= 31 && MB == (32-SH) && ME == 31) { 42 O << "\tsrwi "; useSubstituteMnemonic = true; 43 SH = 32-SH; 44 } 45 if (useSubstituteMnemonic) { 46 printOperand(MI, 0, O); 47 O << ", "; 48 printOperand(MI, 1, O); 49 O << ", " << (unsigned int)SH; 50 51 printAnnotation(O, Annot); 52 return; 53 } 54 } 55 56 if ((MI->getOpcode() == PPC::OR || MI->getOpcode() == PPC::OR8) && 57 MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) { 58 O << "\tmr "; 59 printOperand(MI, 0, O); 60 O << ", "; 61 printOperand(MI, 1, O); 62 printAnnotation(O, Annot); 63 return; 64 } 65 66 if (MI->getOpcode() == PPC::RLDICR) { 67 unsigned char SH = MI->getOperand(2).getImm(); 68 unsigned char ME = MI->getOperand(3).getImm(); 69 // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH 70 if (63-SH == ME) { 71 O << "\tsldi "; 72 printOperand(MI, 0, O); 73 O << ", "; 74 printOperand(MI, 1, O); 75 O << ", " << (unsigned int)SH; 76 printAnnotation(O, Annot); 77 return; 78 } 79 } 80 81 printInstruction(MI, O); 82 printAnnotation(O, Annot); 83 } 84 85 86 void PPCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo, 87 raw_ostream &O, 88 const char *Modifier) { 89 unsigned Code = MI->getOperand(OpNo).getImm(); 90 91 if (StringRef(Modifier) == "cc") { 92 switch ((PPC::Predicate)Code) { 93 case PPC::PRED_LT: O << "lt"; return; 94 case PPC::PRED_LE: O << "le"; return; 95 case PPC::PRED_EQ: O << "eq"; return; 96 case PPC::PRED_GE: O << "ge"; return; 97 case PPC::PRED_GT: O << "gt"; return; 98 case PPC::PRED_NE: O << "ne"; return; 99 case PPC::PRED_UN: O << "un"; return; 100 case PPC::PRED_NU: O << "nu"; return; 101 } 102 } 103 104 assert(StringRef(Modifier) == "reg" && 105 "Need to specify 'cc' or 'reg' as predicate op modifier!"); 106 printOperand(MI, OpNo+1, O); 107 } 108 109 void PPCInstPrinter::printS5ImmOperand(const MCInst *MI, unsigned OpNo, 110 raw_ostream &O) { 111 int Value = MI->getOperand(OpNo).getImm(); 112 Value = SignExtend32<5>(Value); 113 O << (int)Value; 114 } 115 116 void PPCInstPrinter::printU5ImmOperand(const MCInst *MI, unsigned OpNo, 117 raw_ostream &O) { 118 unsigned int Value = MI->getOperand(OpNo).getImm(); 119 assert(Value <= 31 && "Invalid u5imm argument!"); 120 O << (unsigned int)Value; 121 } 122 123 void PPCInstPrinter::printU6ImmOperand(const MCInst *MI, unsigned OpNo, 124 raw_ostream &O) { 125 unsigned int Value = MI->getOperand(OpNo).getImm(); 126 assert(Value <= 63 && "Invalid u6imm argument!"); 127 O << (unsigned int)Value; 128 } 129 130 void PPCInstPrinter::printS16ImmOperand(const MCInst *MI, unsigned OpNo, 131 raw_ostream &O) { 132 O << (short)MI->getOperand(OpNo).getImm(); 133 } 134 135 void PPCInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo, 136 raw_ostream &O) { 137 O << (unsigned short)MI->getOperand(OpNo).getImm(); 138 } 139 140 void PPCInstPrinter::printS16X4ImmOperand(const MCInst *MI, unsigned OpNo, 141 raw_ostream &O) { 142 if (MI->getOperand(OpNo).isImm()) 143 O << (short)(MI->getOperand(OpNo).getImm()*4); 144 else 145 printOperand(MI, OpNo, O); 146 } 147 148 void PPCInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo, 149 raw_ostream &O) { 150 if (!MI->getOperand(OpNo).isImm()) 151 return printOperand(MI, OpNo, O); 152 153 // Branches can take an immediate operand. This is used by the branch 154 // selection pass to print $+8, an eight byte displacement from the PC. 155 O << "$+"; 156 printAbsAddrOperand(MI, OpNo, O); 157 } 158 159 void PPCInstPrinter::printAbsAddrOperand(const MCInst *MI, unsigned OpNo, 160 raw_ostream &O) { 161 O << (int)MI->getOperand(OpNo).getImm()*4; 162 } 163 164 165 void PPCInstPrinter::printcrbitm(const MCInst *MI, unsigned OpNo, 166 raw_ostream &O) { 167 unsigned CCReg = MI->getOperand(OpNo).getReg(); 168 unsigned RegNo; 169 switch (CCReg) { 170 default: llvm_unreachable("Unknown CR register"); 171 case PPC::CR0: RegNo = 0; break; 172 case PPC::CR1: RegNo = 1; break; 173 case PPC::CR2: RegNo = 2; break; 174 case PPC::CR3: RegNo = 3; break; 175 case PPC::CR4: RegNo = 4; break; 176 case PPC::CR5: RegNo = 5; break; 177 case PPC::CR6: RegNo = 6; break; 178 case PPC::CR7: RegNo = 7; break; 179 } 180 O << (0x80 >> RegNo); 181 } 182 183 void PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo, 184 raw_ostream &O) { 185 printSymbolLo(MI, OpNo, O); 186 O << '('; 187 if (MI->getOperand(OpNo+1).getReg() == PPC::R0) 188 O << "0"; 189 else 190 printOperand(MI, OpNo+1, O); 191 O << ')'; 192 } 193 194 void PPCInstPrinter::printMemRegImmShifted(const MCInst *MI, unsigned OpNo, 195 raw_ostream &O) { 196 if (MI->getOperand(OpNo).isImm()) 197 printS16X4ImmOperand(MI, OpNo, O); 198 else 199 printSymbolLo(MI, OpNo, O); 200 O << '('; 201 202 if (MI->getOperand(OpNo+1).getReg() == PPC::R0) 203 O << "0"; 204 else 205 printOperand(MI, OpNo+1, O); 206 O << ')'; 207 } 208 209 210 void PPCInstPrinter::printMemRegReg(const MCInst *MI, unsigned OpNo, 211 raw_ostream &O) { 212 // When used as the base register, r0 reads constant zero rather than 213 // the value contained in the register. For this reason, the darwin 214 // assembler requires that we print r0 as 0 (no r) when used as the base. 215 if (MI->getOperand(OpNo).getReg() == PPC::R0) 216 O << "0"; 217 else 218 printOperand(MI, OpNo, O); 219 O << ", "; 220 printOperand(MI, OpNo+1, O); 221 } 222 223 224 225 /// stripRegisterPrefix - This method strips the character prefix from a 226 /// register name so that only the number is left. Used by for linux asm. 227 static const char *stripRegisterPrefix(const char *RegName) { 228 switch (RegName[0]) { 229 case 'r': 230 case 'f': 231 case 'v': return RegName + 1; 232 case 'c': if (RegName[1] == 'r') return RegName + 2; 233 } 234 235 return RegName; 236 } 237 238 void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 239 raw_ostream &O) { 240 const MCOperand &Op = MI->getOperand(OpNo); 241 if (Op.isReg()) { 242 const char *RegName = getRegisterName(Op.getReg()); 243 // The linux and AIX assembler does not take register prefixes. 244 if (!isDarwinSyntax()) 245 RegName = stripRegisterPrefix(RegName); 246 247 O << RegName; 248 return; 249 } 250 251 if (Op.isImm()) { 252 O << Op.getImm(); 253 return; 254 } 255 256 assert(Op.isExpr() && "unknown operand kind in printOperand"); 257 O << *Op.getExpr(); 258 } 259 260 void PPCInstPrinter::printSymbolLo(const MCInst *MI, unsigned OpNo, 261 raw_ostream &O) { 262 if (MI->getOperand(OpNo).isImm()) 263 return printS16ImmOperand(MI, OpNo, O); 264 265 // FIXME: This is a terrible hack because we can't encode lo16() as an operand 266 // flag of a subtraction. See the FIXME in GetSymbolRef in PPCMCInstLower. 267 if (MI->getOperand(OpNo).isExpr() && 268 isa<MCBinaryExpr>(MI->getOperand(OpNo).getExpr())) { 269 O << "lo16("; 270 printOperand(MI, OpNo, O); 271 O << ')'; 272 } else { 273 printOperand(MI, OpNo, O); 274 } 275 } 276 277 void PPCInstPrinter::printSymbolHi(const MCInst *MI, unsigned OpNo, 278 raw_ostream &O) { 279 if (MI->getOperand(OpNo).isImm()) 280 return printS16ImmOperand(MI, OpNo, O); 281 282 // FIXME: This is a terrible hack because we can't encode lo16() as an operand 283 // flag of a subtraction. See the FIXME in GetSymbolRef in PPCMCInstLower. 284 if (MI->getOperand(OpNo).isExpr() && 285 isa<MCBinaryExpr>(MI->getOperand(OpNo).getExpr())) { 286 O << "ha16("; 287 printOperand(MI, OpNo, O); 288 O << ')'; 289 } else { 290 printOperand(MI, OpNo, O); 291 } 292 } 293 294 295