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