| 52 | } |
| 53 | |
| 54 | AddressMode SelectAddressMode(IREmitter* IREmit, AddressMode A, IR::OpSize GPRSize, bool HostSupportsTSOImm9, bool AtomicTSO, bool Vector, |
| 55 | IR::OpSize AccessSize) { |
| 56 | const auto Is32Bit = GPRSize == OpSize::i32Bit; |
| 57 | const auto GPRSizeMatchesAddrSize = A.AddrSize == GPRSize; |
| 58 | const auto OffsetIndexToLargeFor32Bit = Is32Bit && (A.Offset <= -16384 || A.Offset >= 16384); |
| 59 | if (!GPRSizeMatchesAddrSize || OffsetIndexToLargeFor32Bit) { |
| 60 | // If address size doesn't match GPR size then no optimizations can occur. |
| 61 | return { |
| 62 | .Base = LoadEffectiveAddress(IREmit, A, GPRSize, true), |
| 63 | .Index = IREmit->Invalid(), |
| 64 | }; |
| 65 | } |
| 66 | |
| 67 | // Loadstore rules: |
| 68 | // Non-TSO GPR: |
| 69 | // * LDR/STR: [Reg] |
| 70 | // * LDR/STR: [Reg + Reg, {Shift <AccessSize>}] |
| 71 | // * Can't use with 32-bit |
| 72 | // * LDR/STR: [Reg + [0,4095] * <AccessSize>] |
| 73 | // * Imm must be smaller than 16k with 32-bit |
| 74 | // * LDUR/STUR: [Reg + [-256, 255]] |
| 75 | // |
| 76 | // TSO GPR: |
| 77 | // * ARMv8.0: |
| 78 | // LDAR/STLR: [Reg] |
| 79 | // * FEAT_LRCPC: |
| 80 | // LDAPR: [Reg] |
| 81 | // * FEAT_LRCPC2: |
| 82 | // LDAPUR/STLUR: [Reg + [-256, 255]] |
| 83 | // |
| 84 | // Non-TSO Vector: |
| 85 | // * LDR/STR: [Reg + [0,4095] * <AccessSize>] |
| 86 | // * LDUR/STUR: [Reg + [-256,255]] |
| 87 | // |
| 88 | // TSO Vector: |
| 89 | // * ARMv8.0: |
| 90 | // Just DMB + previous |
| 91 | // * FEAT_LRCPC3 (Unsupported by FEXCore currently): |
| 92 | // LDAPUR/STLUR: [Reg + [-256,255]] |
| 93 | |
| 94 | const auto AccessSizeAsImm = OpSizeToSize(AccessSize); |
| 95 | const bool OffsetIsSIMM9 = A.Offset && A.Offset >= -256 && A.Offset <= 255; |
| 96 | const bool OffsetIsUnsignedScaled = A.Offset > 0 && (A.Offset & (AccessSizeAsImm - 1)) == 0 && (A.Offset / AccessSizeAsImm) <= 4095; |
| 97 | |
| 98 | if ((AtomicTSO && !Vector && HostSupportsTSOImm9 && OffsetIsSIMM9) || (!AtomicTSO && (OffsetIsSIMM9 || OffsetIsUnsignedScaled))) { |
| 99 | // Peel off the offset |
| 100 | AddressMode B = A; |
| 101 | B.Offset = 0; |
| 102 | |
| 103 | return { |
| 104 | .Base = LoadEffectiveAddress(IREmit, B, GPRSize, true /* AddSegmentBase */, false), |
| 105 | .Index = IREmit->Constant(A.Offset), |
| 106 | .IndexType = MEM_OFFSET_SXTX, |
| 107 | .IndexScale = 1, |
| 108 | }; |
| 109 | } |
| 110 | |
| 111 | if (AtomicTSO) { |
no test coverage detected