Home | History | Annotate | Download | only in aarch32
      1 // Copyright 2015, VIXL authors
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are met:
      6 //
      7 //   * Redistributions of source code must retain the above copyright notice,
      8 //     this list of conditions and the following disclaimer.
      9 //   * Redistributions in binary form must reproduce the above copyright notice,
     10 //     this list of conditions and the following disclaimer in the documentation
     11 //     and/or other materials provided with the distribution.
     12 //   * Neither the name of ARM Limited nor the names of its contributors may be
     13 //     used to endorse or promote products derived from this software without
     14 //     specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
     17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
     20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 
     27 #include "aarch32/test-utils-aarch32.h"
     28 
     29 #define __ masm->
     30 
     31 namespace vixl {
     32 namespace aarch32 {
     33 
     34 #define VIXL_OFFSET(type, member) offsetof(type, member)
     35 
     36 void RegisterDump::Dump(MacroAssembler* masm) {
     37   UseScratchRegisterScope scratch(masm);
     38   scratch.ExcludeAll();
     39 
     40   // Preserve some temporary registers.
     41   Register dump_base = r0;
     42   Register tmp = r1;
     43 
     44   // Check that the the dump registers can be used
     45   VIXL_STATIC_ASSERT(sizeof(dump_.r_[0]) == kRegSizeInBytes);
     46   VIXL_STATIC_ASSERT(sizeof(dump_.d_[0]) == kDRegSizeInBytes);
     47 
     48   // Offsets into the dump_ structure.
     49   const int r_offset = static_cast<int>(VIXL_OFFSET(dump_t, r_));
     50   const int d_offset = static_cast<int>(VIXL_OFFSET(dump_t, d_));
     51   const int flags_offset = static_cast<int>(VIXL_OFFSET(dump_t, flags_));
     52 
     53   __ Push(dump_base);
     54   __ Push(tmp);
     55 
     56   // Load the address of the dump_ structure.
     57   __ Mov(dump_base, Operand::From(&dump_));
     58 
     59   // Dump all core registers.  Note that the stack pointer and temporary
     60   // registers will be stored again later after they are restored.
     61   for (unsigned i = 0; i < kNumberOfRegisters; i++) {
     62     Register rt(i);
     63     // In T32 mode, "str pc, [base, #offset]" is not allowed so we cannot store
     64     // the program counter this way. We could however compute the relative
     65     // offset from the start of the buffer and store it but it's not very
     66     // useful. So for now, testing the value of the PC is not supported.
     67     if (!rt.IsPC()) {
     68       __ Str(rt, MemOperand(dump_base, r_offset + (i * kRegSizeInBytes)));
     69     }
     70   }
     71 
     72   for (unsigned i = 0; i < kMaxNumberOfDRegisters; i++) {
     73     DRegister rt(i);
     74     __ Vstr(Untyped64,
     75             rt,
     76             MemOperand(dump_base, d_offset + (i * kDRegSizeInBytes)));
     77   }
     78 
     79   // Dump the flags.
     80   __ Mrs(tmp, APSR);
     81   __ Str(tmp, MemOperand(dump_base, flags_offset));
     82 
     83   // We need a new pointer to dump_ in order to dump the temporary registers and
     84   // the stack pointer.
     85   Register dump2_base = r2;
     86   // TODO: Assert that dump_base, dump2_base and tmp are not aliases.
     87   __ Mov(dump2_base, dump_base);
     88 
     89   __ Pop(tmp);
     90   __ Pop(dump_base);
     91 
     92   // Dump tmp, dump_base and the stack pointer.
     93   __ Str(tmp,
     94          MemOperand(dump2_base, r_offset + (tmp.GetCode() * kRegSizeInBytes)));
     95   __ Str(dump_base,
     96          MemOperand(dump2_base,
     97                     r_offset + (dump_base.GetCode() * kRegSizeInBytes)));
     98   __ Str(sp, MemOperand(dump2_base, r_offset + (kSPRegNum * kRegSizeInBytes)));
     99 
    100   completed_ = true;
    101 }
    102 
    103 
    104 bool Equal32(uint32_t expected, const RegisterDump*, uint32_t result) {
    105   if (result != expected) {
    106     printf("Expected 0x%08" PRIx32 "\t Found 0x%08" PRIx32 "\n",
    107            expected,
    108            result);
    109   }
    110 
    111   return expected == result;
    112 }
    113 
    114 
    115 bool Equal32(uint32_t expected, const RegisterDump* core, const Register& reg) {
    116   if (reg.IsPC()) {
    117     printf("Testing the value of the program counter is not supported.");
    118     return false;
    119   } else {
    120     return Equal32(expected, core, core->reg(reg.GetCode()));
    121   }
    122 }
    123 
    124 
    125 bool Equal32(uint32_t expected,
    126              const RegisterDump* core,
    127              const SRegister& sreg) {
    128   return Equal32(expected, core, core->GetSRegisterBits(sreg.GetCode()));
    129 }
    130 
    131 
    132 bool Equal64(uint64_t expected, const RegisterDump*, uint64_t result) {
    133   if (result != expected) {
    134     printf("Expected 0x%016" PRIx64 "\t Found 0x%016" PRIx64 "\n",
    135            expected,
    136            result);
    137   }
    138 
    139   return expected == result;
    140 }
    141 
    142 
    143 bool Equal64(uint64_t expected,
    144              const RegisterDump* core,
    145              const DRegister& dreg) {
    146   return Equal64(expected, core, core->GetDRegisterBits(dreg.GetCode()));
    147 }
    148 
    149 
    150 bool Equal128(vec128_t expected, const RegisterDump*, vec128_t result) {
    151   if ((result.h != expected.h) || (result.l != expected.l)) {
    152     printf("Expected 0x%016" PRIx64 "%016" PRIx64
    153            "\t "
    154            "Found 0x%016" PRIx64 "%016" PRIx64 "\n",
    155            expected.h,
    156            expected.l,
    157            result.h,
    158            result.l);
    159   }
    160 
    161   return ((expected.h == result.h) && (expected.l == result.l));
    162 }
    163 
    164 
    165 bool Equal128(uint64_t expected_h,
    166               uint64_t expected_l,
    167               const RegisterDump* core,
    168               const QRegister& qreg) {
    169   vec128_t expected = {expected_l, expected_h};
    170   vec128_t result = core->GetQRegisterBits(qreg.GetCode());
    171   return Equal128(expected, core, result);
    172 }
    173 
    174 
    175 static char FlagN(uint32_t flags) { return (flags & NFlag) ? 'N' : 'n'; }
    176 
    177 
    178 static char FlagZ(uint32_t flags) { return (flags & ZFlag) ? 'Z' : 'z'; }
    179 
    180 
    181 static char FlagC(uint32_t flags) { return (flags & CFlag) ? 'C' : 'c'; }
    182 
    183 
    184 static char FlagV(uint32_t flags) { return (flags & VFlag) ? 'V' : 'v'; }
    185 
    186 
    187 bool EqualNzcv(uint32_t expected, uint32_t result) {
    188   VIXL_ASSERT((expected & ~NZCVFlag) == 0);
    189   VIXL_ASSERT((result & ~NZCVFlag) == 0);
    190   if (result != expected) {
    191     printf("Expected: %c%c%c%c\t Found: %c%c%c%c\n",
    192            FlagN(expected),
    193            FlagZ(expected),
    194            FlagC(expected),
    195            FlagV(expected),
    196            FlagN(result),
    197            FlagZ(result),
    198            FlagC(result),
    199            FlagV(result));
    200     return false;
    201   }
    202 
    203   return true;
    204 }
    205 
    206 
    207 bool EqualFP32(float expected,
    208                const RegisterDump* core,
    209                const SRegister& sreg) {
    210   // Retrieve the corresponding S register
    211   uint32_t result = core->GetSRegisterBits(sreg.GetCode());
    212 
    213   if (FloatToRawbits(expected) == result) {
    214     return true;
    215   } else {
    216     if (std::isnan(expected) || (expected == 0.0)) {
    217       printf("Expected 0x%08" PRIx32 "\t Found 0x%08" PRIx32 "\n",
    218              FloatToRawbits(expected),
    219              result);
    220     } else {
    221       printf("Expected %.9f (0x%08" PRIx32
    222              ")\t "
    223              "Found %.9f (0x%08" PRIx32 ")\n",
    224              expected,
    225              FloatToRawbits(expected),
    226              RawbitsToFloat(result),
    227              result);
    228     }
    229     return false;
    230   }
    231 }
    232 
    233 
    234 bool EqualFP64(double expected,
    235                const RegisterDump* core,
    236                const DRegister& dreg) {
    237   // Retrieve the corresponding D register
    238   uint64_t result = core->GetDRegisterBits(dreg.GetCode());
    239 
    240   if (DoubleToRawbits(expected) == result) {
    241     return true;
    242   }
    243 
    244   if (std::isnan(expected) || (expected == 0.0)) {
    245     printf("Expected 0x%016" PRIx64 "\t Found 0x%016" PRIx64 "\n",
    246            DoubleToRawbits(expected),
    247            DoubleToRawbits(result));
    248   } else {
    249     printf("Expected %.17f (0x%016" PRIx64
    250            ")\t "
    251            "Found %.17f (0x%016" PRIx64 ")\n",
    252            expected,
    253            DoubleToRawbits(expected),
    254            RawbitsToDouble(result),
    255            result);
    256   }
    257   return false;
    258 }
    259 
    260 
    261 }  // namespace aarch32
    262 }  // namespace vixl
    263