Home | History | Annotate | Download | only in test
      1 // Copyright 2016, VIXL authors
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are met:
      6 //
      7 //   * Redistributions of source code must retain the above copyright notice,
      8 //     this list of conditions and the following disclaimer.
      9 //   * Redistributions in binary form must reproduce the above copyright notice,
     10 //     this list of conditions and the following disclaimer in the documentation
     11 //     and/or other materials provided with the distribution.
     12 //   * Neither the name of ARM Limited nor the names of its contributors may be
     13 //     used to endorse or promote products derived from this software without
     14 //     specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
     17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
     20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 
     27 #include <stdlib.h>
     28 
     29 #include "test-runner.h"
     30 
     31 #ifdef VIXL_INCLUDE_TARGET_AARCH32
     32 #include "aarch32/macro-assembler-aarch32.h"
     33 #endif
     34 
     35 #ifdef VIXL_INCLUDE_TARGET_AARCH64
     36 #include "aarch64/macro-assembler-aarch64.h"
     37 #endif
     38 
     39 #define STRINGIFY(x) #x
     40 
     41 #define TEST_AARCH32(Name)                                                \
     42   namespace aarch32 {                                                     \
     43   void Test_##Name##_AArch32_Impl();                                      \
     44   }                                                                       \
     45   void Test_##Name##_AArch32() { aarch32::Test_##Name##_AArch32_Impl(); } \
     46   Test test_##Name##_AArch32(STRINGIFY(AARCH32_SCRATCH_##Name),           \
     47                              &Test_##Name##_AArch32);                     \
     48   void aarch32::Test_##Name##_AArch32_Impl()
     49 
     50 #define TEST_AARCH64(Name)                                                \
     51   namespace aarch64 {                                                     \
     52   void Test_##Name##_AArch64_Impl();                                      \
     53   }                                                                       \
     54   void Test_##Name##_AArch64() { aarch64::Test_##Name##_AArch64_Impl(); } \
     55   Test test_##Name##_AArch64(STRINGIFY(AARCH64_SCRATCH_##Name),           \
     56                              &Test_##Name##_AArch64);                     \
     57   void aarch64::Test_##Name##_AArch64_Impl()
     58 
     59 #define SETUP() MacroAssembler masm
     60 
     61 #define __ masm.
     62 
     63 namespace vixl {
     64 
     65 // UseScratchRegisterScopes must be able to nest perfectly. That is, they may
     66 // nest, but nested scopes must not outlive less-nested scopes.
     67 template <typename MacroAssembler, typename UseScratchRegisterScope>
     68 class PerfectNestingTestHelper {
     69  public:
     70   explicit PerfectNestingTestHelper(MacroAssembler* masm) : masm_(masm) {
     71     uint16_t seed[3] = {4, 5, 6};
     72     seed48(seed);
     73   }
     74   void Run() {
     75     UseScratchRegisterScope* top_scope =
     76         masm_->GetCurrentScratchRegisterScope();
     77     int descendents = 0;
     78     while (descendents < kMinimumDescendentScopeCount) descendents += Run(0);
     79     VIXL_CHECK(masm_->GetCurrentScratchRegisterScope() == top_scope);
     80   }
     81 
     82  private:
     83   int Run(int depth) {
     84     // As the depth increases, the probability of recursion decreases.
     85     // At depth = kDepthLimit, we never recurse.
     86     int max_children = static_cast<int>(std::abs(mrand48()) % kDepthLimit);
     87     int children = std::max(0, max_children - depth);
     88     int descendents = children;
     89     while (children-- > 0) {
     90       UseScratchRegisterScope scope(masm_);
     91       VIXL_CHECK(masm_->GetCurrentScratchRegisterScope() == &scope);
     92       descendents += Run(depth + 1);
     93       VIXL_CHECK(masm_->GetCurrentScratchRegisterScope() == &scope);
     94     }
     95     return descendents;
     96   }
     97 
     98   MacroAssembler* masm_;
     99   static const int kDepthLimit = 12;
    100   static const int kMinimumDescendentScopeCount = 10000;
    101 };
    102 
    103 #ifdef VIXL_INCLUDE_TARGET_AARCH32
    104 TEST_AARCH32(perfect_nesting) {
    105   SETUP();
    106   PerfectNestingTestHelper<MacroAssembler, UseScratchRegisterScope>(&masm)
    107       .Run();
    108 }
    109 #endif  // VIXL_INCLUDE_TARGET_AARCH32
    110 
    111 #ifdef VIXL_INCLUDE_TARGET_AARCH64
    112 TEST_AARCH64(perfect_nesting) {
    113   SETUP();
    114   PerfectNestingTestHelper<MacroAssembler, UseScratchRegisterScope>(&masm)
    115       .Run();
    116 }
    117 #endif  // VIXL_INCLUDE_TARGET_AARCH64
    118 
    119 
    120 #ifdef VIXL_INCLUDE_TARGET_AARCH32
    121 TEST_AARCH32(v_registers) {
    122   SETUP();
    123   {
    124     UseScratchRegisterScope temps(&masm);
    125     temps.Include(VRegisterList(q0, q1, q2, q3));
    126 
    127     // This test assumes that low-numbered registers are allocated first. The
    128     // implementation is allowed to use a different strategy; if it does, the
    129     // test will need to be updated.
    130     // TODO: Write more flexible (and thorough) tests.
    131 
    132     VIXL_CHECK(q0.Is(temps.AcquireQ()));
    133     VIXL_CHECK(!temps.IsAvailable(q0));
    134     VIXL_CHECK(!temps.IsAvailable(d0));
    135     VIXL_CHECK(!temps.IsAvailable(d1));
    136     VIXL_CHECK(!temps.IsAvailable(s0));
    137     VIXL_CHECK(!temps.IsAvailable(s1));
    138     VIXL_CHECK(!temps.IsAvailable(s2));
    139     VIXL_CHECK(!temps.IsAvailable(s3));
    140 
    141     VIXL_CHECK(d2.Is(temps.AcquireV(64)));
    142     VIXL_CHECK(!temps.IsAvailable(q1));
    143     VIXL_CHECK(!temps.IsAvailable(d2));
    144     VIXL_CHECK(temps.IsAvailable(d3));
    145     VIXL_CHECK(!temps.IsAvailable(s4));
    146     VIXL_CHECK(!temps.IsAvailable(s5));
    147     VIXL_CHECK(temps.IsAvailable(s6));
    148     VIXL_CHECK(temps.IsAvailable(s7));
    149 
    150     VIXL_CHECK(s6.Is(temps.AcquireS()));
    151     VIXL_CHECK(!temps.IsAvailable(d3));
    152     VIXL_CHECK(!temps.IsAvailable(s6));
    153     VIXL_CHECK(temps.IsAvailable(s7));
    154 
    155     VIXL_CHECK(q2.Is(temps.AcquireV(128)));
    156     VIXL_CHECK(!temps.IsAvailable(q2));
    157     VIXL_CHECK(!temps.IsAvailable(d4));
    158     VIXL_CHECK(!temps.IsAvailable(d5));
    159     VIXL_CHECK(!temps.IsAvailable(s8));
    160     VIXL_CHECK(!temps.IsAvailable(s9));
    161     VIXL_CHECK(!temps.IsAvailable(s10));
    162     VIXL_CHECK(!temps.IsAvailable(s11));
    163     VIXL_CHECK(temps.IsAvailable(s7));
    164 
    165     VIXL_CHECK(d6.Is(temps.AcquireD()));
    166     VIXL_CHECK(!temps.IsAvailable(q3));
    167     VIXL_CHECK(!temps.IsAvailable(d6));
    168     VIXL_CHECK(temps.IsAvailable(d7));
    169     VIXL_CHECK(!temps.IsAvailable(s12));
    170     VIXL_CHECK(!temps.IsAvailable(s13));
    171     VIXL_CHECK(temps.IsAvailable(s14));
    172     VIXL_CHECK(temps.IsAvailable(s15));
    173     VIXL_CHECK(temps.IsAvailable(s7));
    174 
    175     VIXL_CHECK(s7.Is(temps.AcquireS()));
    176   }
    177 }
    178 #endif  // VIXL_INCLUDE_TARGET_AARCH32
    179 
    180 
    181 #ifdef VIXL_INCLUDE_TARGET_AARCH32
    182 TEST_AARCH32(include_exclude) {
    183   SETUP();
    184   {
    185     UseScratchRegisterScope temps(&masm);
    186     temps.Include(r0, r1, r2, r3);
    187     temps.Include(s0, s1, d1, q1);
    188 
    189     VIXL_CHECK(temps.IsAvailable(r0));
    190     VIXL_CHECK(temps.IsAvailable(r1));
    191     VIXL_CHECK(temps.IsAvailable(r2));
    192     VIXL_CHECK(temps.IsAvailable(r3));
    193 
    194     VIXL_CHECK(temps.IsAvailable(s0));
    195 
    196     VIXL_CHECK(temps.IsAvailable(s1));
    197 
    198     VIXL_CHECK(temps.IsAvailable(d1));
    199     VIXL_CHECK(temps.IsAvailable(s2));
    200     VIXL_CHECK(temps.IsAvailable(s3));
    201 
    202     VIXL_CHECK(temps.IsAvailable(q1));
    203     VIXL_CHECK(temps.IsAvailable(d2));
    204     VIXL_CHECK(temps.IsAvailable(d3));
    205     VIXL_CHECK(temps.IsAvailable(s4));
    206     VIXL_CHECK(temps.IsAvailable(s5));
    207     VIXL_CHECK(temps.IsAvailable(s6));
    208     VIXL_CHECK(temps.IsAvailable(s7));
    209 
    210     // Test local exclusion.
    211     {
    212       UseScratchRegisterScope local_temps(&masm);
    213       local_temps.Exclude(r1, r2);
    214       local_temps.Exclude(s1, q1);
    215 
    216       VIXL_CHECK(temps.IsAvailable(r0));
    217       VIXL_CHECK(!temps.IsAvailable(r1));
    218       VIXL_CHECK(!temps.IsAvailable(r2));
    219       VIXL_CHECK(temps.IsAvailable(r3));
    220 
    221       VIXL_CHECK(temps.IsAvailable(s0));
    222 
    223       VIXL_CHECK(!temps.IsAvailable(s1));
    224 
    225       VIXL_CHECK(temps.IsAvailable(d1));
    226       VIXL_CHECK(temps.IsAvailable(s2));
    227       VIXL_CHECK(temps.IsAvailable(s3));
    228 
    229       VIXL_CHECK(!temps.IsAvailable(q1));
    230       VIXL_CHECK(!temps.IsAvailable(d2));
    231       VIXL_CHECK(!temps.IsAvailable(d3));
    232       VIXL_CHECK(!temps.IsAvailable(s4));
    233       VIXL_CHECK(!temps.IsAvailable(s5));
    234       VIXL_CHECK(!temps.IsAvailable(s6));
    235       VIXL_CHECK(!temps.IsAvailable(s7));
    236     }
    237 
    238     // This time, exclude part of included registers, making sure the entire
    239     // register gets excluded.
    240     {
    241       UseScratchRegisterScope local_temps(&masm);
    242       local_temps.Exclude(s2, d3);
    243 
    244       VIXL_CHECK(temps.IsAvailable(r0));
    245       VIXL_CHECK(temps.IsAvailable(r1));
    246       VIXL_CHECK(temps.IsAvailable(r2));
    247       VIXL_CHECK(temps.IsAvailable(r3));
    248 
    249       VIXL_CHECK(temps.IsAvailable(s0));
    250 
    251       VIXL_CHECK(temps.IsAvailable(s1));
    252 
    253       // Excluding s2 should exclude d1 but not s3.
    254       VIXL_CHECK(!temps.IsAvailable(d1));
    255       VIXL_CHECK(!temps.IsAvailable(s2));
    256       VIXL_CHECK(temps.IsAvailable(s3));
    257 
    258       // Excluding d3 should exclude q1, s7 and s6 but not d2, s5, s4.
    259       VIXL_CHECK(!temps.IsAvailable(q1));
    260       VIXL_CHECK(temps.IsAvailable(d2));
    261       VIXL_CHECK(!temps.IsAvailable(d3));
    262       VIXL_CHECK(temps.IsAvailable(s4));
    263       VIXL_CHECK(temps.IsAvailable(s5));
    264       VIXL_CHECK(!temps.IsAvailable(s6));
    265       VIXL_CHECK(!temps.IsAvailable(s7));
    266     }
    267 
    268     // Make sure the initial state was restored.
    269 
    270     VIXL_CHECK(temps.IsAvailable(r0));
    271     VIXL_CHECK(temps.IsAvailable(r1));
    272     VIXL_CHECK(temps.IsAvailable(r2));
    273     VIXL_CHECK(temps.IsAvailable(r3));
    274 
    275     VIXL_CHECK(temps.IsAvailable(s0));
    276 
    277     VIXL_CHECK(temps.IsAvailable(s1));
    278 
    279     VIXL_CHECK(temps.IsAvailable(d1));
    280     VIXL_CHECK(temps.IsAvailable(s2));
    281     VIXL_CHECK(temps.IsAvailable(s3));
    282 
    283     VIXL_CHECK(temps.IsAvailable(q1));
    284     VIXL_CHECK(temps.IsAvailable(d2));
    285     VIXL_CHECK(temps.IsAvailable(d3));
    286     VIXL_CHECK(temps.IsAvailable(s4));
    287     VIXL_CHECK(temps.IsAvailable(s5));
    288     VIXL_CHECK(temps.IsAvailable(s6));
    289     VIXL_CHECK(temps.IsAvailable(s7));
    290   }
    291 }
    292 #endif  // VIXL_INCLUDE_TARGET_AARCH32
    293 
    294 }  // namespace vixl
    295