11123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// Copyright 2014, ARM Limited
21123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// All rights reserved.
31123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl//
41123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// Redistribution and use in source and binary forms, with or without
51123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// modification, are permitted provided that the following conditions are met:
61123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl//
71123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl//   * Redistributions of source code must retain the above copyright notice,
81123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl//     this list of conditions and the following disclaimer.
91123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl//   * Redistributions in binary form must reproduce the above copyright notice,
101123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl//     this list of conditions and the following disclaimer in the documentation
111123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl//     and/or other materials provided with the distribution.
121123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl//   * Neither the name of ARM Limited nor the names of its contributors may be
131123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl//     used to endorse or promote products derived from this software without
141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl//     specific prior written permission.
151123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl//
161123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
181123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
191123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
201123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
211123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
221123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
231123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
241123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
251123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
261123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
271123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#include <stdio.h>
281123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#include <float.h>
291123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
301123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#include "cctest.h"
311123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#include "test-utils-a64.h"
321123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#include "test-simulator-inputs-a64.h"
331123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#include "test-simulator-traces-a64.h"
341123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#include "a64/macro-assembler-a64.h"
351123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#include "a64/simulator-a64.h"
361123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
371123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlnamespace vixl {
381123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
391123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// ==== Simulator Tests ====
401123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl//
411123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// These simulator tests check instruction behaviour against a trace taken from
421123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// real AArch64 hardware. The same test code is used to generate the trace; the
431123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// results are printed to stdout when the test is run with --sim_test_trace.
441123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl//
451123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// The input lists and expected results are stored in
461123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// test/test-simulator-traces-a64.h. The expected results can be regenerated
471123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// using tools/generate_simulator_traces.py.
481123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
491123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define __ masm.
501123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define TEST(name)  TEST_(SIM_##name)
511123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
521123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define BUF_SIZE (256)
531123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
541123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#ifdef USE_SIMULATOR
551123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
561123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define SETUP()                                                               \
571123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  byte* buf = new byte[BUF_SIZE];                                             \
581123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  MacroAssembler masm(buf, BUF_SIZE);                                         \
591123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Decoder decoder;                                                            \
601123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Simulator* simulator = NULL;                                                \
611123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (Cctest::run_debugger()) {                                               \
621123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    simulator = new Debugger(&decoder);                                       \
631123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {                                                                    \
641123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    simulator = new Simulator(&decoder);                                      \
651123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    simulator->set_disasm_trace(Cctest::trace_sim());                         \
661123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }                                                                           \
671123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  simulator->set_coloured_trace(Cctest::coloured_trace());                    \
681123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  simulator->set_instruction_stats(Cctest::instruction_stats());
691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
701123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define START()                                                               \
711123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  masm.Reset();                                                               \
721123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  simulator->ResetState();                                                    \
731123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ PushCalleeSavedRegisters();                                              \
741123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (Cctest::run_debugger()) {                                               \
751123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    if (Cctest::trace_reg()) {                                                \
761123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      __ Trace(LOG_STATE, TRACE_ENABLE);                                      \
771123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }                                                                         \
781123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    if (Cctest::trace_sim()) {                                                \
791123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      __ Trace(LOG_DISASM, TRACE_ENABLE);                                     \
801123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }                                                                         \
811123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }                                                                           \
821123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (Cctest::instruction_stats()) {                                          \
831123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    __ EnableInstrumentation();                                               \
841123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
851123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
861123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define END()                                                                 \
871123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (Cctest::instruction_stats()) {                                          \
881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    __ DisableInstrumentation();                                              \
891123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }                                                                           \
901123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (Cctest::run_debugger()) {                                               \
911123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    __ Trace(LOG_ALL, TRACE_DISABLE);                                         \
921123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }                                                                           \
931123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ PopCalleeSavedRegisters();                                               \
941123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Ret();                                                                   \
951123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  masm.FinalizeCode()
961123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
971123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define RUN()                                                                 \
981123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  simulator->RunFrom(reinterpret_cast<Instruction*>(buf))
991123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1001123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define TEARDOWN()                                                            \
1011123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  delete simulator;                                                           \
1021123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  delete[] buf;
1031123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1041123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#else     // USE_SIMULATOR
1051123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1061123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define SETUP()                                                               \
1071123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  byte* buf = new byte[BUF_SIZE];                                             \
1081123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  MacroAssembler masm(buf, BUF_SIZE);                                         \
1091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  CPU::SetUp()
1101123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1111123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define START()                                                               \
1121123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  masm.Reset();                                                               \
1131123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ PushCalleeSavedRegisters()
1141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1151123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define END()                                                                 \
1161123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ PopCalleeSavedRegisters();                                               \
1171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Ret();                                                                   \
1181123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  masm.FinalizeCode()
1191123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1201123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define RUN()                                                                 \
1211123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  CPU::EnsureIAndDCacheCoherency(buf, BUF_SIZE);                              \
1221123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  {                                                                           \
1231123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    void (*test_function)(void);                                              \
1241123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(sizeof(buf) == sizeof(test_function));                        \
1251123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    memcpy(&test_function, &buf, sizeof(buf));                                \
1261123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    test_function();                                                          \
1271123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
1281123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1291123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define TEARDOWN()                                                            \
1301123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  delete[] buf;
1311123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1321123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#endif    // USE_SIMULATOR
1331123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1341123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1351123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// The maximum number of errors to report in detail for each test.
1361123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlstatic const unsigned kErrorReportLimit = 8;
1371123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1381123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
139ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// Overloaded versions of rawbits_to_double and rawbits_to_float for use in the
140ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// templated test functions.
141ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlstatic float rawbits_to_fp(uint32_t bits) {
142ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  return rawbits_to_float(bits);
143ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl}
144ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
145ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlstatic double rawbits_to_fp(uint64_t bits) {
146ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  return rawbits_to_double(bits);
147ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl}
148ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
149ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
1501123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// MacroAssembler member function pointers to pass to the test dispatchers.
1511123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixltypedef void (MacroAssembler::*Test1OpFPHelper_t)(const FPRegister& fd,
1521123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                                  const FPRegister& fn);
1531123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixltypedef void (MacroAssembler::*Test2OpFPHelper_t)(const FPRegister& fd,
1541123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                                  const FPRegister& fn,
1551123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                                  const FPRegister& fm);
1561123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixltypedef void (MacroAssembler::*Test3OpFPHelper_t)(const FPRegister& fd,
1571123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                                  const FPRegister& fn,
1581123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                                  const FPRegister& fm,
1591123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                                  const FPRegister& fa);
160ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixltypedef void (MacroAssembler::*TestFPCmpHelper_t)(const FPRegister& fn,
161ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                                                  const FPRegister& fm);
162ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixltypedef void (MacroAssembler::*TestFPCmpZeroHelper_t)(const FPRegister& fn,
163ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                                                      double value);
164ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixltypedef void (MacroAssembler::*TestFPToIntHelper_t)(const Register& rd,
165ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                                                    const FPRegister& fn);
166ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixltypedef void (MacroAssembler::*TestFixedToFPHelper_t)(const FPRegister& fd,
167ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                                                      const Register& rn,
168ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                                                      unsigned fbits);
1691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1701123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// Standard test dispatchers.
1711123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1721123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
173ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlstatic void Test1Op_Helper(Test1OpFPHelper_t helper, uintptr_t inputs,
174ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                           unsigned inputs_length, uintptr_t results,
175ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                           unsigned d_size, unsigned n_size) {
176ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  VIXL_ASSERT((d_size == kDRegSize) || (d_size == kSRegSize));
177ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  VIXL_ASSERT((n_size == kDRegSize) || (n_size == kSRegSize));
1781123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1791123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  SETUP();
1801123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  START();
1811123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1821123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // Roll up the loop to keep the code size down.
183ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Label loop_n;
1841123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1851123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Register out = x0;
1861123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Register inputs_base = x1;
1871123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Register length = w2;
1881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Register index_n = w3;
1891123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
190ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const int n_index_shift =
191ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      (n_size == kDRegSize) ? kDRegSizeInBytesLog2 : kSRegSizeInBytesLog2;
1921123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
193ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  FPRegister fd = (d_size == kDRegSize) ? d0 : s0;
194ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  FPRegister fn = (n_size == kDRegSize) ? d1 : s1;
1951123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1961123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Mov(out, results);
1971123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Mov(inputs_base, inputs);
1981123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Mov(length, inputs_length);
1991123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
2001123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Mov(index_n, 0);
2011123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Bind(&loop_n);
202ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Ldr(fn, MemOperand(inputs_base, index_n, UXTW, n_index_shift));
2031123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
204ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  (masm.*helper)(fd, fn);
2051123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Str(fd, MemOperand(out, fd.SizeInBytes(), PostIndex));
2061123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
2071123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Add(index_n, index_n, 1);
2081123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Cmp(index_n, inputs_length);
2091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ B(lo, &loop_n);
2101123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
2111123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  END();
2121123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  RUN();
2131123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  TEARDOWN();
2141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
2151123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
2161123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
217ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// Test FP instructions. The inputs[] and expected[] arrays should be arrays of
218ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// rawbits representations of doubles or floats. This ensures that exact bit
2191123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// comparisons can be performed.
220ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixltemplate <typename Tn, typename Td>
221ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlstatic void Test1Op(const char * name, Test1OpFPHelper_t helper,
222ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                    const Tn inputs[], unsigned inputs_length,
223ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                    const Td expected[], unsigned expected_length) {
2241123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(inputs_length > 0);
2251123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
226ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned results_length = inputs_length;
227ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Td * results = new Td[results_length];
2281123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
229ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned d_bits = sizeof(Td) * 8;
230ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned n_bits = sizeof(Tn) * 8;
231ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
232ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Test1Op_Helper(helper, reinterpret_cast<uintptr_t>(inputs), inputs_length,
233ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 reinterpret_cast<uintptr_t>(results), d_bits, n_bits);
2341123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
2351123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (Cctest::sim_test_trace()) {
2361123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // Print the results.
237ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("const uint%u_t kExpected_%s[] = {\n", d_bits, name);
2381123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    for (unsigned d = 0; d < results_length; d++) {
239ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      printf("  0x%0*" PRIx64 ",\n",
240ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl             d_bits / 4, static_cast<uint64_t>(results[d]));
2411123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
2421123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    printf("};\n");
243ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("const unsigned kExpectedCount_%s = %u;\n", name, results_length);
2441123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
2451123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // Check the results.
2461123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_CHECK(expected_length == results_length);
2471123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    unsigned error_count = 0;
2481123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    unsigned d = 0;
249ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    for (unsigned n = 0; n < inputs_length; n++, d++) {
250ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if (results[d] != expected[d]) {
251ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        if (++error_count > kErrorReportLimit) continue;
252ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
253ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("%s 0x%0*" PRIx64 " (%s %g):\n",
254ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               name, n_bits / 4, static_cast<uint64_t>(inputs[n]),
255ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               name, rawbits_to_fp(inputs[n]));
256ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("  Expected: 0x%0*" PRIx64 " (%g)\n",
257ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               d_bits / 4, static_cast<uint64_t>(expected[d]),
258ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               rawbits_to_fp(expected[d]));
259ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("  Found:    0x%0*" PRIx64 " (%g)\n",
260ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               d_bits / 4, static_cast<uint64_t>(results[d]),
261ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               rawbits_to_fp(results[d]));
262ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("\n");
2631123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      }
2641123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
2651123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(d == expected_length);
2661123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    if (error_count > kErrorReportLimit) {
2671123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      printf("%u other errors follow.\n", error_count - kErrorReportLimit);
2681123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
2691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_CHECK(error_count == 0);
2701123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
2711123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  delete[] results;
2721123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
2731123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
2741123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
275ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlstatic void Test2Op_Helper(Test2OpFPHelper_t helper,
276ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                           uintptr_t inputs, unsigned inputs_length,
277ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                           uintptr_t results, unsigned reg_size) {
278ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  VIXL_ASSERT((reg_size == kDRegSize) || (reg_size == kSRegSize));
279ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
280ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  SETUP();
281ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  START();
282ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
283ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // Roll up the loop to keep the code size down.
284ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Label loop_n, loop_m;
285ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
286ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register out = x0;
287ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register inputs_base = x1;
288ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register length = w2;
289ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register index_n = w3;
290ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register index_m = w4;
291ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
292ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  bool double_op = reg_size == kDRegSize;
293ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const int index_shift =
294ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      double_op ? kDRegSizeInBytesLog2 : kSRegSizeInBytesLog2;
295ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
296ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  FPRegister fd = double_op ? d0 : s0;
297ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  FPRegister fn = double_op ? d1 : s1;
298ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  FPRegister fm = double_op ? d2 : s2;
299ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
300ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(out, results);
301ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(inputs_base, inputs);
302ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(length, inputs_length);
303ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
304ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(index_n, 0);
305ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Bind(&loop_n);
306ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Ldr(fn, MemOperand(inputs_base, index_n, UXTW, index_shift));
307ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
308ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(index_m, 0);
309ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Bind(&loop_m);
310ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Ldr(fm, MemOperand(inputs_base, index_m, UXTW, index_shift));
311ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
312ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  (masm.*helper)(fd, fn, fm);
313ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Str(fd, MemOperand(out, fd.SizeInBytes(), PostIndex));
314ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
315ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Add(index_m, index_m, 1);
316ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Cmp(index_m, inputs_length);
317ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ B(lo, &loop_m);
318ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
319ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Add(index_n, index_n, 1);
320ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Cmp(index_n, inputs_length);
321ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ B(lo, &loop_n);
322ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
323ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  END();
324ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  RUN();
325ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  TEARDOWN();
326ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl}
327ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
328ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
329ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// Test FP instructions. The inputs[] and expected[] arrays should be arrays of
330ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// rawbits representations of doubles or floats. This ensures that exact bit
3311123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// comparisons can be performed.
332ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixltemplate <typename T>
3331123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlstatic void Test2Op(const char * name, Test2OpFPHelper_t helper,
334ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                    const T inputs[], unsigned inputs_length,
335ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                    const T expected[], unsigned expected_length) {
3361123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(inputs_length > 0);
3371123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
338ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned results_length = inputs_length * inputs_length;
339ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  T * results = new T[results_length];
340ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
341ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned bits = sizeof(T) * 8;
3421123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
3431123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Test2Op_Helper(helper, reinterpret_cast<uintptr_t>(inputs), inputs_length,
344ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 reinterpret_cast<uintptr_t>(results), bits);
3451123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
3461123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (Cctest::sim_test_trace()) {
3471123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // Print the results.
348ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("const uint%u_t kExpected_%s[] = {\n", bits, name);
3491123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    for (unsigned d = 0; d < results_length; d++) {
350ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      printf("  0x%0*" PRIx64 ",\n",
351ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl             bits / 4, static_cast<uint64_t>(results[d]));
3521123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
3531123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    printf("};\n");
354ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("const unsigned kExpectedCount_%s = %u;\n", name, results_length);
3551123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
3561123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // Check the results.
3571123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_CHECK(expected_length == results_length);
3581123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    unsigned error_count = 0;
3591123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    unsigned d = 0;
3601123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    for (unsigned n = 0; n < inputs_length; n++) {
3611123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      for (unsigned m = 0; m < inputs_length; m++, d++) {
3621123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl        if (results[d] != expected[d]) {
3631123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl          if (++error_count > kErrorReportLimit) continue;
3641123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
365ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl          printf("%s 0x%0*" PRIx64 ", 0x%0*" PRIx64 " (%s %g %g):\n",
3661123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                 name,
367ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 bits / 4, static_cast<uint64_t>(inputs[n]),
368ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 bits / 4, static_cast<uint64_t>(inputs[m]),
369ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 name,
370ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 rawbits_to_fp(inputs[n]),
371ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 rawbits_to_fp(inputs[m]));
372ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl          printf("  Expected: 0x%0*" PRIx64 " (%g)\n",
373ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 bits / 4, static_cast<uint64_t>(expected[d]),
374ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 rawbits_to_fp(expected[d]));
375ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl          printf("  Found:    0x%0*" PRIx64 " (%g)\n",
376ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 bits / 4, static_cast<uint64_t>(results[d]),
377ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 rawbits_to_fp(results[d]));
3781123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl          printf("\n");
3791123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl        }
3801123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      }
3811123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
3821123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(d == expected_length);
3831123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    if (error_count > kErrorReportLimit) {
3841123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      printf("%u other errors follow.\n", error_count - kErrorReportLimit);
3851123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
3861123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_CHECK(error_count == 0);
3871123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
3881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  delete[] results;
3891123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
3901123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
3911123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
3921123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlstatic void Test3Op_Helper(Test3OpFPHelper_t helper,
3931123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                           uintptr_t inputs, unsigned inputs_length,
3941123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                           uintptr_t results, unsigned reg_size) {
3951123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((reg_size == kDRegSize) || (reg_size == kSRegSize));
3961123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
3971123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  SETUP();
3981123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  START();
3991123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
4001123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // Roll up the loop to keep the code size down.
4011123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Label loop_n, loop_m, loop_a;
4021123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
4031123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Register out = x0;
4041123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Register inputs_base = x1;
4051123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Register length = w2;
4061123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Register index_n = w3;
4071123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Register index_m = w4;
4081123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Register index_a = w5;
4091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
4101123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  bool double_op = reg_size == kDRegSize;
4111123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  const int index_shift =
4121123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      double_op ? kDRegSizeInBytesLog2 : kSRegSizeInBytesLog2;
4131123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
4141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  FPRegister fd = double_op ? d0 : s0;
4151123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  FPRegister fn = double_op ? d1 : s1;
4161123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  FPRegister fm = double_op ? d2 : s2;
4171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  FPRegister fa = double_op ? d3 : s3;
4181123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
4191123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Mov(out, results);
4201123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Mov(inputs_base, inputs);
4211123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Mov(length, inputs_length);
4221123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
4231123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Mov(index_n, 0);
4241123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Bind(&loop_n);
4251123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Ldr(fn, MemOperand(inputs_base, index_n, UXTW, index_shift));
4261123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
4271123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Mov(index_m, 0);
4281123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Bind(&loop_m);
4291123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Ldr(fm, MemOperand(inputs_base, index_m, UXTW, index_shift));
4301123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
4311123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Mov(index_a, 0);
4321123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Bind(&loop_a);
4331123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Ldr(fa, MemOperand(inputs_base, index_a, UXTW, index_shift));
4341123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
4351123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  (masm.*helper)(fd, fn, fm, fa);
4361123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Str(fd, MemOperand(out, fd.SizeInBytes(), PostIndex));
4371123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
4381123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Add(index_a, index_a, 1);
4391123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Cmp(index_a, inputs_length);
4401123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ B(lo, &loop_a);
4411123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
4421123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Add(index_m, index_m, 1);
4431123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Cmp(index_m, inputs_length);
4441123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ B(lo, &loop_m);
4451123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
4461123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Add(index_n, index_n, 1);
4471123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ Cmp(index_n, inputs_length);
4481123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  __ B(lo, &loop_n);
4491123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
4501123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  END();
4511123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  RUN();
4521123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  TEARDOWN();
4531123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
4541123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
4551123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
456ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// Test FP instructions. The inputs[] and expected[] arrays should be arrays of
457ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// rawbits representations of doubles or floats. This ensures that exact bit
4581123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// comparisons can be performed.
459ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixltemplate <typename T>
4601123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlstatic void Test3Op(const char * name, Test3OpFPHelper_t helper,
461ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                    const T inputs[], unsigned inputs_length,
462ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                    const T expected[], unsigned expected_length) {
4631123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(inputs_length > 0);
4641123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
465ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned results_length = inputs_length * inputs_length * inputs_length;
466ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  T * results = new T[results_length];
467ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
468ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned bits = sizeof(T) * 8;
4691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
4701123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  Test3Op_Helper(helper, reinterpret_cast<uintptr_t>(inputs), inputs_length,
471ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 reinterpret_cast<uintptr_t>(results), bits);
4721123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
4731123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (Cctest::sim_test_trace()) {
4741123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // Print the results.
475ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("const uint%u_t kExpected_%s[] = {\n", bits, name);
4761123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    for (unsigned d = 0; d < results_length; d++) {
477ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      printf("  0x%0*" PRIx64 ",\n",
478ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl             bits / 4, static_cast<uint64_t>(results[d]));
4791123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
4801123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    printf("};\n");
481ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("const unsigned kExpectedCount_%s = %u;\n", name, results_length);
4821123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
4831123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // Check the results.
4841123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_CHECK(expected_length == results_length);
4851123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    unsigned error_count = 0;
4861123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    unsigned d = 0;
4871123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    for (unsigned n = 0; n < inputs_length; n++) {
4881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      for (unsigned m = 0; m < inputs_length; m++) {
4891123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl        for (unsigned a = 0; a < inputs_length; a++, d++) {
4901123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl          if (results[d] != expected[d]) {
4911123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl            if (++error_count > kErrorReportLimit) continue;
4921123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
493ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl            printf("%s 0x%0*" PRIx64 ", 0x%0*" PRIx64 ", 0x%0*" PRIx64
494ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                   " (%s %g %g %g):\n",
4951123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                   name,
496ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                   bits / 4, static_cast<uint64_t>(inputs[n]),
497ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                   bits / 4, static_cast<uint64_t>(inputs[m]),
498ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                   bits / 4, static_cast<uint64_t>(inputs[a]),
499ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                   name,
500ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                   rawbits_to_fp(inputs[n]),
501ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                   rawbits_to_fp(inputs[m]),
502ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                   rawbits_to_fp(inputs[a]));
503ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl            printf("  Expected: 0x%0*" PRIx64 " (%g)\n",
504ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                   bits / 4, static_cast<uint64_t>(expected[d]),
505ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                   rawbits_to_fp(expected[d]));
506ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl            printf("  Found:    0x%0*" PRIx64 " (%g)\n",
507ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                   bits / 4, static_cast<uint64_t>(results[d]),
508ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                   rawbits_to_fp(results[d]));
5091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl            printf("\n");
5101123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl          }
5111123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl        }
5121123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      }
5131123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
5141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(d == expected_length);
5151123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    if (error_count > kErrorReportLimit) {
5161123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      printf("%u other errors follow.\n", error_count - kErrorReportLimit);
5171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
5181123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_CHECK(error_count == 0);
5191123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
5201123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  delete[] results;
5211123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
5221123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
5231123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
524ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlstatic void TestCmp_Helper(TestFPCmpHelper_t helper,
525ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                           uintptr_t inputs, unsigned inputs_length,
526ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                           uintptr_t results, unsigned reg_size) {
527ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  VIXL_ASSERT((reg_size == kDRegSize) || (reg_size == kSRegSize));
528ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
529ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  SETUP();
530ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  START();
531ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
532ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // Roll up the loop to keep the code size down.
533ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Label loop_n, loop_m;
534ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
535ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register out = x0;
536ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register inputs_base = x1;
537ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register length = w2;
538ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register index_n = w3;
539ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register index_m = w4;
540ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register flags = x5;
541ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
542ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  bool double_op = reg_size == kDRegSize;
543ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const int index_shift =
544ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      double_op ? kDRegSizeInBytesLog2 : kSRegSizeInBytesLog2;
545ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
546ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  FPRegister fn = double_op ? d1 : s1;
547ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  FPRegister fm = double_op ? d2 : s2;
548ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
549ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(out, results);
550ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(inputs_base, inputs);
551ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(length, inputs_length);
552ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
553ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(index_n, 0);
554ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Bind(&loop_n);
555ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Ldr(fn, MemOperand(inputs_base, index_n, UXTW, index_shift));
556ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
557ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(index_m, 0);
558ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Bind(&loop_m);
559ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Ldr(fm, MemOperand(inputs_base, index_m, UXTW, index_shift));
560ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
561ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  (masm.*helper)(fn, fm);
562ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mrs(flags, NZCV);
563ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Ubfx(flags, flags, 28, 4);
564ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Strb(flags, MemOperand(out, 1, PostIndex));
565ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
566ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Add(index_m, index_m, 1);
567ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Cmp(index_m, inputs_length);
568ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ B(lo, &loop_m);
569ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
570ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Add(index_n, index_n, 1);
571ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Cmp(index_n, inputs_length);
572ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ B(lo, &loop_n);
573ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
574ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  END();
575ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  RUN();
576ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  TEARDOWN();
577ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl}
578ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
579ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
580ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// Test FP instructions. The inputs[] and expected[] arrays should be arrays of
581ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// rawbits representations of doubles or floats. This ensures that exact bit
5821123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// comparisons can be performed.
583ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixltemplate <typename T>
584ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlstatic void TestCmp(const char * name, TestFPCmpHelper_t helper,
585ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                    const T inputs[], unsigned inputs_length,
586ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                    const uint8_t expected[], unsigned expected_length) {
5871123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(inputs_length > 0);
5881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
589ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned results_length = inputs_length * inputs_length;
590ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  uint8_t * results = new uint8_t[results_length];
5911123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
592ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned bits = sizeof(T) * 8;
593ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
594ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  TestCmp_Helper(helper, reinterpret_cast<uintptr_t>(inputs), inputs_length,
595ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 reinterpret_cast<uintptr_t>(results), bits);
5961123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
5971123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (Cctest::sim_test_trace()) {
5981123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // Print the results.
599ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("const uint8_t kExpected_%s[] = {\n", name);
6001123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    for (unsigned d = 0; d < results_length; d++) {
601ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      // Each NZCV result only requires 4 bits.
602ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      VIXL_ASSERT((results[d] & 0xf) == results[d]);
603ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      printf("  0x%" PRIx8 ",\n", results[d]);
6041123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
6051123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    printf("};\n");
606ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("const unsigned kExpectedCount_%s = %u;\n", name, results_length);
6071123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
6081123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // Check the results.
6091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_CHECK(expected_length == results_length);
6101123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    unsigned error_count = 0;
6111123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    unsigned d = 0;
6121123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    for (unsigned n = 0; n < inputs_length; n++) {
613ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      for (unsigned m = 0; m < inputs_length; m++, d++) {
614ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        if (results[d] != expected[d]) {
615ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl          if (++error_count > kErrorReportLimit) continue;
6161123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
617ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl          printf("%s 0x%0*" PRIx64 ", 0x%0*" PRIx64 " (%s %g %g):\n",
618ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 name,
619ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 bits / 4, static_cast<uint64_t>(inputs[n]),
620ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 bits / 4, static_cast<uint64_t>(inputs[m]),
621ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 name,
622ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 rawbits_to_fp(inputs[n]),
623ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 rawbits_to_fp(inputs[m]));
624ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl          printf("  Expected: %c%c%c%c (0x%" PRIx8 ")\n",
625ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 (expected[d] & 0x8) ? 'N' : 'n',
626ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 (expected[d] & 0x4) ? 'Z' : 'z',
627ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 (expected[d] & 0x2) ? 'C' : 'c',
628ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 (expected[d] & 0x1) ? 'V' : 'v',
629ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 expected[d]);
630ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl          printf("  Found:    %c%c%c%c (0x%" PRIx8 ")\n",
631ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 (results[d] & 0x8) ? 'N' : 'n',
632ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 (results[d] & 0x4) ? 'Z' : 'z',
633ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 (results[d] & 0x2) ? 'C' : 'c',
634ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 (results[d] & 0x1) ? 'V' : 'v',
635ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                 results[d]);
636ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl          printf("\n");
6371123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl        }
6381123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      }
6391123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
6401123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(d == expected_length);
6411123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    if (error_count > kErrorReportLimit) {
6421123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      printf("%u other errors follow.\n", error_count - kErrorReportLimit);
6431123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
6441123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_CHECK(error_count == 0);
6451123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
6461123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  delete[] results;
6471123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
6481123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
6491123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
650ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlstatic void TestCmpZero_Helper(TestFPCmpZeroHelper_t helper,
651ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                               uintptr_t inputs, unsigned inputs_length,
652ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                               uintptr_t results, unsigned reg_size) {
653ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  VIXL_ASSERT((reg_size == kDRegSize) || (reg_size == kSRegSize));
6541123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
655ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  SETUP();
656ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  START();
6571123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
658ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // Roll up the loop to keep the code size down.
659ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Label loop_n, loop_m;
660ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
661ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register out = x0;
662ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register inputs_base = x1;
663ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register length = w2;
664ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register index_n = w3;
665ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register flags = x4;
666ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
667ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  bool double_op = reg_size == kDRegSize;
668ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const int index_shift =
669ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      double_op ? kDRegSizeInBytesLog2 : kSRegSizeInBytesLog2;
670ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
671ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  FPRegister fn = double_op ? d1 : s1;
672ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
673ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(out, results);
674ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(inputs_base, inputs);
675ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(length, inputs_length);
676ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
677ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(index_n, 0);
678ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Bind(&loop_n);
679ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Ldr(fn, MemOperand(inputs_base, index_n, UXTW, index_shift));
680ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
681ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  (masm.*helper)(fn, 0.0);
682ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mrs(flags, NZCV);
683ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Ubfx(flags, flags, 28, 4);
684ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Strb(flags, MemOperand(out, 1, PostIndex));
685ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
686ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Add(index_n, index_n, 1);
687ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Cmp(index_n, inputs_length);
688ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ B(lo, &loop_n);
689ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
690ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  END();
691ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  RUN();
692ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  TEARDOWN();
693ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl}
694ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
695ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
696ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// Test FP instructions. The inputs[] and expected[] arrays should be arrays of
697ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// rawbits representations of doubles or floats. This ensures that exact bit
698ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// comparisons can be performed.
699ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixltemplate <typename T>
700ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlstatic void TestCmpZero(const char * name, TestFPCmpZeroHelper_t helper,
701ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                        const T inputs[], unsigned inputs_length,
702ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                        const uint8_t expected[], unsigned expected_length) {
703ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  VIXL_ASSERT(inputs_length > 0);
704ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
705ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned results_length = inputs_length;
706ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  uint8_t * results = new uint8_t[results_length];
707ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
708ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned bits = sizeof(T) * 8;
709ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
710ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  TestCmpZero_Helper(helper, reinterpret_cast<uintptr_t>(inputs), inputs_length,
711ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                     reinterpret_cast<uintptr_t>(results), bits);
712ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
713ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  if (Cctest::sim_test_trace()) {
714ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // Print the results.
715ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("const uint8_t kExpected_%s[] = {\n", name);
716ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    for (unsigned d = 0; d < results_length; d++) {
717ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      // Each NZCV result only requires 4 bits.
718ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      VIXL_ASSERT((results[d] & 0xf) == results[d]);
719ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      printf("  0x%" PRIx8 ",\n", results[d]);
7201123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
721ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("};\n");
722ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("const unsigned kExpectedCount_%s = %u;\n", name, results_length);
723ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  } else {
724ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // Check the results.
725ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    VIXL_CHECK(expected_length == results_length);
726ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    unsigned error_count = 0;
727ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    unsigned d = 0;
728ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    for (unsigned n = 0; n < inputs_length; n++, d++) {
729ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if (results[d] != expected[d]) {
730ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        if (++error_count > kErrorReportLimit) continue;
731ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
732ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("%s 0x%0*" PRIx64 ", 0x%0*u (%s %g #0.0):\n",
733ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               name,
734ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               bits / 4, static_cast<uint64_t>(inputs[n]),
735ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               bits / 4, 0,
736ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               name,
737ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               rawbits_to_fp(inputs[n]));
738ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("  Expected: %c%c%c%c (0x%" PRIx8 ")\n",
739ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               (expected[d] & 0x8) ? 'N' : 'n',
740ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               (expected[d] & 0x4) ? 'Z' : 'z',
741ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               (expected[d] & 0x2) ? 'C' : 'c',
742ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               (expected[d] & 0x1) ? 'V' : 'v',
743ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               expected[d]);
744ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("  Found:    %c%c%c%c (0x%" PRIx8 ")\n",
745ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               (results[d] & 0x8) ? 'N' : 'n',
746ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               (results[d] & 0x4) ? 'Z' : 'z',
747ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               (results[d] & 0x2) ? 'C' : 'c',
748ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               (results[d] & 0x1) ? 'V' : 'v',
749ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               results[d]);
750ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("\n");
751ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      }
752ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }
753ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    VIXL_ASSERT(d == expected_length);
754ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    if (error_count > kErrorReportLimit) {
755ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      printf("%u other errors follow.\n", error_count - kErrorReportLimit);
756ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }
757ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    VIXL_CHECK(error_count == 0);
758ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  }
759ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  delete[] results;
760ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl}
7611123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
7621123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
763ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlstatic void TestFPToInt_Helper(TestFPToIntHelper_t helper, uintptr_t inputs,
764ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                               unsigned inputs_length, uintptr_t results,
765ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                               unsigned d_size, unsigned n_size) {
766ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  VIXL_ASSERT((d_size == kXRegSize) || (d_size == kWRegSize));
767ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  VIXL_ASSERT((n_size == kDRegSize) || (n_size == kSRegSize));
7681123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
769ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  SETUP();
770ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  START();
771ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
772ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // Roll up the loop to keep the code size down.
773ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Label loop_n;
774ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
775ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register out = x0;
776ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register inputs_base = x1;
777ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register length = w2;
778ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register index_n = w3;
779ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
780ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const int n_index_shift =
781ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      (n_size == kDRegSize) ? kDRegSizeInBytesLog2 : kSRegSizeInBytesLog2;
782ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
783ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Register rd = (d_size == kXRegSize) ? x10 : w10;
784ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  FPRegister fn = (n_size == kDRegSize) ? d1 : s1;
785ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
786ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(out, results);
787ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(inputs_base, inputs);
788ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(length, inputs_length);
789ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
790ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Mov(index_n, 0);
791ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Bind(&loop_n);
792ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Ldr(fn, MemOperand(inputs_base, index_n, UXTW, n_index_shift));
793ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
794ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  (masm.*helper)(rd, fn);
795ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Str(rd, MemOperand(out, rd.SizeInBytes(), PostIndex));
796ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
797ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Add(index_n, index_n, 1);
798ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ Cmp(index_n, inputs_length);
799ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  __ B(lo, &loop_n);
800ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
801ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  END();
802ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  RUN();
803ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  TEARDOWN();
804ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl}
8051123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
8061123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
807ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// Test FP instructions.
808ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl//  - The inputs[] array should be an array of rawbits representations of
809ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl//    doubles or floats. This ensures that exact bit comparisons can be
810ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl//    performed.
811ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl//  - The expected[] array should be an array of signed integers.
812ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixltemplate <typename Tn, typename Td>
813ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlstatic void TestFPToS(const char * name, TestFPToIntHelper_t helper,
814ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                      const Tn inputs[], unsigned inputs_length,
815ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                      const Td expected[], unsigned expected_length) {
816ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  VIXL_ASSERT(inputs_length > 0);
8171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
818ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned results_length = inputs_length;
819ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Td * results = new Td[results_length];
8201123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
821ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned d_bits = sizeof(Td) * 8;
822ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned n_bits = sizeof(Tn) * 8;
8231123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
824ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  TestFPToInt_Helper(helper, reinterpret_cast<uintptr_t>(inputs), inputs_length,
825ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                     reinterpret_cast<uintptr_t>(results), d_bits, n_bits);
8261123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
827ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  if (Cctest::sim_test_trace()) {
828ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // Print the results.
829ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("const int%u_t kExpected_%s[] = {\n", d_bits, name);
830ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // There is no simple C++ literal for INT*_MIN that doesn't produce
831ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // warnings, so we use an appropriate constant in that case instead.
832ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // Deriving int_d_min in this way (rather than just checking INT64_MIN and
833ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // the like) avoids warnings about comparing values with differing ranges.
834ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    const int64_t int_d_max = (UINT64_C(1) << (d_bits - 1)) - 1;
835ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    const int64_t int_d_min = -(int_d_max) - 1;
836ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    for (unsigned d = 0; d < results_length; d++) {
837ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if (results[d] == int_d_min) {
838ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("  -INT%u_C(%" PRId64 ") - 1,\n", d_bits, int_d_max);
839ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      } else {
840ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("  %" PRId64 ",\n", static_cast<int64_t>(results[d]));
841ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      }
842ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }
843ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("};\n");
844ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("const unsigned kExpectedCount_%s = %u;\n", name, results_length);
845ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  } else {
846ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // Check the results.
847ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    VIXL_CHECK(expected_length == results_length);
848ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    unsigned error_count = 0;
849ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    unsigned d = 0;
850ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    for (unsigned n = 0; n < inputs_length; n++, d++) {
851ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if (results[d] != expected[d]) {
852ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        if (++error_count > kErrorReportLimit) continue;
853ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
854ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("%s 0x%0*" PRIx64 " (%s %g):\n",
855ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               name, n_bits / 4, static_cast<uint64_t>(inputs[n]),
856ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               name, rawbits_to_fp(inputs[n]));
857ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("  Expected: 0x%0*" PRIx64 " (%" PRId64 ")\n",
858ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               d_bits / 4, static_cast<uint64_t>(expected[d]),
859ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               static_cast<int64_t>(expected[d]));
860ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("  Found:    0x%0*" PRIx64 " (%" PRId64 ")\n",
861ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               d_bits / 4, static_cast<uint64_t>(results[d]),
862ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               static_cast<int64_t>(results[d]));
863ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("\n");
864ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      }
865ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }
866ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    VIXL_ASSERT(d == expected_length);
867ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    if (error_count > kErrorReportLimit) {
868ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      printf("%u other errors follow.\n", error_count - kErrorReportLimit);
869ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }
870ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    VIXL_CHECK(error_count == 0);
871ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  }
872ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  delete[] results;
873ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl}
8741123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
8751123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
876ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// Test FP instructions.
877ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl//  - The inputs[] array should be an array of rawbits representations of
878ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl//    doubles or floats. This ensures that exact bit comparisons can be
879ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl//    performed.
880ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl//  - The expected[] array should be an array of unsigned integers.
881ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixltemplate <typename Tn, typename Td>
882ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlstatic void TestFPToU(const char * name, TestFPToIntHelper_t helper,
883ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                      const Tn inputs[], unsigned inputs_length,
884ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                      const Td expected[], unsigned expected_length) {
885ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  VIXL_ASSERT(inputs_length > 0);
886ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
887ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned results_length = inputs_length;
888ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  Td * results = new Td[results_length];
889ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
890ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned d_bits = sizeof(Td) * 8;
891ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const unsigned n_bits = sizeof(Tn) * 8;
892ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
893ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  TestFPToInt_Helper(helper, reinterpret_cast<uintptr_t>(inputs), inputs_length,
894ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl                     reinterpret_cast<uintptr_t>(results), d_bits, n_bits);
895ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
896ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  if (Cctest::sim_test_trace()) {
897ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // Print the results.
898ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("const uint%u_t kExpected_%s[] = {\n", d_bits, name);
899ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    for (unsigned d = 0; d < results_length; d++) {
900ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      printf("  %" PRIu64 "u,\n", static_cast<uint64_t>(results[d]));
901ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }
902ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("};\n");
903ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    printf("const unsigned kExpectedCount_%s = %u;\n", name, results_length);
904ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  } else {
905ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    // Check the results.
906ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    VIXL_CHECK(expected_length == results_length);
907ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    unsigned error_count = 0;
908ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    unsigned d = 0;
909ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    for (unsigned n = 0; n < inputs_length; n++, d++) {
910ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if (results[d] != expected[d]) {
911ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        if (++error_count > kErrorReportLimit) continue;
912ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
913ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("%s 0x%0*" PRIx64 " (%s %g):\n",
914ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               name, n_bits / 4, static_cast<uint64_t>(inputs[n]),
915ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               name, rawbits_to_fp(inputs[n]));
916ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("  Expected: 0x%0*" PRIx64 " (%" PRIu64 ")\n",
917ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               d_bits / 4, static_cast<uint64_t>(expected[d]),
918ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               static_cast<uint64_t>(expected[d]));
919ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("  Found:    0x%0*" PRIx64 " (%" PRIu64 ")\n",
920ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               d_bits / 4, static_cast<uint64_t>(results[d]),
921ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               static_cast<uint64_t>(results[d]));
922ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        printf("\n");
923ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      }
924ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }
925ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    VIXL_ASSERT(d == expected_length);
926ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    if (error_count > kErrorReportLimit) {
927ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      printf("%u other errors follow.\n", error_count - kErrorReportLimit);
928ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }
929ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    VIXL_CHECK(error_count == 0);
930ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  }
931ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  delete[] results;
932ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl}
933ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
934ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
935ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// Floating-point tests.
936ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
937ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
938ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// Standard floating-point test expansion for both double- and single-precision
939ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// operations.
940ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl#define STRINGIFY(s) #s
941ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
942ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl#define CALL_TEST_FP_HELPER(mnemonic, variant, type, input)         \
943ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    Test##type(STRINGIFY(mnemonic) "_" STRINGIFY(variant),          \
944ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               &MacroAssembler::mnemonic,                           \
945ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               input, sizeof(input) / sizeof(input[0]),             \
946ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               kExpected_##mnemonic##_##variant,                    \
947ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl               kExpectedCount_##mnemonic##_##variant)
948ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
949ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl#define DEFINE_TEST_FP(mnemonic, type, input)                       \
950ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    TEST(mnemonic##_d) {                                            \
951ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      CALL_TEST_FP_HELPER(mnemonic, d, type, kInputDouble##input);  \
952ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }                                                               \
953ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    TEST(mnemonic##_s) {                                            \
954ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      CALL_TEST_FP_HELPER(mnemonic, s, type, kInputFloat##input);   \
955ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }
956ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
957ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(fmadd, 3Op, Basic)
958ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(fmsub, 3Op, Basic)
959ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(fnmadd, 3Op, Basic)
960ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(fnmsub, 3Op, Basic)
961ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
962ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(fadd, 2Op, Basic)
963ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(fdiv, 2Op, Basic)
964ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(fmax, 2Op, Basic)
965ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(fmaxnm, 2Op, Basic)
966ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(fmin, 2Op, Basic)
967ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(fminnm, 2Op, Basic)
968ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(fmul, 2Op, Basic)
969ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(fsub, 2Op, Basic)
970ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
971ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(fabs, 1Op, Basic)
972ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(fmov, 1Op, Basic)
973ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(fneg, 1Op, Basic)
974ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(fsqrt, 1Op, Basic)
975ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(frinta, 1Op, Conversions)
976ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(frintn, 1Op, Conversions)
977ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP(frintz, 1Op, Conversions)
978ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
979ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlTEST(fcmp_d) { CALL_TEST_FP_HELPER(fcmp, d, Cmp, kInputDoubleBasic); }
980ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlTEST(fcmp_s) { CALL_TEST_FP_HELPER(fcmp, s, Cmp, kInputFloatBasic); }
981ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlTEST(fcmp_dz) { CALL_TEST_FP_HELPER(fcmp, dz, CmpZero, kInputDoubleBasic); }
982ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlTEST(fcmp_sz) { CALL_TEST_FP_HELPER(fcmp, sz, CmpZero, kInputFloatBasic); }
983ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
984ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlTEST(fcvt_sd) { CALL_TEST_FP_HELPER(fcvt, sd, 1Op, kInputDoubleConversions); }
985ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlTEST(fcvt_ds) { CALL_TEST_FP_HELPER(fcvt, ds, 1Op, kInputFloatConversions); }
986ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
987ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl#define DEFINE_TEST_FP_TO_INT(mnemonic, type, input)                \
988ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    TEST(mnemonic##_xd) {                                           \
989ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      CALL_TEST_FP_HELPER(mnemonic, xd, type, kInputDouble##input); \
990ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }                                                               \
991ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    TEST(mnemonic##_xs) {                                           \
992ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      CALL_TEST_FP_HELPER(mnemonic, xs, type, kInputFloat##input);  \
993ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }                                                               \
994ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    TEST(mnemonic##_wd) {                                           \
995ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      CALL_TEST_FP_HELPER(mnemonic, wd, type, kInputDouble##input); \
996ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }                                                               \
997ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    TEST(mnemonic##_ws) {                                           \
998ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      CALL_TEST_FP_HELPER(mnemonic, ws, type, kInputFloat##input);  \
999ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }
1000ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
1001ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP_TO_INT(fcvtas, FPToS, Conversions)
1002ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP_TO_INT(fcvtau, FPToU, Conversions)
1003ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP_TO_INT(fcvtms, FPToS, Conversions)
1004ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP_TO_INT(fcvtmu, FPToU, Conversions)
1005ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP_TO_INT(fcvtns, FPToS, Conversions)
1006ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP_TO_INT(fcvtnu, FPToU, Conversions)
1007ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP_TO_INT(fcvtzs, FPToS, Conversions)
1008ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixlDEFINE_TEST_FP_TO_INT(fcvtzu, FPToU, Conversions)
10091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
10101123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// TODO(jbramley): Scvtf-fixed-point
10111123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// TODO(jbramley): Scvtf-integer
10121123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// TODO(jbramley): Ucvtf-fixed-point
10131123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl// TODO(jbramley): Ucvtf-integer
10141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
1015ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// TODO(jbramley): Fccmp
1016ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl// TODO(jbramley): Fcsel
10171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
10181123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}  // namespace vixl
1019