|
133 | 133 | (Isb) |
134 | 134 | (Clrex))) |
135 | 135 |
|
| 136 | +;; Access width for exclusive / acquire-release memory operations. `DWord` |
| 137 | +;; (64-bit) uses an even/odd register pair and is only valid on the paired |
| 138 | +;; exclusive instructions. |
| 139 | +(type AtomicSize |
| 140 | + (enum |
| 141 | + (Byte) |
| 142 | + (Half) |
| 143 | + (Word) |
| 144 | + (DWord))) |
| 145 | + |
136 | 146 | ;; The precision of a VFP floating-point operation. |
137 | 147 | (type FpuSize |
138 | 148 | (enum |
|
297 | 307 | ;; Load/store multiple, increment-after (`ldmia`/`stmia rn{!}, {list}`). |
298 | 308 | (LdmStm (load bool) (rn Reg) (writeback bool) (reg_list u32)) |
299 | 309 |
|
300 | | - ;; Load-exclusive (`ldrex`) or load-acquire-exclusive (`ldaex`). |
301 | | - (LoadEx (acquire bool) (rt WritableReg) (rn Reg)) |
302 | | - ;; Store-exclusive (`strex`) or store-release-exclusive (`stlex`); `rd` |
303 | | - ;; receives the success flag. |
304 | | - (StoreEx (acquire bool) (rd WritableReg) (rt Reg) (rn Reg)) |
305 | | - ;; Load-acquire (`lda rt, [rn]`). |
306 | | - (LoadAcq (rt WritableReg) (rn Reg)) |
307 | | - ;; Store-release (`stl rt, [rn]`). |
308 | | - (StoreRel (rt Reg) (rn Reg)) |
| 310 | + ;; Load-exclusive (`ldrex{b,h}`) or load-acquire-exclusive (`ldaex{b,h}`). |
| 311 | + (LoadEx (acquire bool) (size AtomicSize) (rt WritableReg) (rn Reg)) |
| 312 | + ;; Store-exclusive (`strex{b,h}`) or store-release-exclusive |
| 313 | + ;; (`stlex{b,h}`); `rd` receives the success flag. |
| 314 | + (StoreEx (acquire bool) (size AtomicSize) (rd WritableReg) (rt Reg) (rn Reg)) |
| 315 | + ;; Load-acquire (`lda{b,h} rt, [rn]`). |
| 316 | + (LoadAcq (size AtomicSize) (rt WritableReg) (rn Reg)) |
| 317 | + ;; Store-release (`stl{b,h} rt, [rn]`). |
| 318 | + (StoreRel (size AtomicSize) (rt Reg) (rn Reg)) |
309 | 319 |
|
310 | 320 | ;; A memory barrier / clear-exclusive. |
311 | 321 | (Barrier (op BarrierOp)) |
312 | 322 |
|
313 | | - ;; An atomic read-modify-write loop over a 32-bit word: |
314 | | - ;; loop: ldaex rd, [addr]; <op> tmp1, rd, operand; |
315 | | - ;; stlex tmp2, tmp1, [addr]; cmp tmp2, #0; bne loop |
316 | | - ;; `rd` receives the old value. |
317 | | - (AtomicRmw (op AtomicRmwOp) (rd WritableReg) (addr Reg) (operand Reg) |
318 | | - (tmp1 WritableReg) (tmp2 WritableReg)) |
319 | | - ;; An atomic compare-and-swap loop over a 32-bit word; `rd` receives the |
320 | | - ;; old value. |
321 | | - (AtomicCas (rd WritableReg) (addr Reg) (expected Reg) (new Reg) (tmp WritableReg)) |
| 323 | + ;; An atomic read-modify-write loop over a `size`-wide location: |
| 324 | + ;; loop: ldaex{,b,h} rd, [addr]; <op> tmp1, rd, operand; |
| 325 | + ;; stlex{,b,h} tmp2, tmp1, [addr]; cmp tmp2, #0; bne loop |
| 326 | + ;; `rd` receives the (zero-extended) old value. |
| 327 | + (AtomicRmw (op AtomicRmwOp) (size AtomicSize) (rd WritableReg) (addr Reg) |
| 328 | + (operand Reg) (tmp1 WritableReg) (tmp2 WritableReg)) |
| 329 | + ;; An atomic compare-and-swap loop over a `size`-wide location; `rd` |
| 330 | + ;; receives the (zero-extended) old value. |
| 331 | + (AtomicCas (size AtomicSize) (rd WritableReg) (addr Reg) (expected Reg) |
| 332 | + (new Reg) (tmp WritableReg)) |
| 333 | + |
| 334 | + ;; A 64-bit atomic read-modify-write loop using the paired exclusive |
| 335 | + ;; instructions (`ldaexd`/`stlexd`). The old value is returned in |
| 336 | + ;; (rd_lo, rd_hi). All registers are pinned to a fixed even/odd layout in |
| 337 | + ;; the operand collector because A32 exclusive-pair instructions require |
| 338 | + ;; consecutive even/odd register pairs, which regalloc2 cannot model. |
| 339 | + (AtomicRmw64 (op AtomicRmwOp) (rd_lo WritableReg) (rd_hi WritableReg) |
| 340 | + (addr Reg) (operand_lo Reg) (operand_hi Reg) |
| 341 | + (tmp_new_lo WritableReg) (tmp_new_hi WritableReg) |
| 342 | + (tmp_res WritableReg)) |
| 343 | + ;; A 64-bit atomic compare-and-swap loop; the old value is in (rd_lo, rd_hi). |
| 344 | + (AtomicCas64 (rd_lo WritableReg) (rd_hi WritableReg) (addr Reg) |
| 345 | + (expected_lo Reg) (expected_hi Reg) (new_lo Reg) (new_hi Reg) |
| 346 | + (tmp_res WritableReg)) |
| 347 | + ;; A 64-bit sequentially-consistent atomic load (`ldaexd` + `clrex`). |
| 348 | + (AtomicLoad64 (rd_lo WritableReg) (rd_hi WritableReg) (addr Reg)) |
| 349 | + ;; A 64-bit sequentially-consistent atomic store via an `ldaexd`/`stlexd` |
| 350 | + ;; retry loop; the loaded value is discarded into (scratch_lo, scratch_hi). |
| 351 | + (AtomicStore64 (addr Reg) (src_lo Reg) (src_hi Reg) |
| 352 | + (scratch_lo WritableReg) (scratch_hi WritableReg) |
| 353 | + (tmp_res WritableReg)) |
322 | 354 |
|
323 | 355 | ;; A three-register VFP op (`vadd`/`vsub`/`vmul`/`vdiv`). |
324 | 356 | (FpuRRR (op FpuOp3) (size FpuSize) (rd WritableReg) (rn Reg) (rm Reg)) |
|
550 | 582 | (rule (dmb) |
551 | 583 | (SideEffectNoResult.Inst (MInst.Barrier (BarrierOp.Dmb)))) |
552 | 584 |
|
553 | | -;;;; Atomics (32-bit) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 585 | +;;;; Atomics (8/16/32-bit) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
554 | 586 |
|
555 | | -(decl atomic_rmw_i32 (AtomicRmwOp Reg Reg) Reg) |
556 | | -(rule (atomic_rmw_i32 op addr operand) |
| 587 | +;; Map a scalar integer type to the exclusive-access width. |
| 588 | +(decl atomic_size (Type) AtomicSize) |
| 589 | +(rule (atomic_size $I8) (AtomicSize.Byte)) |
| 590 | +(rule (atomic_size $I16) (AtomicSize.Half)) |
| 591 | +(rule (atomic_size $I32) (AtomicSize.Word)) |
| 592 | + |
| 593 | +(decl atomic_rmw_size (Type AtomicRmwOp Reg Reg) Reg) |
| 594 | +(rule (atomic_rmw_size ty op addr operand) |
557 | 595 | (let ((rd WritableReg (temp_writable_reg $I32)) |
558 | 596 | (tmp1 WritableReg (temp_writable_reg $I32)) |
559 | 597 | (tmp2 WritableReg (temp_writable_reg $I32)) |
560 | | - (_ Unit (emit (MInst.AtomicRmw op rd addr operand tmp1 tmp2)))) |
| 598 | + (_ Unit (emit (MInst.AtomicRmw op (atomic_size ty) rd addr operand tmp1 tmp2)))) |
561 | 599 | rd)) |
562 | 600 |
|
563 | | -(decl atomic_cas_i32 (Reg Reg Reg) Reg) |
564 | | -(rule (atomic_cas_i32 addr expected new) |
| 601 | +(decl atomic_cas_size (Type Reg Reg Reg) Reg) |
| 602 | +(rule (atomic_cas_size ty addr expected new) |
565 | 603 | (let ((rd WritableReg (temp_writable_reg $I32)) |
566 | 604 | (tmp WritableReg (temp_writable_reg $I32)) |
567 | | - (_ Unit (emit (MInst.AtomicCas rd addr expected new tmp)))) |
| 605 | + (_ Unit (emit (MInst.AtomicCas (atomic_size ty) rd addr expected new tmp)))) |
568 | 606 | rd)) |
569 | 607 |
|
570 | 608 | ;; Sequentially-consistent load/store via load-acquire / store-release. |
571 | | -(decl atomic_load_i32 (Reg) Reg) |
572 | | -(rule (atomic_load_i32 addr) |
| 609 | +(decl atomic_load_size (Type Reg) Reg) |
| 610 | +(rule (atomic_load_size ty addr) |
573 | 611 | (let ((rd WritableReg (temp_writable_reg $I32)) |
574 | | - (_ Unit (emit (MInst.LoadAcq rd addr)))) |
575 | | - rd)) |
576 | | - |
577 | | -(decl atomic_store_i32 (Reg Reg) InstOutput) |
578 | | -(rule (atomic_store_i32 src addr) |
579 | | - (side_effect (SideEffectNoResult.Inst (MInst.StoreRel src addr)))) |
| 612 | + (_ Unit (emit (MInst.LoadAcq (atomic_size ty) rd addr)))) |
| 613 | + rd)) |
| 614 | + |
| 615 | +(decl atomic_store_size (Type Reg Reg) InstOutput) |
| 616 | +(rule (atomic_store_size ty src addr) |
| 617 | + (side_effect (SideEffectNoResult.Inst (MInst.StoreRel (atomic_size ty) src addr)))) |
| 618 | + |
| 619 | +;;;; Atomics (64-bit) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 620 | + |
| 621 | +(decl atomic_rmw_i64 (AtomicRmwOp Reg ValueRegs) ValueRegs) |
| 622 | +(rule (atomic_rmw_i64 op addr operand) |
| 623 | + (let ((rd_lo WritableReg (temp_writable_reg $I32)) |
| 624 | + (rd_hi WritableReg (temp_writable_reg $I32)) |
| 625 | + (nl WritableReg (temp_writable_reg $I32)) |
| 626 | + (nh WritableReg (temp_writable_reg $I32)) |
| 627 | + (res WritableReg (temp_writable_reg $I32)) |
| 628 | + (_ Unit (emit (MInst.AtomicRmw64 op rd_lo rd_hi addr |
| 629 | + (vr_lo operand) (vr_hi operand) nl nh res)))) |
| 630 | + (value_regs (writable_reg_to_reg rd_lo) (writable_reg_to_reg rd_hi)))) |
| 631 | + |
| 632 | +(decl atomic_cas_i64 (Reg ValueRegs ValueRegs) ValueRegs) |
| 633 | +(rule (atomic_cas_i64 addr expected new) |
| 634 | + (let ((rd_lo WritableReg (temp_writable_reg $I32)) |
| 635 | + (rd_hi WritableReg (temp_writable_reg $I32)) |
| 636 | + (res WritableReg (temp_writable_reg $I32)) |
| 637 | + (_ Unit (emit (MInst.AtomicCas64 rd_lo rd_hi addr |
| 638 | + (vr_lo expected) (vr_hi expected) |
| 639 | + (vr_lo new) (vr_hi new) res)))) |
| 640 | + (value_regs (writable_reg_to_reg rd_lo) (writable_reg_to_reg rd_hi)))) |
| 641 | + |
| 642 | +(decl atomic_load_i64 (Reg) ValueRegs) |
| 643 | +(rule (atomic_load_i64 addr) |
| 644 | + (let ((rd_lo WritableReg (temp_writable_reg $I32)) |
| 645 | + (rd_hi WritableReg (temp_writable_reg $I32)) |
| 646 | + (_ Unit (emit (MInst.AtomicLoad64 rd_lo rd_hi addr)))) |
| 647 | + (value_regs (writable_reg_to_reg rd_lo) (writable_reg_to_reg rd_hi)))) |
| 648 | + |
| 649 | +(decl atomic_store_i64 (ValueRegs Reg) InstOutput) |
| 650 | +(rule (atomic_store_i64 src addr) |
| 651 | + (let ((sl WritableReg (temp_writable_reg $I32)) |
| 652 | + (sh WritableReg (temp_writable_reg $I32)) |
| 653 | + (res WritableReg (temp_writable_reg $I32))) |
| 654 | + (side_effect (SideEffectNoResult.Inst |
| 655 | + (MInst.AtomicStore64 addr (vr_lo src) (vr_hi src) sl sh res))))) |
580 | 656 |
|
581 | 657 | ;;;; Floating point ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
582 | 658 |
|
|
0 commit comments