Home | History | Annotate | Download | only in cctest
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_ARM64_TEST_UTILS_ARM64_H_
     29 #define V8_ARM64_TEST_UTILS_ARM64_H_
     30 
     31 #include "src/v8.h"
     32 #include "test/cctest/cctest.h"
     33 
     34 #include "src/arm64/macro-assembler-arm64.h"
     35 #include "src/arm64/utils-arm64.h"
     36 #include "src/macro-assembler.h"
     37 
     38 
     39 using namespace v8::internal;
     40 
     41 
     42 // RegisterDump: Object allowing integer, floating point and flags registers
     43 // to be saved to itself for future reference.
     44 class RegisterDump {
     45  public:
     46   RegisterDump() : completed_(false) {}
     47 
     48   // The Dump method generates code to store a snapshot of the register values.
     49   // It needs to be able to use the stack temporarily, and requires that the
     50   // current stack pointer is csp, and is properly aligned.
     51   //
     52   // The dumping code is generated though the given MacroAssembler. No registers
     53   // are corrupted in the process, but the stack is used briefly. The flags will
     54   // be corrupted during this call.
     55   void Dump(MacroAssembler* assm);
     56 
     57   // Register accessors.
     58   inline int32_t wreg(unsigned code) const {
     59     if (code == kSPRegInternalCode) {
     60       return wspreg();
     61     }
     62     DCHECK(RegAliasesMatch(code));
     63     return dump_.w_[code];
     64   }
     65 
     66   inline int64_t xreg(unsigned code) const {
     67     if (code == kSPRegInternalCode) {
     68       return spreg();
     69     }
     70     DCHECK(RegAliasesMatch(code));
     71     return dump_.x_[code];
     72   }
     73 
     74   // FPRegister accessors.
     75   inline uint32_t sreg_bits(unsigned code) const {
     76     DCHECK(FPRegAliasesMatch(code));
     77     return dump_.s_[code];
     78   }
     79 
     80   inline float sreg(unsigned code) const {
     81     return rawbits_to_float(sreg_bits(code));
     82   }
     83 
     84   inline uint64_t dreg_bits(unsigned code) const {
     85     DCHECK(FPRegAliasesMatch(code));
     86     return dump_.d_[code];
     87   }
     88 
     89   inline double dreg(unsigned code) const {
     90     return rawbits_to_double(dreg_bits(code));
     91   }
     92 
     93   // Stack pointer accessors.
     94   inline int64_t spreg() const {
     95     DCHECK(SPRegAliasesMatch());
     96     return dump_.sp_;
     97   }
     98 
     99   inline int64_t wspreg() const {
    100     DCHECK(SPRegAliasesMatch());
    101     return dump_.wsp_;
    102   }
    103 
    104   // Flags accessors.
    105   inline uint64_t flags_nzcv() const {
    106     DCHECK(IsComplete());
    107     DCHECK((dump_.flags_ & ~Flags_mask) == 0);
    108     return dump_.flags_ & Flags_mask;
    109   }
    110 
    111   inline bool IsComplete() const {
    112     return completed_;
    113   }
    114 
    115  private:
    116   // Indicate whether the dump operation has been completed.
    117   bool completed_;
    118 
    119   // Check that the lower 32 bits of x<code> exactly match the 32 bits of
    120   // w<code>. A failure of this test most likely represents a failure in the
    121   // ::Dump method, or a failure in the simulator.
    122   bool RegAliasesMatch(unsigned code) const {
    123     DCHECK(IsComplete());
    124     DCHECK(code < kNumberOfRegisters);
    125     return ((dump_.x_[code] & kWRegMask) == dump_.w_[code]);
    126   }
    127 
    128   // As RegAliasesMatch, but for the stack pointer.
    129   bool SPRegAliasesMatch() const {
    130     DCHECK(IsComplete());
    131     return ((dump_.sp_ & kWRegMask) == dump_.wsp_);
    132   }
    133 
    134   // As RegAliasesMatch, but for floating-point registers.
    135   bool FPRegAliasesMatch(unsigned code) const {
    136     DCHECK(IsComplete());
    137     DCHECK(code < kNumberOfFPRegisters);
    138     return (dump_.d_[code] & kSRegMask) == dump_.s_[code];
    139   }
    140 
    141   // Store all the dumped elements in a simple struct so the implementation can
    142   // use offsetof to quickly find the correct field.
    143   struct dump_t {
    144     // Core registers.
    145     uint64_t x_[kNumberOfRegisters];
    146     uint32_t w_[kNumberOfRegisters];
    147 
    148     // Floating-point registers, as raw bits.
    149     uint64_t d_[kNumberOfFPRegisters];
    150     uint32_t s_[kNumberOfFPRegisters];
    151 
    152     // The stack pointer.
    153     uint64_t sp_;
    154     uint64_t wsp_;
    155 
    156     // NZCV flags, stored in bits 28 to 31.
    157     // bit[31] : Negative
    158     // bit[30] : Zero
    159     // bit[29] : Carry
    160     // bit[28] : oVerflow
    161     uint64_t flags_;
    162   } dump_;
    163 
    164   static dump_t for_sizeof();
    165   STATIC_ASSERT(sizeof(for_sizeof().d_[0]) == kDRegSize);
    166   STATIC_ASSERT(sizeof(for_sizeof().s_[0]) == kSRegSize);
    167   STATIC_ASSERT(sizeof(for_sizeof().d_[0]) == kXRegSize);
    168   STATIC_ASSERT(sizeof(for_sizeof().s_[0]) == kWRegSize);
    169   STATIC_ASSERT(sizeof(for_sizeof().x_[0]) == kXRegSize);
    170   STATIC_ASSERT(sizeof(for_sizeof().w_[0]) == kWRegSize);
    171 };
    172 
    173 // Some of these methods don't use the RegisterDump argument, but they have to
    174 // accept them so that they can overload those that take register arguments.
    175 bool Equal32(uint32_t expected, const RegisterDump*, uint32_t result);
    176 bool Equal64(uint64_t expected, const RegisterDump*, uint64_t result);
    177 
    178 bool EqualFP32(float expected, const RegisterDump*, float result);
    179 bool EqualFP64(double expected, const RegisterDump*, double result);
    180 
    181 bool Equal32(uint32_t expected, const RegisterDump* core, const Register& reg);
    182 bool Equal64(uint64_t expected, const RegisterDump* core, const Register& reg);
    183 
    184 bool EqualFP32(float expected, const RegisterDump* core,
    185                const FPRegister& fpreg);
    186 bool EqualFP64(double expected, const RegisterDump* core,
    187                const FPRegister& fpreg);
    188 
    189 bool Equal64(const Register& reg0, const RegisterDump* core,
    190              const Register& reg1);
    191 
    192 bool EqualNzcv(uint32_t expected, uint32_t result);
    193 
    194 bool EqualRegisters(const RegisterDump* a, const RegisterDump* b);
    195 
    196 // Populate the w, x and r arrays with registers from the 'allowed' mask. The
    197 // r array will be populated with <reg_size>-sized registers,
    198 //
    199 // This allows for tests which use large, parameterized blocks of registers
    200 // (such as the push and pop tests), but where certain registers must be
    201 // avoided as they are used for other purposes.
    202 //
    203 // Any of w, x, or r can be NULL if they are not required.
    204 //
    205 // The return value is a RegList indicating which registers were allocated.
    206 RegList PopulateRegisterArray(Register* w, Register* x, Register* r,
    207                               int reg_size, int reg_count, RegList allowed);
    208 
    209 // As PopulateRegisterArray, but for floating-point registers.
    210 RegList PopulateFPRegisterArray(FPRegister* s, FPRegister* d, FPRegister* v,
    211                                 int reg_size, int reg_count, RegList allowed);
    212 
    213 // Ovewrite the contents of the specified registers. This enables tests to
    214 // check that register contents are written in cases where it's likely that the
    215 // correct outcome could already be stored in the register.
    216 //
    217 // This always overwrites X-sized registers. If tests are operating on W
    218 // registers, a subsequent write into an aliased W register should clear the
    219 // top word anyway, so clobbering the full X registers should make tests more
    220 // rigorous.
    221 void Clobber(MacroAssembler* masm, RegList reg_list,
    222              uint64_t const value = 0xfedcba9876543210UL);
    223 
    224 // As Clobber, but for FP registers.
    225 void ClobberFP(MacroAssembler* masm, RegList reg_list,
    226                double const value = kFP64SignallingNaN);
    227 
    228 // As Clobber, but for a CPURegList with either FP or integer registers. When
    229 // using this method, the clobber value is always the default for the basic
    230 // Clobber or ClobberFP functions.
    231 void Clobber(MacroAssembler* masm, CPURegList reg_list);
    232 
    233 #endif  // V8_ARM64_TEST_UTILS_ARM64_H_
    234