Home | History | Annotate | Download | only in examples
      1 // Copyright 2013, ARM Limited
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are met:
      6 //
      7 //   * Redistributions of source code must retain the above copyright notice,
      8 //     this list of conditions and the following disclaimer.
      9 //   * Redistributions in binary form must reproduce the above copyright notice,
     10 //     this list of conditions and the following disclaimer in the documentation
     11 //     and/or other materials provided with the distribution.
     12 //   * Neither the name of ARM Limited nor the names of its contributors may be
     13 //     used to endorse or promote products derived from this software without
     14 //     specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
     17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
     20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 
     27 // The examples only work with the simulator.
     28 #ifdef USE_SIMULATOR
     29 
     30 #include "a64/macro-assembler-a64.h"
     31 #include "a64/debugger-a64.h"
     32 #include "a64/simulator-a64.h"
     33 #include "examples.h"
     34 #include "../test-utils-a64.h"
     35 
     36 #include "../cctest.h"
     37 
     38 #define ARRAY_SIZE(Array) (sizeof(Array) / sizeof((Array)[0]))
     39 #define BUF_SIZE (4096)
     40 #define __ masm->
     41 
     42 using namespace vixl;
     43 
     44 
     45 uint64_t FactorialC(uint64_t n) {
     46   uint64_t result = 1;
     47 
     48   while (n != 0) {
     49     result *= n;
     50     n--;
     51   }
     52 
     53   return result;
     54 }
     55 
     56 double Add3DoubleC(double x, double y, double z) {
     57   return x + y + z;
     58 }
     59 
     60 double Add4DoubleC(uint64_t a, double b, uint64_t c, double d) {
     61   return static_cast<double>(a) + b + static_cast<double>(c) + d;
     62 }
     63 
     64 uint32_t SumArrayC(uint8_t* array, uint32_t size) {
     65   uint32_t result = 0;
     66 
     67   for (uint32_t i = 0; i < size; ++i) {
     68     result += array[i];
     69   }
     70 
     71   return result;
     72 }
     73 
     74 
     75 void GenerateTestWrapper(MacroAssembler* masm, RegisterDump *regs) {
     76   __ Push(xzr, lr);
     77   __ Blr(x15);
     78   regs->Dump(masm);
     79   __ Pop(lr, xzr);
     80   __ Ret();
     81 }
     82 
     83 
     84 #define TEST_FUNCTION(Func)                                             \
     85   do {                                                                  \
     86     int64_t saved_xregs[13];                                            \
     87     saved_xregs[0] = simulator.xreg(19);                                \
     88     saved_xregs[1] = simulator.xreg(20);                                \
     89     saved_xregs[2] = simulator.xreg(21);                                \
     90     saved_xregs[3] = simulator.xreg(22);                                \
     91     saved_xregs[4] = simulator.xreg(23);                                \
     92     saved_xregs[5] = simulator.xreg(24);                                \
     93     saved_xregs[6] = simulator.xreg(25);                                \
     94     saved_xregs[7] = simulator.xreg(26);                                \
     95     saved_xregs[8] = simulator.xreg(27);                                \
     96     saved_xregs[9] = simulator.xreg(28);                                \
     97     saved_xregs[10] = simulator.xreg(29);                               \
     98     saved_xregs[11] = simulator.xreg(30);                               \
     99     saved_xregs[12] = simulator.xreg(31);                               \
    100                                                                         \
    101     uint64_t saved_dregs[8];                                            \
    102     saved_dregs[0] = simulator.dreg_bits(8);                            \
    103     saved_dregs[1] = simulator.dreg_bits(9);                            \
    104     saved_dregs[2] = simulator.dreg_bits(10);                           \
    105     saved_dregs[3] = simulator.dreg_bits(11);                           \
    106     saved_dregs[4] = simulator.dreg_bits(12);                           \
    107     saved_dregs[5] = simulator.dreg_bits(13);                           \
    108     saved_dregs[6] = simulator.dreg_bits(14);                           \
    109     saved_dregs[7] = simulator.dreg_bits(15);                           \
    110                                                                         \
    111     simulator.set_xreg(15, reinterpret_cast<uint64_t>((Func).target()));\
    112     simulator.RunFrom(test.target());                                   \
    113                                                                         \
    114     assert(saved_xregs[0] == simulator.xreg(19));                       \
    115     assert(saved_xregs[1] == simulator.xreg(20));                       \
    116     assert(saved_xregs[2] == simulator.xreg(21));                       \
    117     assert(saved_xregs[3] == simulator.xreg(22));                       \
    118     assert(saved_xregs[4] == simulator.xreg(23));                       \
    119     assert(saved_xregs[5] == simulator.xreg(24));                       \
    120     assert(saved_xregs[6] == simulator.xreg(25));                       \
    121     assert(saved_xregs[7] == simulator.xreg(26));                       \
    122     assert(saved_xregs[8] == simulator.xreg(27));                       \
    123     assert(saved_xregs[9] == simulator.xreg(28));                       \
    124     assert(saved_xregs[10] == simulator.xreg(29));                      \
    125     assert(saved_xregs[11] == simulator.xreg(30));                      \
    126     assert(saved_xregs[12] == simulator.xreg(31));                      \
    127                                                                         \
    128     assert(saved_dregs[0] == simulator.dreg_bits(8));                   \
    129     assert(saved_dregs[1] == simulator.dreg_bits(9));                   \
    130     assert(saved_dregs[2] == simulator.dreg_bits(10));                  \
    131     assert(saved_dregs[3] == simulator.dreg_bits(11));                  \
    132     assert(saved_dregs[4] == simulator.dreg_bits(12));                  \
    133     assert(saved_dregs[5] == simulator.dreg_bits(13));                  \
    134     assert(saved_dregs[6] == simulator.dreg_bits(14));                  \
    135     assert(saved_dregs[7] == simulator.dreg_bits(15));                  \
    136                                                                         \
    137   } while (0)
    138 
    139 #define START()                                             \
    140   byte assm_buf[BUF_SIZE];                                  \
    141   MacroAssembler masm(assm_buf, BUF_SIZE);                  \
    142   Decoder decoder;                                          \
    143   Debugger simulator(&decoder);                             \
    144   simulator.set_coloured_trace(Cctest::coloured_trace());   \
    145   PrintDisassembler* pdis = NULL;                           \
    146   Instrument* inst = NULL;                                  \
    147   if (Cctest::trace_sim()) {                                \
    148     pdis = new PrintDisassembler(stdout);                   \
    149     decoder.PrependVisitor(pdis);                           \
    150   }                                                         \
    151   if (Cctest::instruction_stats()) {                        \
    152     inst = new Instrument("vixl_stats.csv", 10);            \
    153     inst->Enable();                                         \
    154     decoder.AppendVisitor(inst);                            \
    155   }                                                         \
    156   RegisterDump regs;                                        \
    157                                                             \
    158   Label test;                                               \
    159   masm.Bind(&test);                                         \
    160   GenerateTestWrapper(&masm, &regs);                        \
    161   masm.FinalizeCode()
    162 
    163 
    164 #define TEST(name) TEST_(EXAMPLE_##name)
    165 
    166 
    167 #define FACTORIAL_DOTEST(N)                                             \
    168   do {                                                                  \
    169     simulator.ResetState();                                             \
    170     simulator.set_xreg(0, N);                                           \
    171     TEST_FUNCTION(factorial);                                           \
    172     assert(static_cast<uint64_t>(regs.xreg(0)) == FactorialC(N));       \
    173   } while (0)
    174 
    175 TEST(factorial) {
    176   START();
    177 
    178   Label factorial;
    179   masm.Bind(&factorial);
    180   GenerateFactorial(&masm);
    181   masm.FinalizeCode();
    182 
    183   FACTORIAL_DOTEST(0);
    184   FACTORIAL_DOTEST(1);
    185   FACTORIAL_DOTEST(5);
    186   FACTORIAL_DOTEST(10);
    187   FACTORIAL_DOTEST(20);
    188   FACTORIAL_DOTEST(25);
    189 }
    190 
    191 
    192 #define FACTORIAL_REC_DOTEST(N)                                         \
    193   do {                                                                  \
    194     simulator.ResetState();                                             \
    195     simulator.set_xreg(0, N);                                           \
    196     TEST_FUNCTION(factorial_rec);                                       \
    197     assert(static_cast<uint64_t>(regs.xreg(0)) == FactorialC(N));       \
    198   } while (0)
    199 
    200 TEST(factorial_rec) {
    201   START();
    202 
    203   Label factorial_rec;
    204   masm.Bind(&factorial_rec);
    205   GenerateFactorialRec(&masm);
    206   masm.FinalizeCode();
    207 
    208   FACTORIAL_REC_DOTEST(0);
    209   FACTORIAL_REC_DOTEST(1);
    210   FACTORIAL_REC_DOTEST(5);
    211   FACTORIAL_REC_DOTEST(10);
    212   FACTORIAL_REC_DOTEST(20);
    213   FACTORIAL_REC_DOTEST(25);
    214 }
    215 
    216 
    217 #define ADD3_DOUBLE_DOTEST(A, B, C)                                     \
    218   do {                                                                  \
    219     simulator.ResetState();                                             \
    220     simulator.set_dreg(0, A);                                           \
    221     simulator.set_dreg(1, B);                                           \
    222     simulator.set_dreg(2, C);                                           \
    223     TEST_FUNCTION(add3_double);                                         \
    224     assert(regs.dreg(0) == Add3DoubleC(A, B, C));                       \
    225   } while (0)
    226 
    227 TEST(add3_double) {
    228   START();
    229 
    230   Label add3_double;
    231   masm.Bind(&add3_double);
    232   GenerateAdd3Double(&masm);
    233   masm.FinalizeCode();
    234 
    235   ADD3_DOUBLE_DOTEST(0.0, 0.0, 0.0);
    236   ADD3_DOUBLE_DOTEST(457.698, 14.36, 2.00025);
    237   ADD3_DOUBLE_DOTEST(-45.55, -98.9, -0.354);
    238   ADD3_DOUBLE_DOTEST(.55, .9, .12);
    239 }
    240 
    241 
    242 #define ADD4_DOUBLE_DOTEST(A, B, C, D)                                  \
    243   do {                                                                  \
    244     simulator.ResetState();                                             \
    245     simulator.set_xreg(0, A);                                           \
    246     simulator.set_dreg(0, B);                                           \
    247     simulator.set_xreg(1, C);                                           \
    248     simulator.set_dreg(1, D);                                           \
    249     TEST_FUNCTION(add4_double);                                         \
    250     assert(regs.dreg(0) == Add4DoubleC(A, B, C, D));                    \
    251   } while (0)
    252 
    253 TEST(add4_double) {
    254   START();
    255 
    256   Label add4_double;
    257   masm.Bind(&add4_double);
    258   GenerateAdd4Double(&masm);
    259   masm.FinalizeCode();
    260 
    261   ADD4_DOUBLE_DOTEST(0, 0, 0, 0);
    262   ADD4_DOUBLE_DOTEST(4, 3.287, 6, 13.48);
    263   ADD4_DOUBLE_DOTEST(56, 665.368, 0, -4932.4697);
    264   ADD4_DOUBLE_DOTEST(56, 0, 546, 0);
    265   ADD4_DOUBLE_DOTEST(0, 0.658, 0, 0.00000011540026);
    266 }
    267 
    268 
    269 #define SUM_ARRAY_DOTEST(Array)                                         \
    270   do {                                                                  \
    271     simulator.ResetState();                                             \
    272     uintptr_t addr = reinterpret_cast<uintptr_t>(Array);                \
    273     simulator.set_xreg(0, addr);                                        \
    274     simulator.set_xreg(1, ARRAY_SIZE(Array));                           \
    275     TEST_FUNCTION(sum_array);                                           \
    276     assert(regs.xreg(0) == SumArrayC(Array, ARRAY_SIZE(Array)));        \
    277   } while (0)
    278 
    279 TEST(sum_array) {
    280   START();
    281 
    282   Label sum_array;
    283   masm.Bind(&sum_array);
    284   GenerateSumArray(&masm);
    285   masm.FinalizeCode();
    286 
    287   uint8_t data1[] = { 4, 9, 13, 3, 2, 6, 5 };
    288   SUM_ARRAY_DOTEST(data1);
    289 
    290   uint8_t data2[] = { 42 };
    291   SUM_ARRAY_DOTEST(data2);
    292 
    293   uint8_t data3[1000];
    294   for (unsigned int i = 0; i < ARRAY_SIZE(data3); ++i)
    295     data3[i] = 255;
    296   SUM_ARRAY_DOTEST(data3);
    297 }
    298 
    299 
    300 #define ABS_DOTEST(X)                                                   \
    301   do {                                                                  \
    302     simulator.ResetState();                                             \
    303     simulator.set_xreg(0, X);                                           \
    304     TEST_FUNCTION(func_abs);                                            \
    305     assert(regs.xreg(0) == abs(X));                                     \
    306   } while (0)
    307 
    308 TEST(abs) {
    309   START();
    310 
    311   Label func_abs;
    312   masm.Bind(&func_abs);
    313   GenerateAbs(&masm);
    314   masm.FinalizeCode();
    315 
    316   ABS_DOTEST(-42);
    317   ABS_DOTEST(0);
    318   ABS_DOTEST(545);
    319   ABS_DOTEST(-428751489);
    320 }
    321 
    322 
    323 TEST(swap4) {
    324   START();
    325 
    326   Label swap4;
    327   masm.Bind(&swap4);
    328   GenerateSwap4(&masm);
    329   masm.FinalizeCode();
    330 
    331   int64_t a = 15;
    332   int64_t b = 26;
    333   int64_t c = 46;
    334   int64_t d = 79;
    335 
    336   simulator.set_xreg(0, a);
    337   simulator.set_xreg(1, b);
    338   simulator.set_xreg(2, c);
    339   simulator.set_xreg(3, d);
    340   TEST_FUNCTION(swap4);
    341   assert(regs.xreg(0) == d);
    342   assert(regs.xreg(1) == c);
    343   assert(regs.xreg(2) == b);
    344   assert(regs.xreg(3) == a);
    345 }
    346 
    347 
    348 TEST(swap_int32) {
    349   START();
    350 
    351   Label swap_int32;
    352   masm.Bind(&swap_int32);
    353   GenerateSwapInt32(&masm);
    354   masm.FinalizeCode();
    355 
    356   int32_t x = 168;
    357   int32_t y = 246;
    358   simulator.set_wreg(0, x);
    359   simulator.set_wreg(1, y);
    360   TEST_FUNCTION(swap_int32);
    361   assert(regs.wreg(0) == y);
    362   assert(regs.wreg(1) == x);
    363 }
    364 
    365 
    366 #define CHECKBOUNDS_DOTEST(Value, Low, High)                            \
    367   do {                                                                  \
    368     simulator.ResetState();                                             \
    369     simulator.set_xreg(0, Value);                                       \
    370     simulator.set_xreg(1, Low);                                         \
    371     simulator.set_xreg(2, High);                                        \
    372     TEST_FUNCTION(check_bounds);                                        \
    373     assert(regs.xreg(0) == ((Low <= Value) && (Value <= High)));        \
    374   } while (0)
    375 
    376 TEST(check_bounds) {
    377   START();
    378 
    379   Label check_bounds;
    380   masm.Bind(&check_bounds);
    381   GenerateCheckBounds(&masm);
    382   masm.FinalizeCode();
    383 
    384   CHECKBOUNDS_DOTEST(0, 100, 200);
    385   CHECKBOUNDS_DOTEST(58, 100, 200);
    386   CHECKBOUNDS_DOTEST(99, 100, 200);
    387   CHECKBOUNDS_DOTEST(100, 100, 200);
    388   CHECKBOUNDS_DOTEST(101, 100, 200);
    389   CHECKBOUNDS_DOTEST(150, 100, 200);
    390   CHECKBOUNDS_DOTEST(199, 100, 200);
    391   CHECKBOUNDS_DOTEST(200, 100, 200);
    392   CHECKBOUNDS_DOTEST(201, 100, 200);
    393 }
    394 
    395 
    396 #define GETTING_STARTED_DOTEST(Value)                           \
    397   do {                                                          \
    398     simulator.ResetState();                                     \
    399     simulator.set_xreg(0, Value);                               \
    400     TEST_FUNCTION(demo_function);                               \
    401     assert(regs.xreg(0) == (Value & 0x1122334455667788));       \
    402   } while (0)
    403 
    404 TEST(getting_started) {
    405   START();
    406 
    407   Label demo_function;
    408   masm.Bind(&demo_function);
    409   GenerateDemoFunction(&masm);
    410   masm.FinalizeCode();
    411 
    412   GETTING_STARTED_DOTEST(0x8899aabbccddeeff);
    413   GETTING_STARTED_DOTEST(0x1122334455667788);
    414   GETTING_STARTED_DOTEST(0x0000000000000000);
    415   GETTING_STARTED_DOTEST(0xffffffffffffffff);
    416   GETTING_STARTED_DOTEST(0x5a5a5a5a5a5a5a5a);
    417 }
    418 
    419 #endif  // USE_SIMULATOR
    420