| OLD | NEW |
| 1 //===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===// | 1 //===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // This file implements the InstARM32 and OperandARM32 classes, | 10 // This file implements the InstARM32 and OperandARM32 classes, |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 const struct InstARM32ShiftAttributes_ { | 40 const struct InstARM32ShiftAttributes_ { |
| 41 const char *EmitString; | 41 const char *EmitString; |
| 42 } InstARM32ShiftAttributes[] = { | 42 } InstARM32ShiftAttributes[] = { |
| 43 #define X(tag, emit) \ | 43 #define X(tag, emit) \ |
| 44 { emit } \ | 44 { emit } \ |
| 45 , | 45 , |
| 46 ICEINSTARM32SHIFT_TABLE | 46 ICEINSTARM32SHIFT_TABLE |
| 47 #undef X | 47 #undef X |
| 48 }; | 48 }; |
| 49 | 49 |
| 50 const struct InstARM32CondAttributes_ { |
| 51 CondARM32::Cond Opposite; |
| 52 const char *EmitString; |
| 53 } InstARM32CondAttributes[] = { |
| 54 #define X(tag, encode, opp, emit) \ |
| 55 { CondARM32::opp, emit } \ |
| 56 , |
| 57 ICEINSTARM32COND_TABLE |
| 58 #undef X |
| 59 }; |
| 60 |
| 50 } // end of anonymous namespace | 61 } // end of anonymous namespace |
| 51 | 62 |
| 52 const char *InstARM32::getWidthString(Type Ty) { | 63 const char *InstARM32::getWidthString(Type Ty) { |
| 53 return TypeARM32Attributes[Ty].WidthString; | 64 return TypeARM32Attributes[Ty].WidthString; |
| 54 } | 65 } |
| 55 | 66 |
| 56 void emitTwoAddr(const char *Opcode, const Inst *Inst, const Cfg *Func) { | 67 const char *InstARM32Pred::predString(CondARM32::Cond Pred) { |
| 68 return InstARM32CondAttributes[Pred].EmitString; |
| 69 } |
| 70 |
| 71 void InstARM32Pred::dumpOpcodePred(Ostream &Str, const char *Opcode, |
| 72 Type Ty) const { |
| 73 Str << Opcode << getPredicate() << "." << Ty; |
| 74 } |
| 75 |
| 76 CondARM32::Cond InstARM32::getOppositeCondition(CondARM32::Cond Cond) { |
| 77 return InstARM32CondAttributes[Cond].Opposite; |
| 78 } |
| 79 |
| 80 void InstARM32Pred::emitTwoAddr(const char *Opcode, const InstARM32Pred *Inst, |
| 81 const Cfg *Func) { |
| 57 if (!ALLOW_DUMP) | 82 if (!ALLOW_DUMP) |
| 58 return; | 83 return; |
| 59 Ostream &Str = Func->getContext()->getStrEmit(); | 84 Ostream &Str = Func->getContext()->getStrEmit(); |
| 60 assert(Inst->getSrcSize() == 2); | 85 assert(Inst->getSrcSize() == 2); |
| 61 Variable *Dest = Inst->getDest(); | 86 Variable *Dest = Inst->getDest(); |
| 62 assert(Dest == Inst->getSrc(0)); | 87 assert(Dest == Inst->getSrc(0)); |
| 63 Str << "\t" << Opcode << "\t"; | 88 Str << "\t" << Opcode << Inst->getPredicate() << "\t"; |
| 64 Dest->emit(Func); | 89 Dest->emit(Func); |
| 65 Str << ", "; | 90 Str << ", "; |
| 66 Inst->getSrc(1)->emit(Func); | 91 Inst->getSrc(1)->emit(Func); |
| 67 } | 92 } |
| 68 | 93 |
| 69 void emitThreeAddr(const char *Opcode, const Inst *Inst, const Cfg *Func, | 94 void InstARM32Pred::emitThreeAddr(const char *Opcode, const InstARM32Pred *Inst, |
| 70 bool SetFlags) { | 95 const Cfg *Func, bool SetFlags) { |
| 71 if (!ALLOW_DUMP) | 96 if (!ALLOW_DUMP) |
| 72 return; | 97 return; |
| 73 Ostream &Str = Func->getContext()->getStrEmit(); | 98 Ostream &Str = Func->getContext()->getStrEmit(); |
| 74 assert(Inst->getSrcSize() == 2); | 99 assert(Inst->getSrcSize() == 2); |
| 75 Str << "\t" << Opcode << (SetFlags ? "s" : "") << "\t"; | 100 Str << "\t" << Opcode << (SetFlags ? "s" : "") << Inst->getPredicate() |
| 101 << "\t"; |
| 76 Inst->getDest()->emit(Func); | 102 Inst->getDest()->emit(Func); |
| 77 Str << ", "; | 103 Str << ", "; |
| 78 Inst->getSrc(0)->emit(Func); | 104 Inst->getSrc(0)->emit(Func); |
| 79 Str << ", "; | 105 Str << ", "; |
| 80 Inst->getSrc(1)->emit(Func); | 106 Inst->getSrc(1)->emit(Func); |
| 81 } | 107 } |
| 82 | 108 |
| 83 OperandARM32Mem::OperandARM32Mem(Cfg * /* Func */, Type Ty, Variable *Base, | 109 OperandARM32Mem::OperandARM32Mem(Cfg * /* Func */, Type Ty, Variable *Base, |
| 84 ConstantInteger32 *ImmOffset, AddrMode Mode) | 110 ConstantInteger32 *ImmOffset, AddrMode Mode) |
| 85 : OperandARM32(kMem, Ty), Base(Base), ImmOffset(ImmOffset), Index(nullptr), | 111 : OperandARM32(kMem, Ty), Base(Base), ImmOffset(ImmOffset), Index(nullptr), |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 NumVars = 1; | 173 NumVars = 1; |
| 148 Variable *ShiftVar = llvm::dyn_cast_or_null<Variable>(ShiftAmt); | 174 Variable *ShiftVar = llvm::dyn_cast_or_null<Variable>(ShiftAmt); |
| 149 if (ShiftVar) | 175 if (ShiftVar) |
| 150 ++NumVars; | 176 ++NumVars; |
| 151 Vars = Func->allocateArrayOf<Variable *>(NumVars); | 177 Vars = Func->allocateArrayOf<Variable *>(NumVars); |
| 152 Vars[0] = Reg; | 178 Vars[0] = Reg; |
| 153 if (ShiftVar) | 179 if (ShiftVar) |
| 154 Vars[1] = ShiftVar; | 180 Vars[1] = ShiftVar; |
| 155 } | 181 } |
| 156 | 182 |
| 157 InstARM32Ldr::InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem) | 183 InstARM32Br::InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, |
| 158 : InstARM32(Func, InstARM32::Ldr, 1, Dest) { | 184 const CfgNode *TargetFalse, CondARM32::Cond Pred) |
| 185 : InstARM32Pred(Func, InstARM32::Br, 0, nullptr, Pred), |
| 186 TargetTrue(TargetTrue), TargetFalse(TargetFalse) {} |
| 187 |
| 188 bool InstARM32Br::optimizeBranch(const CfgNode *NextNode) { |
| 189 // If there is no next block, then there can be no fallthrough to |
| 190 // optimize. |
| 191 if (NextNode == nullptr) |
| 192 return false; |
| 193 // If there is no fallthrough node, such as a non-default case label |
| 194 // for a switch instruction, then there is no opportunity to |
| 195 // optimize. |
| 196 if (getTargetFalse() == nullptr) |
| 197 return false; |
| 198 |
| 199 // Unconditional branch to the next node can be removed. |
| 200 if (isUnconditionalBranch() && getTargetFalse() == NextNode) { |
| 201 assert(getTargetTrue() == nullptr); |
| 202 setDeleted(); |
| 203 return true; |
| 204 } |
| 205 // If the fallthrough is to the next node, set fallthrough to nullptr |
| 206 // to indicate. |
| 207 if (getTargetFalse() == NextNode) { |
| 208 TargetFalse = nullptr; |
| 209 return true; |
| 210 } |
| 211 // If TargetTrue is the next node, and TargetFalse is not nullptr |
| 212 // (which was already tested above), then invert the branch |
| 213 // condition, swap the targets, and set new fallthrough to nullptr. |
| 214 if (getTargetTrue() == NextNode) { |
| 215 assert(Predicate != CondARM32::AL); |
| 216 setPredicate(getOppositeCondition(getPredicate())); |
| 217 TargetTrue = getTargetFalse(); |
| 218 TargetFalse = nullptr; |
| 219 return true; |
| 220 } |
| 221 return false; |
| 222 } |
| 223 |
| 224 bool InstARM32Br::repointEdge(CfgNode *OldNode, CfgNode *NewNode) { |
| 225 if (TargetFalse == OldNode) { |
| 226 TargetFalse = NewNode; |
| 227 return true; |
| 228 } else if (TargetTrue == OldNode) { |
| 229 TargetTrue = NewNode; |
| 230 return true; |
| 231 } |
| 232 return false; |
| 233 } |
| 234 |
| 235 InstARM32Call::InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget) |
| 236 : InstARM32(Func, InstARM32::Call, 1, Dest) { |
| 237 HasSideEffects = true; |
| 238 addSource(CallTarget); |
| 239 } |
| 240 |
| 241 InstARM32Cmp::InstARM32Cmp(Cfg *Func, Variable *Src1, Operand *Src2, |
| 242 CondARM32::Cond Predicate) |
| 243 : InstARM32Pred(Func, InstARM32::Cmp, 2, nullptr, Predicate) { |
| 244 addSource(Src1); |
| 245 addSource(Src2); |
| 246 } |
| 247 |
| 248 InstARM32Ldr::InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, |
| 249 CondARM32::Cond Predicate) |
| 250 : InstARM32Pred(Func, InstARM32::Ldr, 1, Dest, Predicate) { |
| 159 addSource(Mem); | 251 addSource(Mem); |
| 160 } | 252 } |
| 161 | 253 |
| 162 InstARM32Mla::InstARM32Mla(Cfg *Func, Variable *Dest, Variable *Src0, | 254 InstARM32Mla::InstARM32Mla(Cfg *Func, Variable *Dest, Variable *Src0, |
| 163 Variable *Src1, Variable *Acc) | 255 Variable *Src1, Variable *Acc, |
| 164 : InstARM32(Func, InstARM32::Mla, 3, Dest) { | 256 CondARM32::Cond Predicate) |
| 257 : InstARM32Pred(Func, InstARM32::Mla, 3, Dest, Predicate) { |
| 165 addSource(Src0); | 258 addSource(Src0); |
| 166 addSource(Src1); | 259 addSource(Src1); |
| 167 addSource(Acc); | 260 addSource(Acc); |
| 168 } | 261 } |
| 169 | 262 |
| 170 InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source) | 263 InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source) |
| 171 : InstARM32(Func, InstARM32::Ret, Source ? 2 : 1, nullptr) { | 264 : InstARM32(Func, InstARM32::Ret, Source ? 2 : 1, nullptr) { |
| 172 addSource(LR); | 265 addSource(LR); |
| 173 if (Source) | 266 if (Source) |
| 174 addSource(Source); | 267 addSource(Source); |
| 175 } | 268 } |
| 176 | 269 |
| 177 InstARM32Umull::InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, | 270 InstARM32Umull::InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, |
| 178 Variable *Src0, Variable *Src1) | 271 Variable *Src0, Variable *Src1, |
| 179 : InstARM32(Func, InstARM32::Umull, 2, DestLo), | 272 CondARM32::Cond Predicate) |
| 273 : InstARM32Pred(Func, InstARM32::Umull, 2, DestLo, Predicate), |
| 180 // DestHi is expected to have a FakeDef inserted by the lowering code. | 274 // DestHi is expected to have a FakeDef inserted by the lowering code. |
| 181 DestHi(DestHi) { | 275 DestHi(DestHi) { |
| 182 addSource(Src0); | 276 addSource(Src0); |
| 183 addSource(Src1); | 277 addSource(Src1); |
| 184 } | 278 } |
| 185 | 279 |
| 186 // ======================== Dump routines ======================== // | 280 // ======================== Dump routines ======================== // |
| 187 | 281 |
| 188 // Two-addr ops | 282 // Two-addr ops |
| 189 template <> const char *InstARM32Movt::Opcode = "movt"; | 283 template <> const char *InstARM32Movt::Opcode = "movt"; |
| 190 // Unary ops | 284 // Unary ops |
| 191 template <> const char *InstARM32Movw::Opcode = "movw"; | 285 template <> const char *InstARM32Movw::Opcode = "movw"; |
| 192 template <> const char *InstARM32Mvn::Opcode = "mvn"; | 286 template <> const char *InstARM32Mvn::Opcode = "mvn"; |
| 193 // Mov-like ops | 287 // Mov-like ops |
| 194 template <> const char *InstARM32Mov::Opcode = "mov"; | 288 template <> const char *InstARM32Mov::Opcode = "mov"; |
| 195 // Three-addr ops | 289 // Three-addr ops |
| 196 template <> const char *InstARM32Adc::Opcode = "adc"; | 290 template <> const char *InstARM32Adc::Opcode = "adc"; |
| 197 template <> const char *InstARM32Add::Opcode = "add"; | 291 template <> const char *InstARM32Add::Opcode = "add"; |
| 198 template <> const char *InstARM32And::Opcode = "and"; | 292 template <> const char *InstARM32And::Opcode = "and"; |
| 199 template <> const char *InstARM32Eor::Opcode = "eor"; | 293 template <> const char *InstARM32Eor::Opcode = "eor"; |
| 294 template <> const char *InstARM32Lsl::Opcode = "lsl"; |
| 200 template <> const char *InstARM32Mul::Opcode = "mul"; | 295 template <> const char *InstARM32Mul::Opcode = "mul"; |
| 201 template <> const char *InstARM32Orr::Opcode = "orr"; | 296 template <> const char *InstARM32Orr::Opcode = "orr"; |
| 202 template <> const char *InstARM32Sbc::Opcode = "sbc"; | 297 template <> const char *InstARM32Sbc::Opcode = "sbc"; |
| 203 template <> const char *InstARM32Sub::Opcode = "sub"; | 298 template <> const char *InstARM32Sub::Opcode = "sub"; |
| 204 | 299 |
| 205 void InstARM32::dump(const Cfg *Func) const { | 300 void InstARM32::dump(const Cfg *Func) const { |
| 206 if (!ALLOW_DUMP) | 301 if (!ALLOW_DUMP) |
| 207 return; | 302 return; |
| 208 Ostream &Str = Func->getContext()->getStrDump(); | 303 Ostream &Str = Func->getContext()->getStrDump(); |
| 209 Str << "[ARM32] "; | 304 Str << "[ARM32] "; |
| 210 Inst::dump(Func); | 305 Inst::dump(Func); |
| 211 } | 306 } |
| 212 | 307 |
| 213 template <> void InstARM32Mov::emit(const Cfg *Func) const { | 308 template <> void InstARM32Mov::emit(const Cfg *Func) const { |
| 214 if (!ALLOW_DUMP) | 309 if (!ALLOW_DUMP) |
| 215 return; | 310 return; |
| 216 Ostream &Str = Func->getContext()->getStrEmit(); | 311 Ostream &Str = Func->getContext()->getStrEmit(); |
| 217 assert(getSrcSize() == 1); | 312 assert(getSrcSize() == 1); |
| 218 Variable *Dest = getDest(); | 313 Variable *Dest = getDest(); |
| 219 if (Dest->hasReg()) { | 314 if (Dest->hasReg()) { |
| 220 Str << "\t" | 315 Str << "\t" |
| 221 << "mov" | 316 << "mov" << getPredicate() << "\t"; |
| 222 << "\t"; | |
| 223 getDest()->emit(Func); | 317 getDest()->emit(Func); |
| 224 Str << ", "; | 318 Str << ", "; |
| 225 getSrc(0)->emit(Func); | 319 getSrc(0)->emit(Func); |
| 226 } else { | 320 } else { |
| 227 Variable *Src0 = llvm::cast<Variable>(getSrc(0)); | 321 Variable *Src0 = llvm::cast<Variable>(getSrc(0)); |
| 228 assert(Src0->hasReg()); | 322 assert(Src0->hasReg()); |
| 229 Str << "\t" | 323 Str << "\t" |
| 230 << "str" | 324 << "str" << getPredicate() << "\t"; |
| 231 << "\t"; | |
| 232 Src0->emit(Func); | 325 Src0->emit(Func); |
| 233 Str << ", "; | 326 Str << ", "; |
| 234 Dest->emit(Func); | 327 Dest->emit(Func); |
| 235 } | 328 } |
| 236 } | 329 } |
| 237 | 330 |
| 238 template <> void InstARM32Mov::emitIAS(const Cfg *Func) const { | 331 template <> void InstARM32Mov::emitIAS(const Cfg *Func) const { |
| 239 assert(getSrcSize() == 1); | 332 assert(getSrcSize() == 1); |
| 240 (void)Func; | 333 (void)Func; |
| 241 llvm_unreachable("Not yet implemented"); | 334 llvm_unreachable("Not yet implemented"); |
| 242 } | 335 } |
| 243 | 336 |
| 337 void InstARM32Br::emit(const Cfg *Func) const { |
| 338 if (!ALLOW_DUMP) |
| 339 return; |
| 340 Ostream &Str = Func->getContext()->getStrEmit(); |
| 341 Str << "\t" |
| 342 << "b" << getPredicate() << "\t"; |
| 343 if (isUnconditionalBranch()) { |
| 344 Str << getTargetFalse()->getAsmName(); |
| 345 } else { |
| 346 Str << getTargetTrue()->getAsmName(); |
| 347 if (getTargetFalse()) { |
| 348 Str << "\n\t" |
| 349 << "b" |
| 350 << "\t" << getTargetFalse()->getAsmName(); |
| 351 } |
| 352 } |
| 353 } |
| 354 |
| 355 void InstARM32Br::emitIAS(const Cfg *Func) const { |
| 356 (void)Func; |
| 357 llvm_unreachable("Not yet implemented"); |
| 358 } |
| 359 |
| 360 void InstARM32Br::dump(const Cfg *Func) const { |
| 361 if (!ALLOW_DUMP) |
| 362 return; |
| 363 Ostream &Str = Func->getContext()->getStrDump(); |
| 364 Str << "br "; |
| 365 |
| 366 if (getPredicate() == CondARM32::AL) { |
| 367 Str << "label %" << getTargetFalse()->getName(); |
| 368 return; |
| 369 } |
| 370 |
| 371 Str << getPredicate() << ", label %" << getTargetTrue()->getName(); |
| 372 if (getTargetFalse()) { |
| 373 Str << ", label %" << getTargetFalse()->getName(); |
| 374 } |
| 375 } |
| 376 |
| 377 void InstARM32Call::emit(const Cfg *Func) const { |
| 378 if (!ALLOW_DUMP) |
| 379 return; |
| 380 Ostream &Str = Func->getContext()->getStrEmit(); |
| 381 assert(getSrcSize() == 1); |
| 382 if (llvm::isa<ConstantInteger32>(getCallTarget())) { |
| 383 // This shouldn't happen (typically have to copy the full 32-bits |
| 384 // to a register and do an indirect jump). |
| 385 llvm::report_fatal_error("ARM32Call to ConstantInteger32"); |
| 386 } else if (const auto CallTarget = |
| 387 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) { |
| 388 // Calls only have 24-bits, but the linker should insert veneers to |
| 389 // extend the range if needed. |
| 390 Str << "\t" |
| 391 << "bl" |
| 392 << "\t"; |
| 393 CallTarget->emitWithoutPrefix(Func->getTarget()); |
| 394 } else { |
| 395 Str << "\t" |
| 396 << "blx" |
| 397 << "\t"; |
| 398 getCallTarget()->emit(Func); |
| 399 } |
| 400 Func->getTarget()->resetStackAdjustment(); |
| 401 } |
| 402 |
| 403 void InstARM32Call::emitIAS(const Cfg *Func) const { |
| 404 (void)Func; |
| 405 llvm_unreachable("Not yet implemented"); |
| 406 } |
| 407 |
| 408 void InstARM32Call::dump(const Cfg *Func) const { |
| 409 if (!ALLOW_DUMP) |
| 410 return; |
| 411 Ostream &Str = Func->getContext()->getStrDump(); |
| 412 if (getDest()) { |
| 413 dumpDest(Func); |
| 414 Str << " = "; |
| 415 } |
| 416 Str << "call "; |
| 417 getCallTarget()->dump(Func); |
| 418 } |
| 419 |
| 420 void InstARM32Cmp::emit(const Cfg *Func) const { |
| 421 if (!ALLOW_DUMP) |
| 422 return; |
| 423 Ostream &Str = Func->getContext()->getStrEmit(); |
| 424 assert(getSrcSize() == 2); |
| 425 Str << "\t" |
| 426 << "cmp" << getPredicate() << "\t"; |
| 427 getSrc(0)->emit(Func); |
| 428 Str << ", "; |
| 429 getSrc(1)->emit(Func); |
| 430 } |
| 431 |
| 432 void InstARM32Cmp::emitIAS(const Cfg *Func) const { |
| 433 assert(getSrcSize() == 2); |
| 434 (void)Func; |
| 435 llvm_unreachable("Not yet implemented"); |
| 436 } |
| 437 |
| 438 void InstARM32Cmp::dump(const Cfg *Func) const { |
| 439 if (!ALLOW_DUMP) |
| 440 return; |
| 441 Ostream &Str = Func->getContext()->getStrDump(); |
| 442 dumpOpcodePred(Str, "cmp", getSrc(0)->getType()); |
| 443 dumpSources(Func); |
| 444 } |
| 445 |
| 244 void InstARM32Ldr::emit(const Cfg *Func) const { | 446 void InstARM32Ldr::emit(const Cfg *Func) const { |
| 245 if (!ALLOW_DUMP) | 447 if (!ALLOW_DUMP) |
| 246 return; | 448 return; |
| 247 Ostream &Str = Func->getContext()->getStrEmit(); | 449 Ostream &Str = Func->getContext()->getStrEmit(); |
| 248 assert(getSrcSize() == 1); | 450 assert(getSrcSize() == 1); |
| 249 assert(getDest()->hasReg()); | 451 assert(getDest()->hasReg()); |
| 250 Type Ty = getSrc(0)->getType(); | 452 Type Ty = getSrc(0)->getType(); |
| 251 Str << "\t" | 453 Str << "\t" |
| 252 << "ldr" << getWidthString(Ty) << "\t"; | 454 << "ldr" << getWidthString(Ty) << getPredicate() << "\t"; |
| 253 getDest()->emit(Func); | 455 getDest()->emit(Func); |
| 254 Str << ", "; | 456 Str << ", "; |
| 255 getSrc(0)->emit(Func); | 457 getSrc(0)->emit(Func); |
| 256 } | 458 } |
| 257 | 459 |
| 258 void InstARM32Ldr::emitIAS(const Cfg *Func) const { | 460 void InstARM32Ldr::emitIAS(const Cfg *Func) const { |
| 259 assert(getSrcSize() == 1); | 461 assert(getSrcSize() == 1); |
| 260 (void)Func; | 462 (void)Func; |
| 261 llvm_unreachable("Not yet implemented"); | 463 llvm_unreachable("Not yet implemented"); |
| 262 } | 464 } |
| 263 | 465 |
| 264 void InstARM32Ldr::dump(const Cfg *Func) const { | 466 void InstARM32Ldr::dump(const Cfg *Func) const { |
| 265 if (!ALLOW_DUMP) | 467 if (!ALLOW_DUMP) |
| 266 return; | 468 return; |
| 267 Ostream &Str = Func->getContext()->getStrDump(); | 469 Ostream &Str = Func->getContext()->getStrDump(); |
| 268 dumpDest(Func); | 470 dumpDest(Func); |
| 269 Str << " = ldr." << getSrc(0)->getType() << " "; | 471 Str << " = "; |
| 472 dumpOpcodePred(Str, "ldr", getDest()->getType()); |
| 473 Str << " "; |
| 270 dumpSources(Func); | 474 dumpSources(Func); |
| 271 } | 475 } |
| 272 | 476 |
| 273 void InstARM32Mla::emit(const Cfg *Func) const { | 477 void InstARM32Mla::emit(const Cfg *Func) const { |
| 274 if (!ALLOW_DUMP) | 478 if (!ALLOW_DUMP) |
| 275 return; | 479 return; |
| 276 Ostream &Str = Func->getContext()->getStrEmit(); | 480 Ostream &Str = Func->getContext()->getStrEmit(); |
| 277 assert(getSrcSize() == 3); | 481 assert(getSrcSize() == 3); |
| 278 assert(getDest()->hasReg()); | 482 assert(getDest()->hasReg()); |
| 279 Str << "\t" | 483 Str << "\t" |
| 280 << "mla" | 484 << "mla" << getPredicate() << "\t"; |
| 281 << "\t"; | |
| 282 getDest()->emit(Func); | 485 getDest()->emit(Func); |
| 283 Str << ", "; | 486 Str << ", "; |
| 284 getSrc(0)->emit(Func); | 487 getSrc(0)->emit(Func); |
| 285 Str << ", "; | 488 Str << ", "; |
| 286 getSrc(1)->emit(Func); | 489 getSrc(1)->emit(Func); |
| 287 Str << ", "; | 490 Str << ", "; |
| 288 getSrc(2)->emit(Func); | 491 getSrc(2)->emit(Func); |
| 289 } | 492 } |
| 290 | 493 |
| 291 void InstARM32Mla::emitIAS(const Cfg *Func) const { | 494 void InstARM32Mla::emitIAS(const Cfg *Func) const { |
| 292 assert(getSrcSize() == 3); | 495 assert(getSrcSize() == 3); |
| 293 (void)Func; | 496 (void)Func; |
| 294 llvm_unreachable("Not yet implemented"); | 497 llvm_unreachable("Not yet implemented"); |
| 295 } | 498 } |
| 296 | 499 |
| 297 void InstARM32Mla::dump(const Cfg *Func) const { | 500 void InstARM32Mla::dump(const Cfg *Func) const { |
| 298 if (!ALLOW_DUMP) | 501 if (!ALLOW_DUMP) |
| 299 return; | 502 return; |
| 300 Ostream &Str = Func->getContext()->getStrDump(); | 503 Ostream &Str = Func->getContext()->getStrDump(); |
| 301 dumpDest(Func); | 504 dumpDest(Func); |
| 302 Str << " = mla." << getSrc(0)->getType() << " "; | 505 Str << " = "; |
| 506 dumpOpcodePred(Str, "mla", getDest()->getType()); |
| 507 Str << " "; |
| 303 dumpSources(Func); | 508 dumpSources(Func); |
| 304 } | 509 } |
| 305 | 510 |
| 306 template <> void InstARM32Movw::emit(const Cfg *Func) const { | 511 template <> void InstARM32Movw::emit(const Cfg *Func) const { |
| 307 if (!ALLOW_DUMP) | 512 if (!ALLOW_DUMP) |
| 308 return; | 513 return; |
| 309 Ostream &Str = Func->getContext()->getStrEmit(); | 514 Ostream &Str = Func->getContext()->getStrEmit(); |
| 310 assert(getSrcSize() == 1); | 515 assert(getSrcSize() == 1); |
| 311 Str << "\t" << Opcode << "\t"; | 516 Str << "\t" << Opcode << getPredicate() << "\t"; |
| 312 getDest()->emit(Func); | 517 getDest()->emit(Func); |
| 313 Str << ", "; | 518 Str << ", "; |
| 314 Constant *Src0 = llvm::cast<Constant>(getSrc(0)); | 519 Constant *Src0 = llvm::cast<Constant>(getSrc(0)); |
| 315 if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) { | 520 if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) { |
| 316 Str << "#:lower16:"; | 521 Str << "#:lower16:"; |
| 317 CR->emitWithoutPrefix(Func->getTarget()); | 522 CR->emitWithoutPrefix(Func->getTarget()); |
| 318 } else { | 523 } else { |
| 319 Src0->emit(Func); | 524 Src0->emit(Func); |
| 320 } | 525 } |
| 321 } | 526 } |
| 322 | 527 |
| 323 template <> void InstARM32Movt::emit(const Cfg *Func) const { | 528 template <> void InstARM32Movt::emit(const Cfg *Func) const { |
| 324 if (!ALLOW_DUMP) | 529 if (!ALLOW_DUMP) |
| 325 return; | 530 return; |
| 326 Ostream &Str = Func->getContext()->getStrEmit(); | 531 Ostream &Str = Func->getContext()->getStrEmit(); |
| 327 assert(getSrcSize() == 2); | 532 assert(getSrcSize() == 2); |
| 328 Variable *Dest = getDest(); | 533 Variable *Dest = getDest(); |
| 329 Constant *Src1 = llvm::cast<Constant>(getSrc(1)); | 534 Constant *Src1 = llvm::cast<Constant>(getSrc(1)); |
| 330 Str << "\t" << Opcode << "\t"; | 535 Str << "\t" << Opcode << getPredicate() << "\t"; |
| 331 Dest->emit(Func); | 536 Dest->emit(Func); |
| 332 Str << ", "; | 537 Str << ", "; |
| 333 if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Src1)) { | 538 if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Src1)) { |
| 334 Str << "#:upper16:"; | 539 Str << "#:upper16:"; |
| 335 CR->emitWithoutPrefix(Func->getTarget()); | 540 CR->emitWithoutPrefix(Func->getTarget()); |
| 336 } else { | 541 } else { |
| 337 Src1->emit(Func); | 542 Src1->emit(Func); |
| 338 } | 543 } |
| 339 } | 544 } |
| 340 | 545 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 366 dumpSources(Func); | 571 dumpSources(Func); |
| 367 } | 572 } |
| 368 | 573 |
| 369 void InstARM32Umull::emit(const Cfg *Func) const { | 574 void InstARM32Umull::emit(const Cfg *Func) const { |
| 370 if (!ALLOW_DUMP) | 575 if (!ALLOW_DUMP) |
| 371 return; | 576 return; |
| 372 Ostream &Str = Func->getContext()->getStrEmit(); | 577 Ostream &Str = Func->getContext()->getStrEmit(); |
| 373 assert(getSrcSize() == 2); | 578 assert(getSrcSize() == 2); |
| 374 assert(getDest()->hasReg()); | 579 assert(getDest()->hasReg()); |
| 375 Str << "\t" | 580 Str << "\t" |
| 376 << "umull" | 581 << "umull" << getPredicate() << "\t"; |
| 377 << "\t"; | |
| 378 getDest()->emit(Func); | 582 getDest()->emit(Func); |
| 379 Str << ", "; | 583 Str << ", "; |
| 380 DestHi->emit(Func); | 584 DestHi->emit(Func); |
| 381 Str << ", "; | 585 Str << ", "; |
| 382 getSrc(0)->emit(Func); | 586 getSrc(0)->emit(Func); |
| 383 Str << ", "; | 587 Str << ", "; |
| 384 getSrc(1)->emit(Func); | 588 getSrc(1)->emit(Func); |
| 385 } | 589 } |
| 386 | 590 |
| 387 void InstARM32Umull::emitIAS(const Cfg *Func) const { | 591 void InstARM32Umull::emitIAS(const Cfg *Func) const { |
| 388 assert(getSrcSize() == 2); | 592 assert(getSrcSize() == 2); |
| 389 (void)Func; | 593 (void)Func; |
| 390 llvm_unreachable("Not yet implemented"); | 594 llvm_unreachable("Not yet implemented"); |
| 391 } | 595 } |
| 392 | 596 |
| 393 void InstARM32Umull::dump(const Cfg *Func) const { | 597 void InstARM32Umull::dump(const Cfg *Func) const { |
| 394 if (!ALLOW_DUMP) | 598 if (!ALLOW_DUMP) |
| 395 return; | 599 return; |
| 396 Ostream &Str = Func->getContext()->getStrDump(); | 600 Ostream &Str = Func->getContext()->getStrDump(); |
| 397 dumpDest(Func); | 601 dumpDest(Func); |
| 398 Str << " = umull." << getSrc(0)->getType() << " "; | 602 Str << " = "; |
| 603 dumpOpcodePred(Str, "umull", getDest()->getType()); |
| 604 Str << " "; |
| 399 dumpSources(Func); | 605 dumpSources(Func); |
| 400 } | 606 } |
| 401 | 607 |
| 402 void OperandARM32Mem::emit(const Cfg *Func) const { | 608 void OperandARM32Mem::emit(const Cfg *Func) const { |
| 403 if (!ALLOW_DUMP) | 609 if (!ALLOW_DUMP) |
| 404 return; | 610 return; |
| 405 Ostream &Str = Func->getContext()->getStrEmit(); | 611 Ostream &Str = Func->getContext()->getStrEmit(); |
| 406 Str << "["; | 612 Str << "["; |
| 407 getBase()->emit(Func); | 613 getBase()->emit(Func); |
| 408 switch (getAddrMode()) { | 614 switch (getAddrMode()) { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 if (getShiftOp() != kNoShift) { | 714 if (getShiftOp() != kNoShift) { |
| 509 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " "; | 715 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " "; |
| 510 if (Func) | 716 if (Func) |
| 511 getShiftAmt()->dump(Func); | 717 getShiftAmt()->dump(Func); |
| 512 else | 718 else |
| 513 getShiftAmt()->dump(Str); | 719 getShiftAmt()->dump(Str); |
| 514 } | 720 } |
| 515 } | 721 } |
| 516 | 722 |
| 517 } // end of namespace Ice | 723 } // end of namespace Ice |
| OLD | NEW |