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/PPCBaseInfo.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 assert(Modifier && "Must specify 'cc' or 'reg' as predicate op modifier!"); 90 unsigned Code = MI->getOperand(OpNo).getImm(); 91 if (StringRef(Modifier) == "cc") { 92 switch ((PPC::Predicate)Code) { 93 case PPC::PRED_ALWAYS: return; // Don't print anything for always. 94 case PPC::PRED_LT: O << "lt"; return; 95 case PPC::PRED_LE: O << "le"; return; 96 case PPC::PRED_EQ: O << "eq"; return; 97 case PPC::PRED_GE: O << "ge"; return; 98 case PPC::PRED_GT: O << "gt"; return; 99 case PPC::PRED_NE: O << "ne"; return; 100 case PPC::PRED_UN: O << "un"; return; 101 case PPC::PRED_NU: O << "nu"; return; 102 } 103 } 104 105 assert(StringRef(Modifier) == "reg" && 106 "Need to specify 'cc' or 'reg' as predicate op modifier!"); 107 // Don't print the register for 'always'. 108 if (Code == PPC::PRED_ALWAYS) return; 109 printOperand(MI, OpNo+1, O); 110 } 111 112 void PPCInstPrinter::printS5ImmOperand(const MCInst *MI, unsigned OpNo, 113 raw_ostream &O) { 114 char Value = MI->getOperand(OpNo).getImm(); 115 Value = (Value << (32-5)) >> (32-5); 116 O << (int)Value; 117 } 118 119 void PPCInstPrinter::printU5ImmOperand(const MCInst *MI, unsigned OpNo, 120 raw_ostream &O) { 121 unsigned char Value = MI->getOperand(OpNo).getImm(); 122 assert(Value <= 31 && "Invalid u5imm argument!"); 123 O << (unsigned int)Value; 124 } 125 126 void PPCInstPrinter::printU6ImmOperand(const MCInst *MI, unsigned OpNo, 127 raw_ostream &O) { 128 unsigned char Value = MI->getOperand(OpNo).getImm(); 129 assert(Value <= 63 && "Invalid u6imm argument!"); 130 O << (unsigned int)Value; 131 } 132 133 void PPCInstPrinter::printS16ImmOperand(const MCInst *MI, unsigned OpNo, 134 raw_ostream &O) { 135 O << (short)MI->getOperand(OpNo).getImm(); 136 } 137 138 void PPCInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo, 139 raw_ostream &O) { 140 O << (unsigned short)MI->getOperand(OpNo).getImm(); 141 } 142 143 void PPCInstPrinter::printS16X4ImmOperand(const MCInst *MI, unsigned OpNo, 144 raw_ostream &O) { 145 if (MI->getOperand(OpNo).isImm()) 146 O << (short)(MI->getOperand(OpNo).getImm()*4); 147 else 148 printOperand(MI, OpNo, O); 149 } 150 151 void PPCInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo, 152 raw_ostream &O) { 153 if (!MI->getOperand(OpNo).isImm()) 154 return printOperand(MI, OpNo, O); 155 156 // Branches can take an immediate operand. This is used by the branch 157 // selection pass to print $+8, an eight byte displacement from the PC. 158 O << "$+"; 159 printAbsAddrOperand(MI, OpNo, O); 160 } 161 162 void PPCInstPrinter::printAbsAddrOperand(const MCInst *MI, unsigned OpNo, 163 raw_ostream &O) { 164 O << (int)MI->getOperand(OpNo).getImm()*4; 165 } 166 167 168 void PPCInstPrinter::printcrbitm(const MCInst *MI, unsigned OpNo, 169 raw_ostream &O) { 170 unsigned CCReg = MI->getOperand(OpNo).getReg(); 171 unsigned RegNo; 172 switch (CCReg) { 173 default: llvm_unreachable("Unknown CR register"); 174 case PPC::CR0: RegNo = 0; break; 175 case PPC::CR1: RegNo = 1; break; 176 case PPC::CR2: RegNo = 2; break; 177 case PPC::CR3: RegNo = 3; break; 178 case PPC::CR4: RegNo = 4; break; 179 case PPC::CR5: RegNo = 5; break; 180 case PPC::CR6: RegNo = 6; break; 181 case PPC::CR7: RegNo = 7; break; 182 } 183 O << (0x80 >> RegNo); 184 } 185 186 void PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo, 187 raw_ostream &O) { 188 printSymbolLo(MI, OpNo, O); 189 O << '('; 190 if (MI->getOperand(OpNo+1).getReg() == PPC::R0) 191 O << "0"; 192 else 193 printOperand(MI, OpNo+1, O); 194 O << ')'; 195 } 196 197 void PPCInstPrinter::printMemRegImmShifted(const MCInst *MI, unsigned OpNo, 198 raw_ostream &O) { 199 if (MI->getOperand(OpNo).isImm()) 200 printS16X4ImmOperand(MI, OpNo, O); 201 else 202 printSymbolLo(MI, OpNo, O); 203 O << '('; 204 205 if (MI->getOperand(OpNo+1).getReg() == PPC::R0) 206 O << "0"; 207 else 208 printOperand(MI, OpNo+1, O); 209 O << ')'; 210 } 211 212 213 void PPCInstPrinter::printMemRegReg(const MCInst *MI, unsigned OpNo, 214 raw_ostream &O) { 215 // When used as the base register, r0 reads constant zero rather than 216 // the value contained in the register. For this reason, the darwin 217 // assembler requires that we print r0 as 0 (no r) when used as the base. 218 if (MI->getOperand(OpNo).getReg() == PPC::R0) 219 O << "0"; 220 else 221 printOperand(MI, OpNo, O); 222 O << ", "; 223 printOperand(MI, OpNo+1, O); 224 } 225 226 227 228 /// stripRegisterPrefix - This method strips the character prefix from a 229 /// register name so that only the number is left. Used by for linux asm. 230 static const char *stripRegisterPrefix(const char *RegName) { 231 switch (RegName[0]) { 232 case 'r': 233 case 'f': 234 case 'v': return RegName + 1; 235 case 'c': if (RegName[1] == 'r') return RegName + 2; 236 } 237 238 return RegName; 239 } 240 241 void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 242 raw_ostream &O) { 243 const MCOperand &Op = MI->getOperand(OpNo); 244 if (Op.isReg()) { 245 const char *RegName = getRegisterName(Op.getReg()); 246 // The linux and AIX assembler does not take register prefixes. 247 if (!isDarwinSyntax()) 248 RegName = stripRegisterPrefix(RegName); 249 250 O << RegName; 251 return; 252 } 253 254 if (Op.isImm()) { 255 O << Op.getImm(); 256 return; 257 } 258 259 assert(Op.isExpr() && "unknown operand kind in printOperand"); 260 O << *Op.getExpr(); 261 } 262 263 void PPCInstPrinter::printSymbolLo(const MCInst *MI, unsigned OpNo, 264 raw_ostream &O) { 265 if (MI->getOperand(OpNo).isImm()) 266 return printS16ImmOperand(MI, OpNo, O); 267 268 // FIXME: This is a terrible hack because we can't encode lo16() as an operand 269 // flag of a subtraction. See the FIXME in GetSymbolRef in PPCMCInstLower. 270 if (MI->getOperand(OpNo).isExpr() && 271 isa<MCBinaryExpr>(MI->getOperand(OpNo).getExpr())) { 272 O << "lo16("; 273 printOperand(MI, OpNo, O); 274 O << ')'; 275 } else { 276 printOperand(MI, OpNo, O); 277 } 278 } 279 280 void PPCInstPrinter::printSymbolHi(const MCInst *MI, unsigned OpNo, 281 raw_ostream &O) { 282 if (MI->getOperand(OpNo).isImm()) 283 return printS16ImmOperand(MI, OpNo, O); 284 285 // FIXME: This is a terrible hack because we can't encode lo16() as an operand 286 // flag of a subtraction. See the FIXME in GetSymbolRef in PPCMCInstLower. 287 if (MI->getOperand(OpNo).isExpr() && 288 isa<MCBinaryExpr>(MI->getOperand(OpNo).getExpr())) { 289 O << "ha16("; 290 printOperand(MI, OpNo, O); 291 O << ')'; 292 } else { 293 printOperand(MI, OpNo, O); 294 } 295 } 296 297 298