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, ®s); \ 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