Home | History | Annotate | Download | only in test
      1 // Copyright 2014, ARM Limited
      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 <stdio.h>
     28 #include <float.h>
     29 
     30 #include "cctest.h"
     31 #include "test-utils-a64.h"
     32 #include "test-simulator-inputs-a64.h"
     33 #include "test-simulator-traces-a64.h"
     34 #include "a64/macro-assembler-a64.h"
     35 #include "a64/simulator-a64.h"
     36 
     37 namespace vixl {
     38 
     39 // ==== Simulator Tests ====
     40 //
     41 // These simulator tests check instruction behaviour against a trace taken from
     42 // real AArch64 hardware. The same test code is used to generate the trace; the
     43 // results are printed to stdout when the test is run with --sim_test_trace.
     44 //
     45 // The input lists and expected results are stored in
     46 // test/test-simulator-traces-a64.h. The expected results can be regenerated
     47 // using tools/generate_simulator_traces.py.
     48 
     49 #define __ masm.
     50 #define TEST(name)  TEST_(SIM_##name)
     51 
     52 #define BUF_SIZE (256)
     53 
     54 #ifdef USE_SIMULATOR
     55 
     56 #define SETUP()                                                               \
     57   byte* buf = new byte[BUF_SIZE];                                             \
     58   MacroAssembler masm(buf, BUF_SIZE);                                         \
     59   Decoder decoder;                                                            \
     60   Simulator* simulator = NULL;                                                \
     61   if (Cctest::run_debugger()) {                                               \
     62     simulator = new Debugger(&decoder);                                       \
     63   } else {                                                                    \
     64     simulator = new Simulator(&decoder);                                      \
     65     simulator->set_disasm_trace(Cctest::trace_sim());                         \
     66   }                                                                           \
     67   simulator->set_coloured_trace(Cctest::coloured_trace());                    \
     68   simulator->set_instruction_stats(Cctest::instruction_stats());
     69 
     70 #define START()                                                               \
     71   masm.Reset();                                                               \
     72   simulator->ResetState();                                                    \
     73   __ PushCalleeSavedRegisters();                                              \
     74   if (Cctest::run_debugger()) {                                               \
     75     if (Cctest::trace_reg()) {                                                \
     76       __ Trace(LOG_STATE, TRACE_ENABLE);                                      \
     77     }                                                                         \
     78     if (Cctest::trace_sim()) {                                                \
     79       __ Trace(LOG_DISASM, TRACE_ENABLE);                                     \
     80     }                                                                         \
     81   }                                                                           \
     82   if (Cctest::instruction_stats()) {                                          \
     83     __ EnableInstrumentation();                                               \
     84   }
     85 
     86 #define END()                                                                 \
     87   if (Cctest::instruction_stats()) {                                          \
     88     __ DisableInstrumentation();                                              \
     89   }                                                                           \
     90   if (Cctest::run_debugger()) {                                               \
     91     __ Trace(LOG_ALL, TRACE_DISABLE);                                         \
     92   }                                                                           \
     93   __ PopCalleeSavedRegisters();                                               \
     94   __ Ret();                                                                   \
     95   masm.FinalizeCode()
     96 
     97 #define RUN()                                                                 \
     98   simulator->RunFrom(reinterpret_cast<Instruction*>(buf))
     99 
    100 #define TEARDOWN()                                                            \
    101   delete simulator;                                                           \
    102   delete[] buf;
    103 
    104 #else     // USE_SIMULATOR
    105 
    106 #define SETUP()                                                               \
    107   byte* buf = new byte[BUF_SIZE];                                             \
    108   MacroAssembler masm(buf, BUF_SIZE);                                         \
    109   CPU::SetUp()
    110 
    111 #define START()                                                               \
    112   masm.Reset();                                                               \
    113   __ PushCalleeSavedRegisters()
    114 
    115 #define END()                                                                 \
    116   __ PopCalleeSavedRegisters();                                               \
    117   __ Ret();                                                                   \
    118   masm.FinalizeCode()
    119 
    120 #define RUN()                                                                 \
    121   CPU::EnsureIAndDCacheCoherency(buf, BUF_SIZE);                              \
    122   {                                                                           \
    123     void (*test_function)(void);                                              \
    124     VIXL_ASSERT(sizeof(buf) == sizeof(test_function));                        \
    125     memcpy(&test_function, &buf, sizeof(buf));                                \
    126     test_function();                                                          \
    127   }
    128 
    129 #define TEARDOWN()                                                            \
    130   delete[] buf;
    131 
    132 #endif    // USE_SIMULATOR
    133 
    134 
    135 // The maximum number of errors to report in detail for each test.
    136 static const unsigned kErrorReportLimit = 8;
    137 
    138 
    139 // Overloaded versions of rawbits_to_double and rawbits_to_float for use in the
    140 // templated test functions.
    141 static float rawbits_to_fp(uint32_t bits) {
    142   return rawbits_to_float(bits);
    143 }
    144 
    145 static double rawbits_to_fp(uint64_t bits) {
    146   return rawbits_to_double(bits);
    147 }
    148 
    149 
    150 // MacroAssembler member function pointers to pass to the test dispatchers.
    151 typedef void (MacroAssembler::*Test1OpFPHelper_t)(const FPRegister& fd,
    152                                                   const FPRegister& fn);
    153 typedef void (MacroAssembler::*Test2OpFPHelper_t)(const FPRegister& fd,
    154                                                   const FPRegister& fn,
    155                                                   const FPRegister& fm);
    156 typedef void (MacroAssembler::*Test3OpFPHelper_t)(const FPRegister& fd,
    157                                                   const FPRegister& fn,
    158                                                   const FPRegister& fm,
    159                                                   const FPRegister& fa);
    160 typedef void (MacroAssembler::*TestFPCmpHelper_t)(const FPRegister& fn,
    161                                                   const FPRegister& fm);
    162 typedef void (MacroAssembler::*TestFPCmpZeroHelper_t)(const FPRegister& fn,
    163                                                       double value);
    164 typedef void (MacroAssembler::*TestFPToIntHelper_t)(const Register& rd,
    165                                                     const FPRegister& fn);
    166 typedef void (MacroAssembler::*TestFixedToFPHelper_t)(const FPRegister& fd,
    167                                                       const Register& rn,
    168                                                       unsigned fbits);
    169 
    170 // Standard test dispatchers.
    171 
    172 
    173 static void Test1Op_Helper(Test1OpFPHelper_t helper, uintptr_t inputs,
    174                            unsigned inputs_length, uintptr_t results,
    175                            unsigned d_size, unsigned n_size) {
    176   VIXL_ASSERT((d_size == kDRegSize) || (d_size == kSRegSize));
    177   VIXL_ASSERT((n_size == kDRegSize) || (n_size == kSRegSize));
    178 
    179   SETUP();
    180   START();
    181 
    182   // Roll up the loop to keep the code size down.
    183   Label loop_n;
    184 
    185   Register out = x0;
    186   Register inputs_base = x1;
    187   Register length = w2;
    188   Register index_n = w3;
    189 
    190   const int n_index_shift =
    191       (n_size == kDRegSize) ? kDRegSizeInBytesLog2 : kSRegSizeInBytesLog2;
    192 
    193   FPRegister fd = (d_size == kDRegSize) ? d0 : s0;
    194   FPRegister fn = (n_size == kDRegSize) ? d1 : s1;
    195 
    196   __ Mov(out, results);
    197   __ Mov(inputs_base, inputs);
    198   __ Mov(length, inputs_length);
    199 
    200   __ Mov(index_n, 0);
    201   __ Bind(&loop_n);
    202   __ Ldr(fn, MemOperand(inputs_base, index_n, UXTW, n_index_shift));
    203 
    204   (masm.*helper)(fd, fn);
    205   __ Str(fd, MemOperand(out, fd.SizeInBytes(), PostIndex));
    206 
    207   __ Add(index_n, index_n, 1);
    208   __ Cmp(index_n, inputs_length);
    209   __ B(lo, &loop_n);
    210 
    211   END();
    212   RUN();
    213   TEARDOWN();
    214 }
    215 
    216 
    217 // Test FP instructions. The inputs[] and expected[] arrays should be arrays of
    218 // rawbits representations of doubles or floats. This ensures that exact bit
    219 // comparisons can be performed.
    220 template <typename Tn, typename Td>
    221 static void Test1Op(const char * name, Test1OpFPHelper_t helper,
    222                     const Tn inputs[], unsigned inputs_length,
    223                     const Td expected[], unsigned expected_length) {
    224   VIXL_ASSERT(inputs_length > 0);
    225 
    226   const unsigned results_length = inputs_length;
    227   Td * results = new Td[results_length];
    228 
    229   const unsigned d_bits = sizeof(Td) * 8;
    230   const unsigned n_bits = sizeof(Tn) * 8;
    231 
    232   Test1Op_Helper(helper, reinterpret_cast<uintptr_t>(inputs), inputs_length,
    233                  reinterpret_cast<uintptr_t>(results), d_bits, n_bits);
    234 
    235   if (Cctest::sim_test_trace()) {
    236     // Print the results.
    237     printf("const uint%u_t kExpected_%s[] = {\n", d_bits, name);
    238     for (unsigned d = 0; d < results_length; d++) {
    239       printf("  0x%0*" PRIx64 ",\n",
    240              d_bits / 4, static_cast<uint64_t>(results[d]));
    241     }
    242     printf("};\n");
    243     printf("const unsigned kExpectedCount_%s = %u;\n", name, results_length);
    244   } else {
    245     // Check the results.
    246     VIXL_CHECK(expected_length == results_length);
    247     unsigned error_count = 0;
    248     unsigned d = 0;
    249     for (unsigned n = 0; n < inputs_length; n++, d++) {
    250       if (results[d] != expected[d]) {
    251         if (++error_count > kErrorReportLimit) continue;
    252 
    253         printf("%s 0x%0*" PRIx64 " (%s %g):\n",
    254                name, n_bits / 4, static_cast<uint64_t>(inputs[n]),
    255                name, rawbits_to_fp(inputs[n]));
    256         printf("  Expected: 0x%0*" PRIx64 " (%g)\n",
    257                d_bits / 4, static_cast<uint64_t>(expected[d]),
    258                rawbits_to_fp(expected[d]));
    259         printf("  Found:    0x%0*" PRIx64 " (%g)\n",
    260                d_bits / 4, static_cast<uint64_t>(results[d]),
    261                rawbits_to_fp(results[d]));
    262         printf("\n");
    263       }
    264     }
    265     VIXL_ASSERT(d == expected_length);
    266     if (error_count > kErrorReportLimit) {
    267       printf("%u other errors follow.\n", error_count - kErrorReportLimit);
    268     }
    269     VIXL_CHECK(error_count == 0);
    270   }
    271   delete[] results;
    272 }
    273 
    274 
    275 static void Test2Op_Helper(Test2OpFPHelper_t helper,
    276                            uintptr_t inputs, unsigned inputs_length,
    277                            uintptr_t results, unsigned reg_size) {
    278   VIXL_ASSERT((reg_size == kDRegSize) || (reg_size == kSRegSize));
    279 
    280   SETUP();
    281   START();
    282 
    283   // Roll up the loop to keep the code size down.
    284   Label loop_n, loop_m;
    285 
    286   Register out = x0;
    287   Register inputs_base = x1;
    288   Register length = w2;
    289   Register index_n = w3;
    290   Register index_m = w4;
    291 
    292   bool double_op = reg_size == kDRegSize;
    293   const int index_shift =
    294       double_op ? kDRegSizeInBytesLog2 : kSRegSizeInBytesLog2;
    295 
    296   FPRegister fd = double_op ? d0 : s0;
    297   FPRegister fn = double_op ? d1 : s1;
    298   FPRegister fm = double_op ? d2 : s2;
    299 
    300   __ Mov(out, results);
    301   __ Mov(inputs_base, inputs);
    302   __ Mov(length, inputs_length);
    303 
    304   __ Mov(index_n, 0);
    305   __ Bind(&loop_n);
    306   __ Ldr(fn, MemOperand(inputs_base, index_n, UXTW, index_shift));
    307 
    308   __ Mov(index_m, 0);
    309   __ Bind(&loop_m);
    310   __ Ldr(fm, MemOperand(inputs_base, index_m, UXTW, index_shift));
    311 
    312   (masm.*helper)(fd, fn, fm);
    313   __ Str(fd, MemOperand(out, fd.SizeInBytes(), PostIndex));
    314 
    315   __ Add(index_m, index_m, 1);
    316   __ Cmp(index_m, inputs_length);
    317   __ B(lo, &loop_m);
    318 
    319   __ Add(index_n, index_n, 1);
    320   __ Cmp(index_n, inputs_length);
    321   __ B(lo, &loop_n);
    322 
    323   END();
    324   RUN();
    325   TEARDOWN();
    326 }
    327 
    328 
    329 // Test FP instructions. The inputs[] and expected[] arrays should be arrays of
    330 // rawbits representations of doubles or floats. This ensures that exact bit
    331 // comparisons can be performed.
    332 template <typename T>
    333 static void Test2Op(const char * name, Test2OpFPHelper_t helper,
    334                     const T inputs[], unsigned inputs_length,
    335                     const T expected[], unsigned expected_length) {
    336   VIXL_ASSERT(inputs_length > 0);
    337 
    338   const unsigned results_length = inputs_length * inputs_length;
    339   T * results = new T[results_length];
    340 
    341   const unsigned bits = sizeof(T) * 8;
    342 
    343   Test2Op_Helper(helper, reinterpret_cast<uintptr_t>(inputs), inputs_length,
    344                  reinterpret_cast<uintptr_t>(results), bits);
    345 
    346   if (Cctest::sim_test_trace()) {
    347     // Print the results.
    348     printf("const uint%u_t kExpected_%s[] = {\n", bits, name);
    349     for (unsigned d = 0; d < results_length; d++) {
    350       printf("  0x%0*" PRIx64 ",\n",
    351              bits / 4, static_cast<uint64_t>(results[d]));
    352     }
    353     printf("};\n");
    354     printf("const unsigned kExpectedCount_%s = %u;\n", name, results_length);
    355   } else {
    356     // Check the results.
    357     VIXL_CHECK(expected_length == results_length);
    358     unsigned error_count = 0;
    359     unsigned d = 0;
    360     for (unsigned n = 0; n < inputs_length; n++) {
    361       for (unsigned m = 0; m < inputs_length; m++, d++) {
    362         if (results[d] != expected[d]) {
    363           if (++error_count > kErrorReportLimit) continue;
    364 
    365           printf("%s 0x%0*" PRIx64 ", 0x%0*" PRIx64 " (%s %g %g):\n",
    366                  name,
    367                  bits / 4, static_cast<uint64_t>(inputs[n]),
    368                  bits / 4, static_cast<uint64_t>(inputs[m]),
    369                  name,
    370                  rawbits_to_fp(inputs[n]),
    371                  rawbits_to_fp(inputs[m]));
    372           printf("  Expected: 0x%0*" PRIx64 " (%g)\n",
    373                  bits / 4, static_cast<uint64_t>(expected[d]),
    374                  rawbits_to_fp(expected[d]));
    375           printf("  Found:    0x%0*" PRIx64 " (%g)\n",
    376                  bits / 4, static_cast<uint64_t>(results[d]),
    377                  rawbits_to_fp(results[d]));
    378           printf("\n");
    379         }
    380       }
    381     }
    382     VIXL_ASSERT(d == expected_length);
    383     if (error_count > kErrorReportLimit) {
    384       printf("%u other errors follow.\n", error_count - kErrorReportLimit);
    385     }
    386     VIXL_CHECK(error_count == 0);
    387   }
    388   delete[] results;
    389 }
    390 
    391 
    392 static void Test3Op_Helper(Test3OpFPHelper_t helper,
    393                            uintptr_t inputs, unsigned inputs_length,
    394                            uintptr_t results, unsigned reg_size) {
    395   VIXL_ASSERT((reg_size == kDRegSize) || (reg_size == kSRegSize));
    396 
    397   SETUP();
    398   START();
    399 
    400   // Roll up the loop to keep the code size down.
    401   Label loop_n, loop_m, loop_a;
    402 
    403   Register out = x0;
    404   Register inputs_base = x1;
    405   Register length = w2;
    406   Register index_n = w3;
    407   Register index_m = w4;
    408   Register index_a = w5;
    409 
    410   bool double_op = reg_size == kDRegSize;
    411   const int index_shift =
    412       double_op ? kDRegSizeInBytesLog2 : kSRegSizeInBytesLog2;
    413 
    414   FPRegister fd = double_op ? d0 : s0;
    415   FPRegister fn = double_op ? d1 : s1;
    416   FPRegister fm = double_op ? d2 : s2;
    417   FPRegister fa = double_op ? d3 : s3;
    418 
    419   __ Mov(out, results);
    420   __ Mov(inputs_base, inputs);
    421   __ Mov(length, inputs_length);
    422 
    423   __ Mov(index_n, 0);
    424   __ Bind(&loop_n);
    425   __ Ldr(fn, MemOperand(inputs_base, index_n, UXTW, index_shift));
    426 
    427   __ Mov(index_m, 0);
    428   __ Bind(&loop_m);
    429   __ Ldr(fm, MemOperand(inputs_base, index_m, UXTW, index_shift));
    430 
    431   __ Mov(index_a, 0);
    432   __ Bind(&loop_a);
    433   __ Ldr(fa, MemOperand(inputs_base, index_a, UXTW, index_shift));
    434 
    435   (masm.*helper)(fd, fn, fm, fa);
    436   __ Str(fd, MemOperand(out, fd.SizeInBytes(), PostIndex));
    437 
    438   __ Add(index_a, index_a, 1);
    439   __ Cmp(index_a, inputs_length);
    440   __ B(lo, &loop_a);
    441 
    442   __ Add(index_m, index_m, 1);
    443   __ Cmp(index_m, inputs_length);
    444   __ B(lo, &loop_m);
    445 
    446   __ Add(index_n, index_n, 1);
    447   __ Cmp(index_n, inputs_length);
    448   __ B(lo, &loop_n);
    449 
    450   END();
    451   RUN();
    452   TEARDOWN();
    453 }
    454 
    455 
    456 // Test FP instructions. The inputs[] and expected[] arrays should be arrays of
    457 // rawbits representations of doubles or floats. This ensures that exact bit
    458 // comparisons can be performed.
    459 template <typename T>
    460 static void Test3Op(const char * name, Test3OpFPHelper_t helper,
    461                     const T inputs[], unsigned inputs_length,
    462                     const T expected[], unsigned expected_length) {
    463   VIXL_ASSERT(inputs_length > 0);
    464 
    465   const unsigned results_length = inputs_length * inputs_length * inputs_length;
    466   T * results = new T[results_length];
    467 
    468   const unsigned bits = sizeof(T) * 8;
    469 
    470   Test3Op_Helper(helper, reinterpret_cast<uintptr_t>(inputs), inputs_length,
    471                  reinterpret_cast<uintptr_t>(results), bits);
    472 
    473   if (Cctest::sim_test_trace()) {
    474     // Print the results.
    475     printf("const uint%u_t kExpected_%s[] = {\n", bits, name);
    476     for (unsigned d = 0; d < results_length; d++) {
    477       printf("  0x%0*" PRIx64 ",\n",
    478              bits / 4, static_cast<uint64_t>(results[d]));
    479     }
    480     printf("};\n");
    481     printf("const unsigned kExpectedCount_%s = %u;\n", name, results_length);
    482   } else {
    483     // Check the results.
    484     VIXL_CHECK(expected_length == results_length);
    485     unsigned error_count = 0;
    486     unsigned d = 0;
    487     for (unsigned n = 0; n < inputs_length; n++) {
    488       for (unsigned m = 0; m < inputs_length; m++) {
    489         for (unsigned a = 0; a < inputs_length; a++, d++) {
    490           if (results[d] != expected[d]) {
    491             if (++error_count > kErrorReportLimit) continue;
    492 
    493             printf("%s 0x%0*" PRIx64 ", 0x%0*" PRIx64 ", 0x%0*" PRIx64
    494                    " (%s %g %g %g):\n",
    495                    name,
    496                    bits / 4, static_cast<uint64_t>(inputs[n]),
    497                    bits / 4, static_cast<uint64_t>(inputs[m]),
    498                    bits / 4, static_cast<uint64_t>(inputs[a]),
    499                    name,
    500                    rawbits_to_fp(inputs[n]),
    501                    rawbits_to_fp(inputs[m]),
    502                    rawbits_to_fp(inputs[a]));
    503             printf("  Expected: 0x%0*" PRIx64 " (%g)\n",
    504                    bits / 4, static_cast<uint64_t>(expected[d]),
    505                    rawbits_to_fp(expected[d]));
    506             printf("  Found:    0x%0*" PRIx64 " (%g)\n",
    507                    bits / 4, static_cast<uint64_t>(results[d]),
    508                    rawbits_to_fp(results[d]));
    509             printf("\n");
    510           }
    511         }
    512       }
    513     }
    514     VIXL_ASSERT(d == expected_length);
    515     if (error_count > kErrorReportLimit) {
    516       printf("%u other errors follow.\n", error_count - kErrorReportLimit);
    517     }
    518     VIXL_CHECK(error_count == 0);
    519   }
    520   delete[] results;
    521 }
    522 
    523 
    524 static void TestCmp_Helper(TestFPCmpHelper_t helper,
    525                            uintptr_t inputs, unsigned inputs_length,
    526                            uintptr_t results, unsigned reg_size) {
    527   VIXL_ASSERT((reg_size == kDRegSize) || (reg_size == kSRegSize));
    528 
    529   SETUP();
    530   START();
    531 
    532   // Roll up the loop to keep the code size down.
    533   Label loop_n, loop_m;
    534 
    535   Register out = x0;
    536   Register inputs_base = x1;
    537   Register length = w2;
    538   Register index_n = w3;
    539   Register index_m = w4;
    540   Register flags = x5;
    541 
    542   bool double_op = reg_size == kDRegSize;
    543   const int index_shift =
    544       double_op ? kDRegSizeInBytesLog2 : kSRegSizeInBytesLog2;
    545 
    546   FPRegister fn = double_op ? d1 : s1;
    547   FPRegister fm = double_op ? d2 : s2;
    548 
    549   __ Mov(out, results);
    550   __ Mov(inputs_base, inputs);
    551   __ Mov(length, inputs_length);
    552 
    553   __ Mov(index_n, 0);
    554   __ Bind(&loop_n);
    555   __ Ldr(fn, MemOperand(inputs_base, index_n, UXTW, index_shift));
    556 
    557   __ Mov(index_m, 0);
    558   __ Bind(&loop_m);
    559   __ Ldr(fm, MemOperand(inputs_base, index_m, UXTW, index_shift));
    560 
    561   (masm.*helper)(fn, fm);
    562   __ Mrs(flags, NZCV);
    563   __ Ubfx(flags, flags, 28, 4);
    564   __ Strb(flags, MemOperand(out, 1, PostIndex));
    565 
    566   __ Add(index_m, index_m, 1);
    567   __ Cmp(index_m, inputs_length);
    568   __ B(lo, &loop_m);
    569 
    570   __ Add(index_n, index_n, 1);
    571   __ Cmp(index_n, inputs_length);
    572   __ B(lo, &loop_n);
    573 
    574   END();
    575   RUN();
    576   TEARDOWN();
    577 }
    578 
    579 
    580 // Test FP instructions. The inputs[] and expected[] arrays should be arrays of
    581 // rawbits representations of doubles or floats. This ensures that exact bit
    582 // comparisons can be performed.
    583 template <typename T>
    584 static void TestCmp(const char * name, TestFPCmpHelper_t helper,
    585                     const T inputs[], unsigned inputs_length,
    586                     const uint8_t expected[], unsigned expected_length) {
    587   VIXL_ASSERT(inputs_length > 0);
    588 
    589   const unsigned results_length = inputs_length * inputs_length;
    590   uint8_t * results = new uint8_t[results_length];
    591 
    592   const unsigned bits = sizeof(T) * 8;
    593 
    594   TestCmp_Helper(helper, reinterpret_cast<uintptr_t>(inputs), inputs_length,
    595                  reinterpret_cast<uintptr_t>(results), bits);
    596 
    597   if (Cctest::sim_test_trace()) {
    598     // Print the results.
    599     printf("const uint8_t kExpected_%s[] = {\n", name);
    600     for (unsigned d = 0; d < results_length; d++) {
    601       // Each NZCV result only requires 4 bits.
    602       VIXL_ASSERT((results[d] & 0xf) == results[d]);
    603       printf("  0x%" PRIx8 ",\n", results[d]);
    604     }
    605     printf("};\n");
    606     printf("const unsigned kExpectedCount_%s = %u;\n", name, results_length);
    607   } else {
    608     // Check the results.
    609     VIXL_CHECK(expected_length == results_length);
    610     unsigned error_count = 0;
    611     unsigned d = 0;
    612     for (unsigned n = 0; n < inputs_length; n++) {
    613       for (unsigned m = 0; m < inputs_length; m++, d++) {
    614         if (results[d] != expected[d]) {
    615           if (++error_count > kErrorReportLimit) continue;
    616 
    617           printf("%s 0x%0*" PRIx64 ", 0x%0*" PRIx64 " (%s %g %g):\n",
    618                  name,
    619                  bits / 4, static_cast<uint64_t>(inputs[n]),
    620                  bits / 4, static_cast<uint64_t>(inputs[m]),
    621                  name,
    622                  rawbits_to_fp(inputs[n]),
    623                  rawbits_to_fp(inputs[m]));
    624           printf("  Expected: %c%c%c%c (0x%" PRIx8 ")\n",
    625                  (expected[d] & 0x8) ? 'N' : 'n',
    626                  (expected[d] & 0x4) ? 'Z' : 'z',
    627                  (expected[d] & 0x2) ? 'C' : 'c',
    628                  (expected[d] & 0x1) ? 'V' : 'v',
    629                  expected[d]);
    630           printf("  Found:    %c%c%c%c (0x%" PRIx8 ")\n",
    631                  (results[d] & 0x8) ? 'N' : 'n',
    632                  (results[d] & 0x4) ? 'Z' : 'z',
    633                  (results[d] & 0x2) ? 'C' : 'c',
    634                  (results[d] & 0x1) ? 'V' : 'v',
    635                  results[d]);
    636           printf("\n");
    637         }
    638       }
    639     }
    640     VIXL_ASSERT(d == expected_length);
    641     if (error_count > kErrorReportLimit) {
    642       printf("%u other errors follow.\n", error_count - kErrorReportLimit);
    643     }
    644     VIXL_CHECK(error_count == 0);
    645   }
    646   delete[] results;
    647 }
    648 
    649 
    650 static void TestCmpZero_Helper(TestFPCmpZeroHelper_t helper,
    651                                uintptr_t inputs, unsigned inputs_length,
    652                                uintptr_t results, unsigned reg_size) {
    653   VIXL_ASSERT((reg_size == kDRegSize) || (reg_size == kSRegSize));
    654 
    655   SETUP();
    656   START();
    657 
    658   // Roll up the loop to keep the code size down.
    659   Label loop_n, loop_m;
    660 
    661   Register out = x0;
    662   Register inputs_base = x1;
    663   Register length = w2;
    664   Register index_n = w3;
    665   Register flags = x4;
    666 
    667   bool double_op = reg_size == kDRegSize;
    668   const int index_shift =
    669       double_op ? kDRegSizeInBytesLog2 : kSRegSizeInBytesLog2;
    670 
    671   FPRegister fn = double_op ? d1 : s1;
    672 
    673   __ Mov(out, results);
    674   __ Mov(inputs_base, inputs);
    675   __ Mov(length, inputs_length);
    676 
    677   __ Mov(index_n, 0);
    678   __ Bind(&loop_n);
    679   __ Ldr(fn, MemOperand(inputs_base, index_n, UXTW, index_shift));
    680 
    681   (masm.*helper)(fn, 0.0);
    682   __ Mrs(flags, NZCV);
    683   __ Ubfx(flags, flags, 28, 4);
    684   __ Strb(flags, MemOperand(out, 1, PostIndex));
    685 
    686   __ Add(index_n, index_n, 1);
    687   __ Cmp(index_n, inputs_length);
    688   __ B(lo, &loop_n);
    689 
    690   END();
    691   RUN();
    692   TEARDOWN();
    693 }
    694 
    695 
    696 // Test FP instructions. The inputs[] and expected[] arrays should be arrays of
    697 // rawbits representations of doubles or floats. This ensures that exact bit
    698 // comparisons can be performed.
    699 template <typename T>
    700 static void TestCmpZero(const char * name, TestFPCmpZeroHelper_t helper,
    701                         const T inputs[], unsigned inputs_length,
    702                         const uint8_t expected[], unsigned expected_length) {
    703   VIXL_ASSERT(inputs_length > 0);
    704 
    705   const unsigned results_length = inputs_length;
    706   uint8_t * results = new uint8_t[results_length];
    707 
    708   const unsigned bits = sizeof(T) * 8;
    709 
    710   TestCmpZero_Helper(helper, reinterpret_cast<uintptr_t>(inputs), inputs_length,
    711                      reinterpret_cast<uintptr_t>(results), bits);
    712 
    713   if (Cctest::sim_test_trace()) {
    714     // Print the results.
    715     printf("const uint8_t kExpected_%s[] = {\n", name);
    716     for (unsigned d = 0; d < results_length; d++) {
    717       // Each NZCV result only requires 4 bits.
    718       VIXL_ASSERT((results[d] & 0xf) == results[d]);
    719       printf("  0x%" PRIx8 ",\n", results[d]);
    720     }
    721     printf("};\n");
    722     printf("const unsigned kExpectedCount_%s = %u;\n", name, results_length);
    723   } else {
    724     // Check the results.
    725     VIXL_CHECK(expected_length == results_length);
    726     unsigned error_count = 0;
    727     unsigned d = 0;
    728     for (unsigned n = 0; n < inputs_length; n++, d++) {
    729       if (results[d] != expected[d]) {
    730         if (++error_count > kErrorReportLimit) continue;
    731 
    732         printf("%s 0x%0*" PRIx64 ", 0x%0*u (%s %g #0.0):\n",
    733                name,
    734                bits / 4, static_cast<uint64_t>(inputs[n]),
    735                bits / 4, 0,
    736                name,
    737                rawbits_to_fp(inputs[n]));
    738         printf("  Expected: %c%c%c%c (0x%" PRIx8 ")\n",
    739                (expected[d] & 0x8) ? 'N' : 'n',
    740                (expected[d] & 0x4) ? 'Z' : 'z',
    741                (expected[d] & 0x2) ? 'C' : 'c',
    742                (expected[d] & 0x1) ? 'V' : 'v',
    743                expected[d]);
    744         printf("  Found:    %c%c%c%c (0x%" PRIx8 ")\n",
    745                (results[d] & 0x8) ? 'N' : 'n',
    746                (results[d] & 0x4) ? 'Z' : 'z',
    747                (results[d] & 0x2) ? 'C' : 'c',
    748                (results[d] & 0x1) ? 'V' : 'v',
    749                results[d]);
    750         printf("\n");
    751       }
    752     }
    753     VIXL_ASSERT(d == expected_length);
    754     if (error_count > kErrorReportLimit) {
    755       printf("%u other errors follow.\n", error_count - kErrorReportLimit);
    756     }
    757     VIXL_CHECK(error_count == 0);
    758   }
    759   delete[] results;
    760 }
    761 
    762 
    763 static void TestFPToInt_Helper(TestFPToIntHelper_t helper, uintptr_t inputs,
    764                                unsigned inputs_length, uintptr_t results,
    765                                unsigned d_size, unsigned n_size) {
    766   VIXL_ASSERT((d_size == kXRegSize) || (d_size == kWRegSize));
    767   VIXL_ASSERT((n_size == kDRegSize) || (n_size == kSRegSize));
    768 
    769   SETUP();
    770   START();
    771 
    772   // Roll up the loop to keep the code size down.
    773   Label loop_n;
    774 
    775   Register out = x0;
    776   Register inputs_base = x1;
    777   Register length = w2;
    778   Register index_n = w3;
    779 
    780   const int n_index_shift =
    781       (n_size == kDRegSize) ? kDRegSizeInBytesLog2 : kSRegSizeInBytesLog2;
    782 
    783   Register rd = (d_size == kXRegSize) ? x10 : w10;
    784   FPRegister fn = (n_size == kDRegSize) ? d1 : s1;
    785 
    786   __ Mov(out, results);
    787   __ Mov(inputs_base, inputs);
    788   __ Mov(length, inputs_length);
    789 
    790   __ Mov(index_n, 0);
    791   __ Bind(&loop_n);
    792   __ Ldr(fn, MemOperand(inputs_base, index_n, UXTW, n_index_shift));
    793 
    794   (masm.*helper)(rd, fn);
    795   __ Str(rd, MemOperand(out, rd.SizeInBytes(), PostIndex));
    796 
    797   __ Add(index_n, index_n, 1);
    798   __ Cmp(index_n, inputs_length);
    799   __ B(lo, &loop_n);
    800 
    801   END();
    802   RUN();
    803   TEARDOWN();
    804 }
    805 
    806 
    807 // Test FP instructions.
    808 //  - The inputs[] array should be an array of rawbits representations of
    809 //    doubles or floats. This ensures that exact bit comparisons can be
    810 //    performed.
    811 //  - The expected[] array should be an array of signed integers.
    812 template <typename Tn, typename Td>
    813 static void TestFPToS(const char * name, TestFPToIntHelper_t helper,
    814                       const Tn inputs[], unsigned inputs_length,
    815                       const Td expected[], unsigned expected_length) {
    816   VIXL_ASSERT(inputs_length > 0);
    817 
    818   const unsigned results_length = inputs_length;
    819   Td * results = new Td[results_length];
    820 
    821   const unsigned d_bits = sizeof(Td) * 8;
    822   const unsigned n_bits = sizeof(Tn) * 8;
    823 
    824   TestFPToInt_Helper(helper, reinterpret_cast<uintptr_t>(inputs), inputs_length,
    825                      reinterpret_cast<uintptr_t>(results), d_bits, n_bits);
    826 
    827   if (Cctest::sim_test_trace()) {
    828     // Print the results.
    829     printf("const int%u_t kExpected_%s[] = {\n", d_bits, name);
    830     // There is no simple C++ literal for INT*_MIN that doesn't produce
    831     // warnings, so we use an appropriate constant in that case instead.
    832     // Deriving int_d_min in this way (rather than just checking INT64_MIN and
    833     // the like) avoids warnings about comparing values with differing ranges.
    834     const int64_t int_d_max = (UINT64_C(1) << (d_bits - 1)) - 1;
    835     const int64_t int_d_min = -(int_d_max) - 1;
    836     for (unsigned d = 0; d < results_length; d++) {
    837       if (results[d] == int_d_min) {
    838         printf("  -INT%u_C(%" PRId64 ") - 1,\n", d_bits, int_d_max);
    839       } else {
    840         printf("  %" PRId64 ",\n", static_cast<int64_t>(results[d]));
    841       }
    842     }
    843     printf("};\n");
    844     printf("const unsigned kExpectedCount_%s = %u;\n", name, results_length);
    845   } else {
    846     // Check the results.
    847     VIXL_CHECK(expected_length == results_length);
    848     unsigned error_count = 0;
    849     unsigned d = 0;
    850     for (unsigned n = 0; n < inputs_length; n++, d++) {
    851       if (results[d] != expected[d]) {
    852         if (++error_count > kErrorReportLimit) continue;
    853 
    854         printf("%s 0x%0*" PRIx64 " (%s %g):\n",
    855                name, n_bits / 4, static_cast<uint64_t>(inputs[n]),
    856                name, rawbits_to_fp(inputs[n]));
    857         printf("  Expected: 0x%0*" PRIx64 " (%" PRId64 ")\n",
    858                d_bits / 4, static_cast<uint64_t>(expected[d]),
    859                static_cast<int64_t>(expected[d]));
    860         printf("  Found:    0x%0*" PRIx64 " (%" PRId64 ")\n",
    861                d_bits / 4, static_cast<uint64_t>(results[d]),
    862                static_cast<int64_t>(results[d]));
    863         printf("\n");
    864       }
    865     }
    866     VIXL_ASSERT(d == expected_length);
    867     if (error_count > kErrorReportLimit) {
    868       printf("%u other errors follow.\n", error_count - kErrorReportLimit);
    869     }
    870     VIXL_CHECK(error_count == 0);
    871   }
    872   delete[] results;
    873 }
    874 
    875 
    876 // Test FP instructions.
    877 //  - The inputs[] array should be an array of rawbits representations of
    878 //    doubles or floats. This ensures that exact bit comparisons can be
    879 //    performed.
    880 //  - The expected[] array should be an array of unsigned integers.
    881 template <typename Tn, typename Td>
    882 static void TestFPToU(const char * name, TestFPToIntHelper_t helper,
    883                       const Tn inputs[], unsigned inputs_length,
    884                       const Td expected[], unsigned expected_length) {
    885   VIXL_ASSERT(inputs_length > 0);
    886 
    887   const unsigned results_length = inputs_length;
    888   Td * results = new Td[results_length];
    889 
    890   const unsigned d_bits = sizeof(Td) * 8;
    891   const unsigned n_bits = sizeof(Tn) * 8;
    892 
    893   TestFPToInt_Helper(helper, reinterpret_cast<uintptr_t>(inputs), inputs_length,
    894                      reinterpret_cast<uintptr_t>(results), d_bits, n_bits);
    895 
    896   if (Cctest::sim_test_trace()) {
    897     // Print the results.
    898     printf("const uint%u_t kExpected_%s[] = {\n", d_bits, name);
    899     for (unsigned d = 0; d < results_length; d++) {
    900       printf("  %" PRIu64 "u,\n", static_cast<uint64_t>(results[d]));
    901     }
    902     printf("};\n");
    903     printf("const unsigned kExpectedCount_%s = %u;\n", name, results_length);
    904   } else {
    905     // Check the results.
    906     VIXL_CHECK(expected_length == results_length);
    907     unsigned error_count = 0;
    908     unsigned d = 0;
    909     for (unsigned n = 0; n < inputs_length; n++, d++) {
    910       if (results[d] != expected[d]) {
    911         if (++error_count > kErrorReportLimit) continue;
    912 
    913         printf("%s 0x%0*" PRIx64 " (%s %g):\n",
    914                name, n_bits / 4, static_cast<uint64_t>(inputs[n]),
    915                name, rawbits_to_fp(inputs[n]));
    916         printf("  Expected: 0x%0*" PRIx64 " (%" PRIu64 ")\n",
    917                d_bits / 4, static_cast<uint64_t>(expected[d]),
    918                static_cast<uint64_t>(expected[d]));
    919         printf("  Found:    0x%0*" PRIx64 " (%" PRIu64 ")\n",
    920                d_bits / 4, static_cast<uint64_t>(results[d]),
    921                static_cast<uint64_t>(results[d]));
    922         printf("\n");
    923       }
    924     }
    925     VIXL_ASSERT(d == expected_length);
    926     if (error_count > kErrorReportLimit) {
    927       printf("%u other errors follow.\n", error_count - kErrorReportLimit);
    928     }
    929     VIXL_CHECK(error_count == 0);
    930   }
    931   delete[] results;
    932 }
    933 
    934 
    935 // Floating-point tests.
    936 
    937 
    938 // Standard floating-point test expansion for both double- and single-precision
    939 // operations.
    940 #define STRINGIFY(s) #s
    941 
    942 #define CALL_TEST_FP_HELPER(mnemonic, variant, type, input)         \
    943     Test##type(STRINGIFY(mnemonic) "_" STRINGIFY(variant),          \
    944                &MacroAssembler::mnemonic,                           \
    945                input, sizeof(input) / sizeof(input[0]),             \
    946                kExpected_##mnemonic##_##variant,                    \
    947                kExpectedCount_##mnemonic##_##variant)
    948 
    949 #define DEFINE_TEST_FP(mnemonic, type, input)                       \
    950     TEST(mnemonic##_d) {                                            \
    951       CALL_TEST_FP_HELPER(mnemonic, d, type, kInputDouble##input);  \
    952     }                                                               \
    953     TEST(mnemonic##_s) {                                            \
    954       CALL_TEST_FP_HELPER(mnemonic, s, type, kInputFloat##input);   \
    955     }
    956 
    957 DEFINE_TEST_FP(fmadd, 3Op, Basic)
    958 DEFINE_TEST_FP(fmsub, 3Op, Basic)
    959 DEFINE_TEST_FP(fnmadd, 3Op, Basic)
    960 DEFINE_TEST_FP(fnmsub, 3Op, Basic)
    961 
    962 DEFINE_TEST_FP(fadd, 2Op, Basic)
    963 DEFINE_TEST_FP(fdiv, 2Op, Basic)
    964 DEFINE_TEST_FP(fmax, 2Op, Basic)
    965 DEFINE_TEST_FP(fmaxnm, 2Op, Basic)
    966 DEFINE_TEST_FP(fmin, 2Op, Basic)
    967 DEFINE_TEST_FP(fminnm, 2Op, Basic)
    968 DEFINE_TEST_FP(fmul, 2Op, Basic)
    969 DEFINE_TEST_FP(fsub, 2Op, Basic)
    970 
    971 DEFINE_TEST_FP(fabs, 1Op, Basic)
    972 DEFINE_TEST_FP(fmov, 1Op, Basic)
    973 DEFINE_TEST_FP(fneg, 1Op, Basic)
    974 DEFINE_TEST_FP(fsqrt, 1Op, Basic)
    975 DEFINE_TEST_FP(frinta, 1Op, Conversions)
    976 DEFINE_TEST_FP(frintn, 1Op, Conversions)
    977 DEFINE_TEST_FP(frintz, 1Op, Conversions)
    978 
    979 TEST(fcmp_d) { CALL_TEST_FP_HELPER(fcmp, d, Cmp, kInputDoubleBasic); }
    980 TEST(fcmp_s) { CALL_TEST_FP_HELPER(fcmp, s, Cmp, kInputFloatBasic); }
    981 TEST(fcmp_dz) { CALL_TEST_FP_HELPER(fcmp, dz, CmpZero, kInputDoubleBasic); }
    982 TEST(fcmp_sz) { CALL_TEST_FP_HELPER(fcmp, sz, CmpZero, kInputFloatBasic); }
    983 
    984 TEST(fcvt_sd) { CALL_TEST_FP_HELPER(fcvt, sd, 1Op, kInputDoubleConversions); }
    985 TEST(fcvt_ds) { CALL_TEST_FP_HELPER(fcvt, ds, 1Op, kInputFloatConversions); }
    986 
    987 #define DEFINE_TEST_FP_TO_INT(mnemonic, type, input)                \
    988     TEST(mnemonic##_xd) {                                           \
    989       CALL_TEST_FP_HELPER(mnemonic, xd, type, kInputDouble##input); \
    990     }                                                               \
    991     TEST(mnemonic##_xs) {                                           \
    992       CALL_TEST_FP_HELPER(mnemonic, xs, type, kInputFloat##input);  \
    993     }                                                               \
    994     TEST(mnemonic##_wd) {                                           \
    995       CALL_TEST_FP_HELPER(mnemonic, wd, type, kInputDouble##input); \
    996     }                                                               \
    997     TEST(mnemonic##_ws) {                                           \
    998       CALL_TEST_FP_HELPER(mnemonic, ws, type, kInputFloat##input);  \
    999     }
   1000 
   1001 DEFINE_TEST_FP_TO_INT(fcvtas, FPToS, Conversions)
   1002 DEFINE_TEST_FP_TO_INT(fcvtau, FPToU, Conversions)
   1003 DEFINE_TEST_FP_TO_INT(fcvtms, FPToS, Conversions)
   1004 DEFINE_TEST_FP_TO_INT(fcvtmu, FPToU, Conversions)
   1005 DEFINE_TEST_FP_TO_INT(fcvtns, FPToS, Conversions)
   1006 DEFINE_TEST_FP_TO_INT(fcvtnu, FPToU, Conversions)
   1007 DEFINE_TEST_FP_TO_INT(fcvtzs, FPToS, Conversions)
   1008 DEFINE_TEST_FP_TO_INT(fcvtzu, FPToU, Conversions)
   1009 
   1010 // TODO(jbramley): Scvtf-fixed-point
   1011 // TODO(jbramley): Scvtf-integer
   1012 // TODO(jbramley): Ucvtf-fixed-point
   1013 // TODO(jbramley): Ucvtf-integer
   1014 
   1015 // TODO(jbramley): Fccmp
   1016 // TODO(jbramley): Fcsel
   1017 
   1018 }  // namespace vixl
   1019