OLD | NEW |
1 //===- subzero/src/IceTargetLoweringARM32.h - ARM32 lowering ----*- C++ -*-===// | 1 //===- subzero/src/IceTargetLoweringARM32.h - ARM32 lowering ----*- C++ -*-===// |
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 /// \file | 10 /// \file |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 // The following are helpers that insert lowered ARM32 instructions | 183 // The following are helpers that insert lowered ARM32 instructions |
184 // with minimal syntactic overhead, so that the lowering code can | 184 // with minimal syntactic overhead, so that the lowering code can |
185 // look as close to assembly as practical. | 185 // look as close to assembly as practical. |
186 | 186 |
187 void _add(Variable *Dest, Variable *Src0, Operand *Src1, | 187 void _add(Variable *Dest, Variable *Src0, Operand *Src1, |
188 CondARM32::Cond Pred = CondARM32::AL) { | 188 CondARM32::Cond Pred = CondARM32::AL) { |
189 Context.insert(InstARM32Add::create(Func, Dest, Src0, Src1, Pred)); | 189 Context.insert(InstARM32Add::create(Func, Dest, Src0, Src1, Pred)); |
190 } | 190 } |
191 void _adds(Variable *Dest, Variable *Src0, Operand *Src1, | 191 void _adds(Variable *Dest, Variable *Src0, Operand *Src1, |
192 CondARM32::Cond Pred = CondARM32::AL) { | 192 CondARM32::Cond Pred = CondARM32::AL) { |
193 const bool SetFlags = true; | 193 constexpr bool SetFlags = true; |
194 Context.insert( | 194 Context.insert( |
195 InstARM32Add::create(Func, Dest, Src0, Src1, Pred, SetFlags)); | 195 InstARM32Add::create(Func, Dest, Src0, Src1, Pred, SetFlags)); |
196 } | 196 } |
197 void _adc(Variable *Dest, Variable *Src0, Operand *Src1, | 197 void _adc(Variable *Dest, Variable *Src0, Operand *Src1, |
198 CondARM32::Cond Pred = CondARM32::AL) { | 198 CondARM32::Cond Pred = CondARM32::AL) { |
199 Context.insert(InstARM32Adc::create(Func, Dest, Src0, Src1, Pred)); | 199 Context.insert(InstARM32Adc::create(Func, Dest, Src0, Src1, Pred)); |
200 } | 200 } |
201 void _adjust_stack(int32_t Amount, Operand *SrcAmount) { | 201 void _adjust_stack(int32_t Amount, Operand *SrcAmount) { |
202 Context.insert(InstARM32AdjustStack::create( | 202 Context.insert(InstARM32AdjustStack::create( |
203 Func, getPhysicalRegister(RegARM32::Reg_sp), Amount, SrcAmount)); | 203 Func, getPhysicalRegister(RegARM32::Reg_sp), Amount, SrcAmount)); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 void _mvn(Variable *Dest, Operand *Src0, | 293 void _mvn(Variable *Dest, Operand *Src0, |
294 CondARM32::Cond Pred = CondARM32::AL) { | 294 CondARM32::Cond Pred = CondARM32::AL) { |
295 Context.insert(InstARM32Mvn::create(Func, Dest, Src0, Pred)); | 295 Context.insert(InstARM32Mvn::create(Func, Dest, Src0, Pred)); |
296 } | 296 } |
297 void _orr(Variable *Dest, Variable *Src0, Operand *Src1, | 297 void _orr(Variable *Dest, Variable *Src0, Operand *Src1, |
298 CondARM32::Cond Pred = CondARM32::AL) { | 298 CondARM32::Cond Pred = CondARM32::AL) { |
299 Context.insert(InstARM32Orr::create(Func, Dest, Src0, Src1, Pred)); | 299 Context.insert(InstARM32Orr::create(Func, Dest, Src0, Src1, Pred)); |
300 } | 300 } |
301 void _orrs(Variable *Dest, Variable *Src0, Operand *Src1, | 301 void _orrs(Variable *Dest, Variable *Src0, Operand *Src1, |
302 CondARM32::Cond Pred = CondARM32::AL) { | 302 CondARM32::Cond Pred = CondARM32::AL) { |
303 const bool SetFlags = true; | 303 constexpr bool SetFlags = true; |
304 Context.insert( | 304 Context.insert( |
305 InstARM32Orr::create(Func, Dest, Src0, Src1, Pred, SetFlags)); | 305 InstARM32Orr::create(Func, Dest, Src0, Src1, Pred, SetFlags)); |
306 } | 306 } |
307 void _push(const VarList &Sources) { | 307 void _push(const VarList &Sources) { |
308 Context.insert(InstARM32Push::create(Func, Sources)); | 308 Context.insert(InstARM32Push::create(Func, Sources)); |
309 } | 309 } |
310 void _pop(const VarList &Dests) { | 310 void _pop(const VarList &Dests) { |
311 Context.insert(InstARM32Pop::create(Func, Dests)); | 311 Context.insert(InstARM32Pop::create(Func, Dests)); |
312 // Mark dests as modified. | 312 // Mark dests as modified. |
313 for (Variable *Dest : Dests) | 313 for (Variable *Dest : Dests) |
(...skipping 13 matching lines...) Expand all Loading... |
327 void _rsb(Variable *Dest, Variable *Src0, Operand *Src1, | 327 void _rsb(Variable *Dest, Variable *Src0, Operand *Src1, |
328 CondARM32::Cond Pred = CondARM32::AL) { | 328 CondARM32::Cond Pred = CondARM32::AL) { |
329 Context.insert(InstARM32Rsb::create(Func, Dest, Src0, Src1, Pred)); | 329 Context.insert(InstARM32Rsb::create(Func, Dest, Src0, Src1, Pred)); |
330 } | 330 } |
331 void _sbc(Variable *Dest, Variable *Src0, Operand *Src1, | 331 void _sbc(Variable *Dest, Variable *Src0, Operand *Src1, |
332 CondARM32::Cond Pred = CondARM32::AL) { | 332 CondARM32::Cond Pred = CondARM32::AL) { |
333 Context.insert(InstARM32Sbc::create(Func, Dest, Src0, Src1, Pred)); | 333 Context.insert(InstARM32Sbc::create(Func, Dest, Src0, Src1, Pred)); |
334 } | 334 } |
335 void _sbcs(Variable *Dest, Variable *Src0, Operand *Src1, | 335 void _sbcs(Variable *Dest, Variable *Src0, Operand *Src1, |
336 CondARM32::Cond Pred = CondARM32::AL) { | 336 CondARM32::Cond Pred = CondARM32::AL) { |
337 const bool SetFlags = true; | 337 constexpr bool SetFlags = true; |
338 Context.insert( | 338 Context.insert( |
339 InstARM32Sbc::create(Func, Dest, Src0, Src1, Pred, SetFlags)); | 339 InstARM32Sbc::create(Func, Dest, Src0, Src1, Pred, SetFlags)); |
340 } | 340 } |
341 void _sdiv(Variable *Dest, Variable *Src0, Variable *Src1, | 341 void _sdiv(Variable *Dest, Variable *Src0, Variable *Src1, |
342 CondARM32::Cond Pred = CondARM32::AL) { | 342 CondARM32::Cond Pred = CondARM32::AL) { |
343 Context.insert(InstARM32Sdiv::create(Func, Dest, Src0, Src1, Pred)); | 343 Context.insert(InstARM32Sdiv::create(Func, Dest, Src0, Src1, Pred)); |
344 } | 344 } |
345 void _str(Variable *Value, OperandARM32Mem *Addr, | 345 void _str(Variable *Value, OperandARM32Mem *Addr, |
346 CondARM32::Cond Pred = CondARM32::AL) { | 346 CondARM32::Cond Pred = CondARM32::AL) { |
347 Context.insert(InstARM32Str::create(Func, Value, Addr, Pred)); | 347 Context.insert(InstARM32Str::create(Func, Value, Addr, Pred)); |
348 } | 348 } |
349 void _sub(Variable *Dest, Variable *Src0, Operand *Src1, | 349 void _sub(Variable *Dest, Variable *Src0, Operand *Src1, |
350 CondARM32::Cond Pred = CondARM32::AL) { | 350 CondARM32::Cond Pred = CondARM32::AL) { |
351 Context.insert(InstARM32Sub::create(Func, Dest, Src0, Src1, Pred)); | 351 Context.insert(InstARM32Sub::create(Func, Dest, Src0, Src1, Pred)); |
352 } | 352 } |
353 void _subs(Variable *Dest, Variable *Src0, Operand *Src1, | 353 void _subs(Variable *Dest, Variable *Src0, Operand *Src1, |
354 CondARM32::Cond Pred = CondARM32::AL) { | 354 CondARM32::Cond Pred = CondARM32::AL) { |
355 const bool SetFlags = true; | 355 constexpr bool SetFlags = true; |
356 Context.insert( | 356 Context.insert( |
357 InstARM32Sub::create(Func, Dest, Src0, Src1, Pred, SetFlags)); | 357 InstARM32Sub::create(Func, Dest, Src0, Src1, Pred, SetFlags)); |
358 } | 358 } |
359 void _sxt(Variable *Dest, Variable *Src0, | 359 void _sxt(Variable *Dest, Variable *Src0, |
360 CondARM32::Cond Pred = CondARM32::AL) { | 360 CondARM32::Cond Pred = CondARM32::AL) { |
361 Context.insert(InstARM32Sxt::create(Func, Dest, Src0, Pred)); | 361 Context.insert(InstARM32Sxt::create(Func, Dest, Src0, Pred)); |
362 } | 362 } |
363 void _tst(Variable *Src0, Operand *Src1, | 363 void _tst(Variable *Src0, Operand *Src1, |
364 CondARM32::Cond Pred = CondARM32::AL) { | 364 CondARM32::Cond Pred = CondARM32::AL) { |
365 Context.insert(InstARM32Tst::create(Func, Src0, Src1, Pred)); | 365 Context.insert(InstARM32Tst::create(Func, Src0, Src1, Pred)); |
366 } | 366 } |
367 void _trap() { Context.insert(InstARM32Trap::create(Func)); } | 367 void _trap() { Context.insert(InstARM32Trap::create(Func)); } |
368 void _udiv(Variable *Dest, Variable *Src0, Variable *Src1, | 368 void _udiv(Variable *Dest, Variable *Src0, Variable *Src1, |
369 CondARM32::Cond Pred = CondARM32::AL) { | 369 CondARM32::Cond Pred = CondARM32::AL) { |
370 Context.insert(InstARM32Udiv::create(Func, Dest, Src0, Src1, Pred)); | 370 Context.insert(InstARM32Udiv::create(Func, Dest, Src0, Src1, Pred)); |
371 } | 371 } |
372 void _umull(Variable *DestLo, Variable *DestHi, Variable *Src0, | 372 void _umull(Variable *DestLo, Variable *DestHi, Variable *Src0, |
373 Variable *Src1, CondARM32::Cond Pred = CondARM32::AL) { | 373 Variable *Src1, CondARM32::Cond Pred = CondARM32::AL) { |
374 Context.insert( | 374 Context.insert( |
375 InstARM32Umull::create(Func, DestLo, DestHi, Src0, Src1, Pred)); | 375 InstARM32Umull::create(Func, DestLo, DestHi, Src0, Src1, Pred)); |
376 // Model the modification to the second dest as a fake def. | 376 // Model the modification to the second dest as a fake def. |
377 // Note that the def is not predicated. | 377 // Note that the def is not predicated. |
378 Context.insert(InstFakeDef::create(Func, DestHi, DestLo)); | 378 Context.insert(InstFakeDef::create(Func, DestHi, DestLo)); |
379 } | 379 } |
380 void _uxt(Variable *Dest, Variable *Src0, | 380 void _uxt(Variable *Dest, Variable *Src0, |
381 CondARM32::Cond Pred = CondARM32::AL) { | 381 CondARM32::Cond Pred = CondARM32::AL) { |
382 Context.insert(InstARM32Uxt::create(Func, Dest, Src0, Pred)); | 382 Context.insert(InstARM32Uxt::create(Func, Dest, Src0, Pred)); |
383 } | 383 } |
| 384 void _vadd(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 385 Context.insert(InstARM32Vadd::create(Func, Dest, Src0, Src1)); |
| 386 } |
| 387 void _vdiv(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 388 Context.insert(InstARM32Vdiv::create(Func, Dest, Src0, Src1)); |
| 389 } |
| 390 void _vldr(Variable *Dest, OperandARM32Mem *Src, |
| 391 CondARM32::Cond Pred = CondARM32::AL) { |
| 392 Context.insert(InstARM32Vldr::create(Func, Dest, Src, Pred)); |
| 393 } |
| 394 // There are a whole bunch of vmov variants, to transfer within |
| 395 // S/D/Q registers, between core integer registers and S/D, |
| 396 // and from small immediates into S/D. |
| 397 // For integer -> S/D/Q there is a variant which takes two integer |
| 398 // register to fill a D, or to fill two consecutive S registers. |
| 399 // Vmov can also be used to insert-element. E.g., |
| 400 // "vmov.8 d0[1], r0" |
| 401 // but insert-element is a "two-address" operation where only part of the |
| 402 // register is modified. This cannot model that. |
| 403 // |
| 404 // This represents the simple single source, single dest variants only. |
| 405 void _vmov(Variable *Dest, Operand *Src0) { |
| 406 constexpr CondARM32::Cond Pred = CondARM32::AL; |
| 407 Context.insert(InstARM32Vmov::create(Func, Dest, Src0, Pred)); |
| 408 } |
| 409 void _vmul(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 410 Context.insert(InstARM32Vmul::create(Func, Dest, Src0, Src1)); |
| 411 } |
| 412 void _vsqrt(Variable *Dest, Variable *Src, |
| 413 CondARM32::Cond Pred = CondARM32::AL) { |
| 414 Context.insert(InstARM32Vsqrt::create(Func, Dest, Src, Pred)); |
| 415 } |
| 416 void _vsub(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 417 Context.insert(InstARM32Vsub::create(Func, Dest, Src0, Src1)); |
| 418 } |
384 | 419 |
385 /// Run a pass through stack variables and ensure that the offsets are legal. | 420 /// Run a pass through stack variables and ensure that the offsets are legal. |
386 /// If the offset is not legal, use a new base register that accounts for | 421 /// If the offset is not legal, use a new base register that accounts for |
387 /// the offset, such that the addressing mode offset bits are now legal. | 422 /// the offset, such that the addressing mode offset bits are now legal. |
388 void legalizeStackSlots(); | 423 void legalizeStackSlots(); |
389 /// Returns true if the given Offset can be represented in a stack ldr/str. | 424 /// Returns true if the given Offset can be represented in a stack ldr/str. |
390 bool isLegalVariableStackOffset(int32_t Offset) const; | 425 bool isLegalVariableStackOffset(int32_t Offset) const; |
391 /// Assuming Var needs its offset legalized, define a new base register | 426 /// Assuming Var needs its offset legalized, define a new base register |
392 /// centered on the given Var's offset and use it. | 427 /// centered on the given Var's offset and use it. |
393 StackVariable *legalizeVariableSlot(Variable *Var, Variable *OrigBaseReg); | 428 StackVariable *legalizeVariableSlot(Variable *Var, Variable *OrigBaseReg); |
(...skipping 16 matching lines...) Expand all Loading... |
410 /// start with registers but extend beyond the available registers can be | 445 /// start with registers but extend beyond the available registers can be |
411 /// split between the registers and the stack. However, this is typically | 446 /// split between the registers and the stack. However, this is typically |
412 /// for passing GPR structs by value, and PNaCl transforms expand this out. | 447 /// for passing GPR structs by value, and PNaCl transforms expand this out. |
413 /// | 448 /// |
414 /// Also, at the point before the call, the stack must be aligned. | 449 /// Also, at the point before the call, the stack must be aligned. |
415 class CallingConv { | 450 class CallingConv { |
416 CallingConv(const CallingConv &) = delete; | 451 CallingConv(const CallingConv &) = delete; |
417 CallingConv &operator=(const CallingConv &) = delete; | 452 CallingConv &operator=(const CallingConv &) = delete; |
418 | 453 |
419 public: | 454 public: |
420 CallingConv() : NumGPRRegsUsed(0) {} | 455 CallingConv() {} |
421 ~CallingConv() = default; | 456 ~CallingConv() = default; |
422 | 457 |
423 bool I64InRegs(std::pair<int32_t, int32_t> *Regs); | 458 bool I64InRegs(std::pair<int32_t, int32_t> *Regs); |
424 bool I32InReg(int32_t *Reg); | 459 bool I32InReg(int32_t *Reg); |
| 460 bool FPInReg(Type Ty, int32_t *Reg); |
425 | 461 |
426 static constexpr uint32_t ARM32_MAX_GPR_ARG = 4; | 462 static constexpr uint32_t ARM32_MAX_GPR_ARG = 4; |
| 463 // Units of S registers still available to S/D/Q arguments. |
| 464 static constexpr uint32_t ARM32_MAX_FP_REG_UNITS = 16; |
427 | 465 |
428 private: | 466 private: |
429 uint32_t NumGPRRegsUsed; | 467 uint32_t NumGPRRegsUsed = 0; |
| 468 uint32_t NumFPRegUnits = 0; |
430 }; | 469 }; |
431 | 470 |
432 private: | 471 private: |
433 ~TargetARM32() override = default; | 472 ~TargetARM32() override = default; |
434 }; | 473 }; |
435 | 474 |
436 class TargetDataARM32 final : public TargetDataLowering { | 475 class TargetDataARM32 final : public TargetDataLowering { |
437 TargetDataARM32() = delete; | 476 TargetDataARM32() = delete; |
438 TargetDataARM32(const TargetDataARM32 &) = delete; | 477 TargetDataARM32(const TargetDataARM32 &) = delete; |
439 TargetDataARM32 &operator=(const TargetDataARM32 &) = delete; | 478 TargetDataARM32 &operator=(const TargetDataARM32 &) = delete; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 | 512 |
474 private: | 513 private: |
475 ~TargetHeaderARM32() = default; | 514 ~TargetHeaderARM32() = default; |
476 | 515 |
477 TargetARM32Features CPUFeatures; | 516 TargetARM32Features CPUFeatures; |
478 }; | 517 }; |
479 | 518 |
480 } // end of namespace Ice | 519 } // end of namespace Ice |
481 | 520 |
482 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H | 521 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H |
OLD | NEW |