| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/os.h" | 9 #include "vm/os.h" |
| 10 #include "vm/unit_test.h" | 10 #include "vm/unit_test.h" |
| 11 #include "vm/virtual_memory.h" | 11 #include "vm/virtual_memory.h" |
| 12 | 12 |
| 13 namespace dart { | 13 namespace dart { |
| 14 | 14 |
| 15 #define __ assembler-> | 15 #define __ assembler-> |
| 16 | 16 |
| 17 | 17 |
| 18 ASSEMBLER_TEST_GENERATE(Simple, assembler) { | 18 ASSEMBLER_TEST_GENERATE(Simple, assembler) { |
| 19 __ mov(R0, ShifterOperand(42)); | 19 __ mov(R0, ShifterOperand(42)); |
| 20 __ mov(PC, ShifterOperand(LR)); | 20 __ mov(PC, ShifterOperand(LR)); |
| 21 } | 21 } |
| 22 | 22 |
| 23 | 23 |
| 24 ASSEMBLER_TEST_RUN(Simple, test) { | 24 ASSEMBLER_TEST_RUN(Simple, test) { |
| 25 typedef int (*SimpleCode)(); | 25 typedef int (*SimpleCode)(); |
| 26 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry())); | 26 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry())); |
| 27 } | 27 } |
| 28 | 28 |
| 29 |
| 30 ASSEMBLER_TEST_GENERATE(MoveNegated, assembler) { |
| 31 __ mvn(R0, ShifterOperand(42)); |
| 32 __ mov(PC, ShifterOperand(LR)); |
| 33 } |
| 34 |
| 35 |
| 36 ASSEMBLER_TEST_RUN(MoveNegated, test) { |
| 37 EXPECT(test != NULL); |
| 38 typedef int (*MoveNegated)(); |
| 39 EXPECT_EQ(~42, EXECUTE_TEST_CODE_INT32(MoveNegated, test->entry())); |
| 40 } |
| 41 |
| 42 |
| 43 ASSEMBLER_TEST_GENERATE(MoveRotImm, assembler) { |
| 44 ShifterOperand shifter_op; |
| 45 EXPECT(ShifterOperand::CanHold(0x00550000, &shifter_op)); |
| 46 __ mov(R0, shifter_op); |
| 47 EXPECT(ShifterOperand::CanHold(0x30000003, &shifter_op)); |
| 48 __ add(R0, R0, shifter_op); |
| 49 __ mov(PC, ShifterOperand(LR)); |
| 50 } |
| 51 |
| 52 |
| 53 ASSEMBLER_TEST_RUN(MoveRotImm, test) { |
| 54 EXPECT(test != NULL); |
| 55 typedef int (*MoveRotImm)(); |
| 56 EXPECT_EQ(0x30550003, EXECUTE_TEST_CODE_INT32(MoveRotImm, test->entry())); |
| 57 } |
| 58 |
| 59 |
| 60 ASSEMBLER_TEST_GENERATE(MovImm16, assembler) { |
| 61 __ movw(R0, 0x5678); |
| 62 __ movt(R0, 0x1234); |
| 63 __ mov(PC, ShifterOperand(LR)); |
| 64 } |
| 65 |
| 66 |
| 67 ASSEMBLER_TEST_RUN(MovImm16, test) { |
| 68 EXPECT(test != NULL); |
| 69 typedef int (*MovImm16)(); |
| 70 EXPECT_EQ(0x12345678, EXECUTE_TEST_CODE_INT32(MovImm16, test->entry())); |
| 71 } |
| 72 |
| 73 |
| 74 ASSEMBLER_TEST_GENERATE(LoadImmediate, assembler) { |
| 75 __ mov(R0, ShifterOperand(0)); |
| 76 __ cmp(R0, ShifterOperand(0)); |
| 77 __ LoadImmediate(R0, 0x12345678, EQ); |
| 78 __ LoadImmediate(R0, 0x87654321, NE); |
| 79 __ mov(PC, ShifterOperand(LR)); |
| 80 } |
| 81 |
| 82 |
| 83 ASSEMBLER_TEST_RUN(LoadImmediate, test) { |
| 84 EXPECT(test != NULL); |
| 85 typedef int (*LoadImmediate)(); |
| 86 EXPECT_EQ(0x12345678, EXECUTE_TEST_CODE_INT32(LoadImmediate, test->entry())); |
| 87 } |
| 88 |
| 89 |
| 90 ASSEMBLER_TEST_GENERATE(Vmov, assembler) { |
| 91 __ mov(R3, ShifterOperand(43)); |
| 92 __ mov(R1, ShifterOperand(41)); |
| 93 __ vmovsrr(S1, R1, R3); // S1:S2 = 41:43 |
| 94 __ vmovs(S0, S2); // S0 = S2, S0:S1 == 43:41 |
| 95 __ vmovd(D2, D0); // D2 = D0, S4:S5 == 43:41 |
| 96 __ vmovrs(R3, S5); // R3 = S5, R3 == 41 |
| 97 __ vmovrrs(R1, R2, S4); // R1:R2 = S4:S5, R1:R2 == 43:41 |
| 98 __ vmovdrr(D3, R3, R2); // D3 = R3:R2, S6:S7 == 41:41 |
| 99 __ vmovsr(S7, R1); // S7 = R1, S6:S7 == 41:43 |
| 100 __ vmovrrd(R0, R1, D3); // R0:R1 = D3, R0:R1 == 41:43 |
| 101 __ sub(R0, R1, ShifterOperand(R0)); // 43-41 |
| 102 __ mov(PC, ShifterOperand(LR)); |
| 103 } |
| 104 |
| 105 |
| 106 ASSEMBLER_TEST_RUN(Vmov, test) { |
| 107 EXPECT(test != NULL); |
| 108 typedef int (*Vmov)(); |
| 109 EXPECT_EQ(2, EXECUTE_TEST_CODE_INT32(Vmov, test->entry())); |
| 110 } |
| 111 |
| 112 |
| 113 ASSEMBLER_TEST_GENERATE(SingleVLoadStore, assembler) { |
| 114 __ LoadImmediate(R0, bit_cast<int32_t, float>(12.3f)); |
| 115 __ mov(R2, ShifterOperand(SP)); |
| 116 __ str(R0, Address(SP, (-kWordSize * 30), Address::PreIndex)); |
| 117 __ vldrs(S0, Address(R2, (-kWordSize * 30))); |
| 118 __ vadds(S0, S0, S0); |
| 119 __ vstrs(S0, Address(R2, (-kWordSize * 30))); |
| 120 __ ldr(R0, Address(SP, (kWordSize * 30), Address::PostIndex)); |
| 121 __ mov(PC, ShifterOperand(LR)); |
| 122 } |
| 123 |
| 124 |
| 125 ASSEMBLER_TEST_RUN(SingleVLoadStore, test) { |
| 126 EXPECT(test != NULL); |
| 127 typedef float (*SingleVLoadStore)(); |
| 128 float res = EXECUTE_TEST_CODE_FLOAT(SingleVLoadStore, test->entry()); |
| 129 EXPECT_FLOAT_EQ(2*12.3f, res, 0.001f); |
| 130 } |
| 131 |
| 132 |
| 133 ASSEMBLER_TEST_GENERATE(DoubleVLoadStore, assembler) { |
| 134 int64_t value = bit_cast<int64_t, double>(12.3); |
| 135 __ LoadImmediate(R0, Utils::Low32Bits(value)); |
| 136 __ LoadImmediate(R1, Utils::High32Bits(value)); |
| 137 __ mov(R2, ShifterOperand(SP)); |
| 138 __ str(R0, Address(SP, (-kWordSize * 30), Address::PreIndex)); |
| 139 __ str(R1, Address(R2, (-kWordSize * 29))); |
| 140 __ vldrd(D0, Address(R2, (-kWordSize * 30))); |
| 141 __ vaddd(D0, D0, D0); |
| 142 __ vstrd(D0, Address(R2, (-kWordSize * 30))); |
| 143 __ ldr(R1, Address(R2, (-kWordSize * 29))); |
| 144 __ ldr(R0, Address(SP, (kWordSize * 30), Address::PostIndex)); |
| 145 __ mov(PC, ShifterOperand(LR)); |
| 146 } |
| 147 |
| 148 |
| 149 ASSEMBLER_TEST_RUN(DoubleVLoadStore, test) { |
| 150 EXPECT(test != NULL); |
| 151 typedef double (*DoubleVLoadStore)(); |
| 152 double res = EXECUTE_TEST_CODE_DOUBLE(DoubleVLoadStore, test->entry()); |
| 153 EXPECT_FLOAT_EQ(2*12.3, res, 0.001); |
| 154 } |
| 155 |
| 156 |
| 157 ASSEMBLER_TEST_GENERATE(SingleFPOperations, assembler) { |
| 158 __ LoadSImmediate(S0, 12.3f); |
| 159 __ LoadSImmediate(S1, 3.4f); |
| 160 __ vnegs(S0, S0); // -12.3f |
| 161 __ vabss(S0, S0); // 12.3f |
| 162 __ vadds(S0, S0, S1); // 15.7f |
| 163 __ vmuls(S0, S0, S1); // 53.38f |
| 164 __ vsubs(S0, S0, S1); // 49.98f |
| 165 __ vdivs(S0, S0, S1); // 14.7f |
| 166 __ vsqrts(S0, S0); // 3.8340579f |
| 167 __ vmovrs(R0, S0); |
| 168 __ mov(PC, ShifterOperand(LR)); |
| 169 } |
| 170 |
| 171 |
| 172 ASSEMBLER_TEST_RUN(SingleFPOperations, test) { |
| 173 EXPECT(test != NULL); |
| 174 typedef float (*SingleFPOperations)(); |
| 175 float res = EXECUTE_TEST_CODE_FLOAT(SingleFPOperations, test->entry()); |
| 176 EXPECT_FLOAT_EQ(3.8340579f, res, 0.001f); |
| 177 } |
| 178 |
| 179 |
| 180 ASSEMBLER_TEST_GENERATE(DoubleFPOperations, assembler) { |
| 181 __ LoadDImmediate(D0, 12.3, R0); |
| 182 __ LoadDImmediate(D1, 3.4, R0); |
| 183 __ vnegd(D0, D0); // -12.3 |
| 184 __ vabsd(D0, D0); // 12.3 |
| 185 __ vaddd(D0, D0, D1); // 15.7 |
| 186 __ vmuld(D0, D0, D1); // 53.38 |
| 187 __ vsubd(D0, D0, D1); // 49.98 |
| 188 __ vdivd(D0, D0, D1); // 14.7 |
| 189 __ vsqrtd(D0, D0); // 3.8340579 |
| 190 __ vmovrrd(R0, R1, D0); |
| 191 __ mov(PC, ShifterOperand(LR)); |
| 192 } |
| 193 |
| 194 |
| 195 ASSEMBLER_TEST_RUN(DoubleFPOperations, test) { |
| 196 EXPECT(test != NULL); |
| 197 typedef double (*DoubleFPOperations)(); |
| 198 double res = EXECUTE_TEST_CODE_DOUBLE(DoubleFPOperations, test->entry()); |
| 199 EXPECT_FLOAT_EQ(3.8340579, res, 0.001); |
| 200 } |
| 201 |
| 202 |
| 203 ASSEMBLER_TEST_GENERATE(IntToDoubleConversion, assembler) { |
| 204 __ mov(R3, ShifterOperand(6)); |
| 205 __ vmovsr(S3, R3); |
| 206 __ vcvtdi(D1, S3); |
| 207 __ vmovrrd(R0, R1, D1); |
| 208 __ mov(PC, ShifterOperand(LR)); |
| 209 } |
| 210 |
| 211 |
| 212 ASSEMBLER_TEST_RUN(IntToDoubleConversion, test) { |
| 213 typedef double (*IntToDoubleConversionCode)(); |
| 214 EXPECT(test != NULL); |
| 215 double res = EXECUTE_TEST_CODE_DOUBLE(IntToDoubleConversionCode, |
| 216 test->entry()); |
| 217 EXPECT_FLOAT_EQ(6.0, res, 0.001); |
| 218 } |
| 219 |
| 220 |
| 221 ASSEMBLER_TEST_GENERATE(LongToDoubleConversion, assembler) { |
| 222 int64_t value = 60000000000LL; |
| 223 __ LoadImmediate(R0, Utils::Low32Bits(value)); |
| 224 __ LoadImmediate(R1, Utils::High32Bits(value)); |
| 225 __ vmovsr(S0, R0); |
| 226 __ vmovsr(S2, R1); |
| 227 __ vcvtdu(D0, S0); |
| 228 __ vcvtdi(D1, S2); |
| 229 __ LoadDImmediate(D2, 1.0 * (1LL << 32), R0); |
| 230 __ vmlad(D0, D1, D2); |
| 231 __ vmovrrd(R0, R1, D0); |
| 232 __ mov(PC, ShifterOperand(LR)); |
| 233 } |
| 234 |
| 235 |
| 236 ASSEMBLER_TEST_RUN(LongToDoubleConversion, test) { |
| 237 typedef double (*LongToDoubleConversionCode)(); |
| 238 EXPECT(test != NULL); |
| 239 double res = EXECUTE_TEST_CODE_DOUBLE(LongToDoubleConversionCode, |
| 240 test->entry()); |
| 241 EXPECT_FLOAT_EQ(60000000000.0, res, 0.001); |
| 242 } |
| 243 |
| 244 |
| 245 ASSEMBLER_TEST_GENERATE(IntToFloatConversion, assembler) { |
| 246 __ mov(R3, ShifterOperand(6)); |
| 247 __ vmovsr(S3, R3); |
| 248 __ vcvtsi(S1, S3); |
| 249 __ vmovrs(R0, S1); |
| 250 __ mov(PC, ShifterOperand(LR)); |
| 251 } |
| 252 |
| 253 |
| 254 ASSEMBLER_TEST_RUN(IntToFloatConversion, test) { |
| 255 typedef float (*IntToFloatConversionCode)(); |
| 256 EXPECT(test != NULL); |
| 257 float res = EXECUTE_TEST_CODE_FLOAT(IntToFloatConversionCode, test->entry()); |
| 258 EXPECT_FLOAT_EQ(6.0, res, 0.001); |
| 259 } |
| 260 |
| 261 |
| 262 ASSEMBLER_TEST_GENERATE(FloatToIntConversion, assembler) { |
| 263 __ vmovsr(S1, R0); |
| 264 __ vcvtis(S0, S1); |
| 265 __ vmovrs(R0, S0); |
| 266 __ mov(PC, ShifterOperand(LR)); |
| 267 } |
| 268 |
| 269 |
| 270 ASSEMBLER_TEST_RUN(FloatToIntConversion, test) { |
| 271 typedef int (*FloatToIntConversion)(float arg); |
| 272 EXPECT(test != NULL); |
| 273 EXPECT_EQ(12, |
| 274 EXECUTE_TEST_CODE_INT32_F(FloatToIntConversion, test->entry(), |
| 275 12.8f)); |
| 276 EXPECT_EQ(INT_MIN, |
| 277 EXECUTE_TEST_CODE_INT32_F(FloatToIntConversion, test->entry(), |
| 278 -FLT_MAX)); |
| 279 EXPECT_EQ(INT_MAX, |
| 280 EXECUTE_TEST_CODE_INT32_F(FloatToIntConversion, test->entry(), |
| 281 FLT_MAX)); |
| 282 } |
| 283 |
| 284 |
| 285 ASSEMBLER_TEST_GENERATE(DoubleToIntConversion, assembler) { |
| 286 __ vmovdrr(D1, R0, R1); |
| 287 __ vcvtid(S0, D1); |
| 288 __ vmovrs(R0, S0); |
| 289 __ mov(PC, ShifterOperand(LR)); |
| 290 } |
| 291 |
| 292 |
| 293 ASSEMBLER_TEST_RUN(DoubleToIntConversion, test) { |
| 294 typedef int (*DoubleToIntConversion)(double arg); |
| 295 EXPECT(test != NULL); |
| 296 EXPECT_EQ(12, |
| 297 EXECUTE_TEST_CODE_INT32_D(DoubleToIntConversion, test->entry(), |
| 298 12.8)); |
| 299 EXPECT_EQ(INT_MIN, |
| 300 EXECUTE_TEST_CODE_INT32_D(DoubleToIntConversion, test->entry(), |
| 301 -DBL_MAX)); |
| 302 EXPECT_EQ(INT_MAX, |
| 303 EXECUTE_TEST_CODE_INT32_D(DoubleToIntConversion, test->entry(), |
| 304 DBL_MAX)); |
| 305 } |
| 306 |
| 307 |
| 308 ASSEMBLER_TEST_GENERATE(FloatToDoubleConversion, assembler) { |
| 309 __ LoadSImmediate(S1, 12.8f); |
| 310 __ vcvtds(D2, S1); |
| 311 __ vmovrrd(R0, R1, D2); |
| 312 __ mov(PC, ShifterOperand(LR)); |
| 313 } |
| 314 |
| 315 |
| 316 ASSEMBLER_TEST_RUN(FloatToDoubleConversion, test) { |
| 317 typedef double (*FloatToDoubleConversionCode)(); |
| 318 EXPECT(test != NULL); |
| 319 double res = EXECUTE_TEST_CODE_DOUBLE(FloatToDoubleConversionCode, |
| 320 test->entry()); |
| 321 EXPECT_FLOAT_EQ(12.8, res, 0.001); |
| 322 } |
| 323 |
| 324 |
| 325 ASSEMBLER_TEST_GENERATE(DoubleToFloatConversion, assembler) { |
| 326 __ LoadDImmediate(D1, 12.8, R0); |
| 327 __ vcvtsd(S3, D1); |
| 328 __ vmovrs(R0, S3); |
| 329 __ mov(PC, ShifterOperand(LR)); |
| 330 } |
| 331 |
| 332 |
| 333 ASSEMBLER_TEST_RUN(DoubleToFloatConversion, test) { |
| 334 typedef float (*DoubleToFloatConversionCode)(); |
| 335 EXPECT(test != NULL); |
| 336 float res = EXECUTE_TEST_CODE_FLOAT(DoubleToFloatConversionCode, |
| 337 test->entry()); |
| 338 EXPECT_FLOAT_EQ(12.8, res, 0.001); |
| 339 } |
| 340 |
| 341 |
| 342 ASSEMBLER_TEST_GENERATE(FloatCompare, assembler) { |
| 343 // Test 12.3f vs 12.5f. |
| 344 __ LoadSImmediate(S0, 12.3f); |
| 345 __ LoadSImmediate(S1, 12.5f); |
| 346 |
| 347 // Count errors in R0. R0 is zero if no errors found. |
| 348 __ mov(R0, ShifterOperand(0)); |
| 349 __ vcmps(S0, S1); |
| 350 __ vmstat(); |
| 351 __ add(R0, R0, ShifterOperand(1), VS); // Error if unordered (Nan). |
| 352 __ add(R0, R0, ShifterOperand(2), GT); // Error if greater. |
| 353 __ add(R0, R0, ShifterOperand(4), EQ); // Error if equal. |
| 354 __ add(R0, R0, ShifterOperand(8), PL); // Error if not less. |
| 355 |
| 356 // Test NaN. |
| 357 // Create NaN by dividing 0.0f/0.0f. |
| 358 __ LoadSImmediate(S1, 0.0f); |
| 359 __ vdivs(S1, S1, S1); |
| 360 __ vcmps(S1, S1); |
| 361 __ vmstat(); |
| 362 __ add(R0, R0, ShifterOperand(16), VC); // Error if not unordered (not Nan). |
| 363 |
| 364 // R0 is 0 if all tests passed. |
| 365 __ mov(PC, ShifterOperand(LR)); |
| 366 } |
| 367 |
| 368 |
| 369 ASSEMBLER_TEST_RUN(FloatCompare, test) { |
| 370 EXPECT(test != NULL); |
| 371 typedef int (*FloatCompare)(); |
| 372 EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(FloatCompare, test->entry())); |
| 373 } |
| 374 |
| 375 |
| 376 ASSEMBLER_TEST_GENERATE(DoubleCompare, assembler) { |
| 377 // Test 12.3 vs 12.5. |
| 378 __ LoadDImmediate(D0, 12.3, R1); |
| 379 __ LoadDImmediate(D1, 12.5, R1); |
| 380 |
| 381 // Count errors in R0. R0 is zero if no errors found. |
| 382 __ mov(R0, ShifterOperand(0)); |
| 383 __ vcmpd(D0, D1); |
| 384 __ vmstat(); |
| 385 __ add(R0, R0, ShifterOperand(1), VS); // Error if unordered (Nan). |
| 386 __ add(R0, R0, ShifterOperand(2), GT); // Error if greater. |
| 387 __ add(R0, R0, ShifterOperand(4), EQ); // Error if equal. |
| 388 __ add(R0, R0, ShifterOperand(8), PL); // Error if not less. |
| 389 |
| 390 // Test NaN. |
| 391 // Create NaN by dividing 0.0/0.0. |
| 392 __ LoadDImmediate(D1, 0.0, R1); |
| 393 __ vdivd(D1, D1, D1); |
| 394 __ vcmpd(D1, D1); |
| 395 __ vmstat(); |
| 396 __ add(R0, R0, ShifterOperand(16), VC); // Error if not unordered (not Nan). |
| 397 |
| 398 // R0 is 0 if all tests passed. |
| 399 __ mov(PC, ShifterOperand(LR)); |
| 400 } |
| 401 |
| 402 |
| 403 ASSEMBLER_TEST_RUN(DoubleCompare, test) { |
| 404 EXPECT(test != NULL); |
| 405 typedef int (*DoubleCompare)(); |
| 406 EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(DoubleCompare, test->entry())); |
| 407 } |
| 408 |
| 409 |
| 410 ASSEMBLER_TEST_GENERATE(Loop, assembler) { |
| 411 Label loop_entry; |
| 412 __ mov(R0, ShifterOperand(1)); |
| 413 __ mov(R1, ShifterOperand(2)); |
| 414 __ Bind(&loop_entry); |
| 415 __ mov(R0, ShifterOperand(R0, LSL, 1)); |
| 416 __ movs(R1, ShifterOperand(R1, LSR, 1)); |
| 417 __ b(&loop_entry, NE); |
| 418 __ mov(PC, ShifterOperand(LR)); |
| 419 } |
| 420 |
| 421 |
| 422 ASSEMBLER_TEST_RUN(Loop, test) { |
| 423 EXPECT(test != NULL); |
| 424 typedef int (*Loop)(); |
| 425 EXPECT_EQ(4, EXECUTE_TEST_CODE_INT32(Loop, test->entry())); |
| 426 } |
| 427 |
| 428 |
| 429 ASSEMBLER_TEST_GENERATE(ForwardBranch, assembler) { |
| 430 Label skip; |
| 431 __ mov(R0, ShifterOperand(42)); |
| 432 __ b(&skip); |
| 433 __ mov(R0, ShifterOperand(11)); |
| 434 __ Bind(&skip); |
| 435 __ mov(PC, ShifterOperand(LR)); |
| 436 } |
| 437 |
| 438 |
| 439 ASSEMBLER_TEST_RUN(ForwardBranch, test) { |
| 440 EXPECT(test != NULL); |
| 441 typedef int (*ForwardBranch)(); |
| 442 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(ForwardBranch, test->entry())); |
| 443 } |
| 444 |
| 445 |
| 446 ASSEMBLER_TEST_GENERATE(LoadStore, assembler) { |
| 447 __ mov(R1, ShifterOperand(123)); |
| 448 __ Push(R1); |
| 449 __ Pop(R0); |
| 450 __ mov(PC, ShifterOperand(LR)); |
| 451 } |
| 452 |
| 453 |
| 454 ASSEMBLER_TEST_RUN(LoadStore, test) { |
| 455 EXPECT(test != NULL); |
| 456 typedef int (*LoadStore)(); |
| 457 EXPECT_EQ(123, EXECUTE_TEST_CODE_INT32(LoadStore, test->entry())); |
| 458 } |
| 459 |
| 460 |
| 461 ASSEMBLER_TEST_GENERATE(AddSub, assembler) { |
| 462 __ mov(R1, ShifterOperand(40)); |
| 463 __ sub(R1, R1, ShifterOperand(2)); |
| 464 __ add(R0, R1, ShifterOperand(4)); |
| 465 __ rsbs(R0, R0, ShifterOperand(100)); |
| 466 __ rsc(R0, R0, ShifterOperand(100)); |
| 467 __ mov(PC, ShifterOperand(LR)); |
| 468 } |
| 469 |
| 470 |
| 471 ASSEMBLER_TEST_RUN(AddSub, test) { |
| 472 EXPECT(test != NULL); |
| 473 typedef int (*AddSub)(); |
| 474 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(AddSub, test->entry())); |
| 475 } |
| 476 |
| 477 |
| 478 ASSEMBLER_TEST_GENERATE(Semaphore, assembler) { |
| 479 __ mov(R0, ShifterOperand(40)); |
| 480 __ mov(R1, ShifterOperand(42)); |
| 481 __ Push(R0); |
| 482 Label retry; |
| 483 __ Bind(&retry); |
| 484 __ ldrex(R0, SP); |
| 485 __ strex(IP, R1, SP); // IP == 0, success |
| 486 __ tst(IP, ShifterOperand(0)); |
| 487 __ b(&retry, NE); // NE if context switch occurred between ldrex and strex. |
| 488 __ Pop(R0); // 42 |
| 489 __ mov(PC, ShifterOperand(LR)); |
| 490 } |
| 491 |
| 492 |
| 493 ASSEMBLER_TEST_RUN(Semaphore, test) { |
| 494 EXPECT(test != NULL); |
| 495 typedef int (*Semaphore)(); |
| 496 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Semaphore, test->entry())); |
| 497 } |
| 498 |
| 499 |
| 500 ASSEMBLER_TEST_GENERATE(FailedSemaphore, assembler) { |
| 501 __ mov(R0, ShifterOperand(40)); |
| 502 __ mov(R1, ShifterOperand(42)); |
| 503 __ Push(R0); |
| 504 __ ldrex(R0, SP); |
| 505 __ clrex(); // Simulate a context switch. |
| 506 __ strex(IP, R1, SP); // IP == 1, failure |
| 507 __ Pop(R0); // 40 |
| 508 __ add(R0, R0, ShifterOperand(IP)); |
| 509 __ mov(PC, ShifterOperand(LR)); |
| 510 } |
| 511 |
| 512 |
| 513 ASSEMBLER_TEST_RUN(FailedSemaphore, test) { |
| 514 EXPECT(test != NULL); |
| 515 typedef int (*FailedSemaphore)(); |
| 516 EXPECT_EQ(41, EXECUTE_TEST_CODE_INT32(FailedSemaphore, test->entry())); |
| 517 } |
| 518 |
| 519 |
| 520 ASSEMBLER_TEST_GENERATE(AndOrr, assembler) { |
| 521 __ mov(R1, ShifterOperand(40)); |
| 522 __ mov(R2, ShifterOperand(0)); |
| 523 __ and_(R1, R2, ShifterOperand(R1)); |
| 524 __ mov(R3, ShifterOperand(42)); |
| 525 __ orr(R0, R1, ShifterOperand(R3)); |
| 526 __ mov(PC, ShifterOperand(LR)); |
| 527 } |
| 528 |
| 529 |
| 530 ASSEMBLER_TEST_RUN(AndOrr, test) { |
| 531 EXPECT(test != NULL); |
| 532 typedef int (*AndOrr)(); |
| 533 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(AndOrr, test->entry())); |
| 534 } |
| 535 |
| 536 |
| 537 ASSEMBLER_TEST_GENERATE(Orrs, assembler) { |
| 538 __ mov(R0, ShifterOperand(0)); |
| 539 __ tst(R0, ShifterOperand(R1)); // Set zero-flag. |
| 540 __ orrs(R0, R0, ShifterOperand(1)); // Clear zero-flag. |
| 541 __ mov(PC, ShifterOperand(LR), EQ); |
| 542 __ mov(R0, ShifterOperand(42)); |
| 543 __ mov(PC, ShifterOperand(LR), NE); // Only this return should fire. |
| 544 __ mov(R0, ShifterOperand(2)); |
| 545 __ mov(PC, ShifterOperand(LR)); |
| 546 } |
| 547 |
| 548 |
| 549 ASSEMBLER_TEST_RUN(Orrs, test) { |
| 550 EXPECT(test != NULL); |
| 551 typedef int (*Orrs)(); |
| 552 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Orrs, test->entry())); |
| 553 } |
| 554 |
| 555 |
| 556 ASSEMBLER_TEST_GENERATE(Multiply, assembler) { |
| 557 __ mov(R1, ShifterOperand(20)); |
| 558 __ mov(R2, ShifterOperand(40)); |
| 559 __ mul(R3, R2, R1); |
| 560 __ mov(R0, ShifterOperand(R3)); |
| 561 __ mov(PC, ShifterOperand(LR)); |
| 562 } |
| 563 |
| 564 |
| 565 ASSEMBLER_TEST_RUN(Multiply, test) { |
| 566 EXPECT(test != NULL); |
| 567 typedef int (*Multiply)(); |
| 568 EXPECT_EQ(800, EXECUTE_TEST_CODE_INT32(Multiply, test->entry())); |
| 569 } |
| 570 |
| 571 |
| 572 ASSEMBLER_TEST_GENERATE(QuotientRemainder, assembler) { |
| 573 __ vmovsr(S2, R0); |
| 574 __ vmovsr(S4, R2); |
| 575 __ vcvtdi(D1, S2); |
| 576 __ vcvtdi(D2, S4); |
| 577 __ vdivd(D0, D1, D2); |
| 578 __ vcvtid(S0, D0); |
| 579 __ vmovrs(R1, S0); // r1 = r0/r2 |
| 580 __ mls(R0, R1, R2, R0); // r0 = r0 - r1*r2 |
| 581 __ mov(PC, ShifterOperand(LR)); |
| 582 } |
| 583 |
| 584 |
| 585 ASSEMBLER_TEST_RUN(QuotientRemainder, test) { |
| 586 EXPECT(test != NULL); |
| 587 typedef int64_t (*QuotientRemainder)(int64_t dividend, int64_t divisor); |
| 588 EXPECT_EQ(0x1000400000da8LL, |
| 589 EXECUTE_TEST_CODE_INT64_LL(QuotientRemainder, test->entry(), |
| 590 0x12345678, 0x1234)); |
| 591 } |
| 592 |
| 593 |
| 594 ASSEMBLER_TEST_GENERATE(LongMultiply, assembler) { |
| 595 __ Push(R4); |
| 596 __ Mov(IP, R0); |
| 597 __ mul(R4, R2, R1); |
| 598 __ umull(R0, R1, R2, IP); |
| 599 __ mla(R2, IP, R3, R4); |
| 600 __ add(R1, R2, ShifterOperand(R1)); |
| 601 __ Pop(R4); |
| 602 __ mov(PC, ShifterOperand(LR)); |
| 603 } |
| 604 |
| 605 |
| 606 ASSEMBLER_TEST_RUN(LongMultiply, test) { |
| 607 EXPECT(test != NULL); |
| 608 typedef int64_t (*LongMultiply)(int64_t operand0, int64_t operand1); |
| 609 EXPECT_EQ(6, EXECUTE_TEST_CODE_INT64_LL(LongMultiply, test->entry(), -3, -2)); |
| 610 } |
| 611 |
| 612 |
| 613 ASSEMBLER_TEST_GENERATE(Clz, assembler) { |
| 614 Label error; |
| 615 |
| 616 __ mov(R0, ShifterOperand(0)); |
| 617 __ clz(R1, R0); |
| 618 __ cmp(R1, ShifterOperand(32)); |
| 619 __ b(&error, NE); |
| 620 __ mov(R2, ShifterOperand(42)); |
| 621 __ clz(R2, R2); |
| 622 __ cmp(R2, ShifterOperand(26)); |
| 623 __ b(&error, NE); |
| 624 __ mvn(R0, ShifterOperand(0)); |
| 625 __ clz(R1, R0); |
| 626 __ cmp(R1, ShifterOperand(0)); |
| 627 __ b(&error, NE); |
| 628 __ Lsr(R0, R0, 3); |
| 629 __ clz(R1, R0); |
| 630 __ cmp(R1, ShifterOperand(3)); |
| 631 __ b(&error, NE); |
| 632 __ mov(R0, ShifterOperand(0)); |
| 633 __ mov(PC, ShifterOperand(LR)); |
| 634 __ Bind(&error); |
| 635 __ mov(R0, ShifterOperand(1)); |
| 636 __ mov(PC, ShifterOperand(LR)); |
| 637 } |
| 638 |
| 639 |
| 640 ASSEMBLER_TEST_RUN(Clz, test) { |
| 641 EXPECT(test != NULL); |
| 642 typedef int (*Clz)(); |
| 643 EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(Clz, test->entry())); |
| 644 } |
| 645 |
| 646 |
| 647 ASSEMBLER_TEST_GENERATE(Tst, assembler) { |
| 648 Label skip; |
| 649 |
| 650 __ mov(R0, ShifterOperand(42)); |
| 651 __ mov(R1, ShifterOperand(40)); |
| 652 __ tst(R1, ShifterOperand(0)); |
| 653 __ b(&skip, NE); |
| 654 __ mov(R0, ShifterOperand(0)); |
| 655 __ Bind(&skip); |
| 656 __ mov(PC, ShifterOperand(LR)); |
| 657 } |
| 658 |
| 659 |
| 660 ASSEMBLER_TEST_RUN(Tst, test) { |
| 661 EXPECT(test != NULL); |
| 662 typedef int (*Tst)(); |
| 663 EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(Tst, test->entry())); |
| 664 } |
| 665 |
| 666 |
| 667 ASSEMBLER_TEST_GENERATE(Lsl, assembler) { |
| 668 Label skip; |
| 669 |
| 670 __ mov(R0, ShifterOperand(1)); |
| 671 __ mov(R0, ShifterOperand(R0, LSL, 1)); |
| 672 __ mov(R1, ShifterOperand(1)); |
| 673 __ mov(R0, ShifterOperand(R0, LSL, R1)); |
| 674 __ mov(PC, ShifterOperand(LR)); |
| 675 } |
| 676 |
| 677 |
| 678 ASSEMBLER_TEST_RUN(Lsl, test) { |
| 679 EXPECT(test != NULL); |
| 680 typedef int (*Tst)(); |
| 681 EXPECT_EQ(4, EXECUTE_TEST_CODE_INT32(Tst, test->entry())); |
| 682 } |
| 683 |
| 684 |
| 685 ASSEMBLER_TEST_GENERATE(Lsr, assembler) { |
| 686 Label skip; |
| 687 |
| 688 __ mov(R0, ShifterOperand(4)); |
| 689 __ mov(R0, ShifterOperand(R0, LSR, 1)); |
| 690 __ mov(R1, ShifterOperand(1)); |
| 691 __ mov(R0, ShifterOperand(R0, LSR, R1)); |
| 692 __ mov(PC, ShifterOperand(LR)); |
| 693 } |
| 694 |
| 695 |
| 696 ASSEMBLER_TEST_RUN(Lsr, test) { |
| 697 EXPECT(test != NULL); |
| 698 typedef int (*Tst)(); |
| 699 EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(Tst, test->entry())); |
| 700 } |
| 701 |
| 702 |
| 703 ASSEMBLER_TEST_GENERATE(Lsr1, assembler) { |
| 704 Label skip; |
| 705 |
| 706 __ mov(R0, ShifterOperand(1)); |
| 707 __ Lsl(R0, R0, 31); |
| 708 __ Lsr(R0, R0, 31); |
| 709 __ mov(PC, ShifterOperand(LR)); |
| 710 } |
| 711 |
| 712 |
| 713 ASSEMBLER_TEST_RUN(Lsr1, test) { |
| 714 EXPECT(test != NULL); |
| 715 typedef int (*Tst)(); |
| 716 EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(Tst, test->entry())); |
| 717 } |
| 718 |
| 719 |
| 720 ASSEMBLER_TEST_GENERATE(Asr1, assembler) { |
| 721 Label skip; |
| 722 |
| 723 __ mov(R0, ShifterOperand(1)); |
| 724 __ Lsl(R0, R0, 31); |
| 725 __ Asr(R0, R0, 31); |
| 726 __ mov(PC, ShifterOperand(LR)); |
| 727 } |
| 728 |
| 729 |
| 730 ASSEMBLER_TEST_RUN(Asr1, test) { |
| 731 EXPECT(test != NULL); |
| 732 typedef int (*Tst)(); |
| 733 EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT32(Tst, test->entry())); |
| 734 } |
| 735 |
| 736 |
| 737 ASSEMBLER_TEST_GENERATE(Rsb, assembler) { |
| 738 __ mov(R3, ShifterOperand(10)); |
| 739 __ rsb(R0, R3, ShifterOperand(42)); |
| 740 __ mov(PC, ShifterOperand(LR)); |
| 741 } |
| 742 |
| 743 |
| 744 ASSEMBLER_TEST_RUN(Rsb, test) { |
| 745 EXPECT(test != NULL); |
| 746 typedef int (*Rsb)(); |
| 747 EXPECT_EQ(32, EXECUTE_TEST_CODE_INT32(Rsb, test->entry())); |
| 748 } |
| 749 |
| 750 |
| 751 ASSEMBLER_TEST_GENERATE(Ldrh, assembler) { |
| 752 Label Test1; |
| 753 Label Test2; |
| 754 Label Done; |
| 755 |
| 756 __ mov(R1, ShifterOperand(0x11)); |
| 757 __ mov(R2, ShifterOperand(SP)); |
| 758 __ str(R1, Address(SP, (-kWordSize * 30), Address::PreIndex)); |
| 759 __ ldrh(R0, Address(R2, (-kWordSize * 30))); |
| 760 __ cmp(R0, ShifterOperand(0x11)); |
| 761 __ b(&Test1, EQ); |
| 762 __ mov(R0, ShifterOperand(1)); |
| 763 __ b(&Done); |
| 764 __ Bind(&Test1); |
| 765 |
| 766 __ mov(R0, ShifterOperand(0)); |
| 767 __ strh(R0, Address(R2, (-kWordSize * 30))); |
| 768 __ ldrh(R1, Address(R2, (-kWordSize * 30))); |
| 769 __ cmp(R1, ShifterOperand(0)); |
| 770 __ b(&Test2, EQ); |
| 771 __ mov(R0, ShifterOperand(1)); |
| 772 __ b(&Done); |
| 773 __ Bind(&Test2); |
| 774 |
| 775 __ mov(R0, ShifterOperand(0)); |
| 776 __ Bind(&Done); |
| 777 __ ldr(R1, Address(SP, (kWordSize * 30), Address::PostIndex)); |
| 778 __ mov(PC, ShifterOperand(LR)); |
| 779 } |
| 780 |
| 781 |
| 782 ASSEMBLER_TEST_RUN(Ldrh, test) { |
| 783 EXPECT(test != NULL); |
| 784 typedef int (*Tst)(); |
| 785 EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(Tst, test->entry())); |
| 786 } |
| 787 |
| 788 |
| 789 ASSEMBLER_TEST_GENERATE(Ldrsb, assembler) { |
| 790 __ mov(R1, ShifterOperand(0xFF)); |
| 791 __ mov(R2, ShifterOperand(SP)); |
| 792 __ str(R1, Address(SP, (-kWordSize * 30), Address::PreIndex)); |
| 793 __ ldrsb(R0, Address(R2, (-kWordSize * 30))); |
| 794 __ ldr(R1, Address(SP, (kWordSize * 30), Address::PostIndex)); |
| 795 __ mov(PC, ShifterOperand(LR)); |
| 796 } |
| 797 |
| 798 |
| 799 ASSEMBLER_TEST_RUN(Ldrsb, test) { |
| 800 EXPECT(test != NULL); |
| 801 typedef int (*Tst)(); |
| 802 EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT32(Tst, test->entry())); |
| 803 } |
| 804 |
| 805 |
| 806 ASSEMBLER_TEST_GENERATE(Ldrb, assembler) { |
| 807 __ mov(R1, ShifterOperand(0xFF)); |
| 808 __ mov(R2, ShifterOperand(SP)); |
| 809 __ str(R1, Address(SP, (-kWordSize * 30), Address::PreIndex)); |
| 810 __ ldrb(R0, Address(R2, (-kWordSize * 30))); |
| 811 __ ldr(R1, Address(SP, (kWordSize * 30), Address::PostIndex)); |
| 812 __ mov(PC, ShifterOperand(LR)); |
| 813 } |
| 814 |
| 815 |
| 816 ASSEMBLER_TEST_RUN(Ldrb, test) { |
| 817 EXPECT(test != NULL); |
| 818 typedef int (*Tst)(); |
| 819 EXPECT_EQ(0xff, EXECUTE_TEST_CODE_INT32(Tst, test->entry())); |
| 820 } |
| 821 |
| 822 |
| 823 ASSEMBLER_TEST_GENERATE(Ldrsh, assembler) { |
| 824 __ mov(R1, ShifterOperand(0xFF)); |
| 825 __ mov(R2, ShifterOperand(SP)); |
| 826 __ str(R1, Address(SP, (-kWordSize * 30), Address::PreIndex)); |
| 827 __ ldrsh(R0, Address(R2, (-kWordSize * 30))); |
| 828 __ ldr(R1, Address(SP, (kWordSize * 30), Address::PostIndex)); |
| 829 __ mov(PC, ShifterOperand(LR)); |
| 830 } |
| 831 |
| 832 |
| 833 ASSEMBLER_TEST_RUN(Ldrsh, test) { |
| 834 EXPECT(test != NULL); |
| 835 typedef int (*Tst)(); |
| 836 EXPECT_EQ(0xff, EXECUTE_TEST_CODE_INT32(Tst, test->entry())); |
| 837 } |
| 838 |
| 839 |
| 840 ASSEMBLER_TEST_GENERATE(Ldrh1, assembler) { |
| 841 __ mov(R1, ShifterOperand(0xFF)); |
| 842 __ mov(R2, ShifterOperand(SP)); |
| 843 __ str(R1, Address(SP, (-kWordSize * 30), Address::PreIndex)); |
| 844 __ ldrh(R0, Address(R2, (-kWordSize * 30))); |
| 845 __ ldr(R1, Address(SP, (kWordSize * 30), Address::PostIndex)); |
| 846 __ mov(PC, ShifterOperand(LR)); |
| 847 } |
| 848 |
| 849 |
| 850 ASSEMBLER_TEST_RUN(Ldrh1, test) { |
| 851 EXPECT(test != NULL); |
| 852 typedef int (*Tst)(); |
| 853 EXPECT_EQ(0xff, EXECUTE_TEST_CODE_INT32(Tst, test->entry())); |
| 854 } |
| 855 |
| 856 |
| 857 ASSEMBLER_TEST_GENERATE(Ldrd, assembler) { |
| 858 __ Mov(IP, SP); |
| 859 __ strd(R2, Address(SP, (-kWordSize * 30), Address::PreIndex)); |
| 860 __ strd(R0, Address(IP, (-kWordSize * 28))); |
| 861 __ ldrd(R2, Address(IP, (-kWordSize * 28))); |
| 862 __ ldrd(R0, Address(SP, (kWordSize * 30), Address::PostIndex)); |
| 863 __ sub(R0, R0, ShifterOperand(R2)); |
| 864 __ add(R1, R1, ShifterOperand(R3)); |
| 865 __ mov(PC, ShifterOperand(LR)); |
| 866 } |
| 867 |
| 868 |
| 869 ASSEMBLER_TEST_RUN(Ldrd, test) { |
| 870 EXPECT(test != NULL); |
| 871 typedef int64_t (*Tst)(int64_t r0r1, int64_t r2r3); |
| 872 EXPECT_EQ(0x0000444400002222LL, EXECUTE_TEST_CODE_INT64_LL( |
| 873 Tst, test->entry(), 0x0000111100000000LL, 0x0000333300002222LL)); |
| 874 } |
| 875 |
| 876 |
| 877 ASSEMBLER_TEST_GENERATE(Ldm_stm_da, assembler) { |
| 878 __ mov(R0, ShifterOperand(1)); |
| 879 __ mov(R1, ShifterOperand(7)); |
| 880 __ mov(R2, ShifterOperand(11)); |
| 881 __ mov(R3, ShifterOperand(31)); |
| 882 __ Push(R5); // We use R5 as accumulator. |
| 883 __ Push(R5); |
| 884 __ Push(R5); |
| 885 __ Push(R5); |
| 886 __ Push(R5); |
| 887 __ Push(R0); // Make room, so we can decrement after. |
| 888 __ stm(DA_W, SP, (1 << R0 | 1 << R1 | 1 << R2 | 1 << R3)); |
| 889 __ str(R2, Address(SP)); // Should be a free slot. |
| 890 __ ldr(R5, Address(SP, 1 * kWordSize)); // R0. R5 = +1. |
| 891 __ ldr(IP, Address(SP, 2 * kWordSize)); // R1. |
| 892 __ sub(R5, R5, ShifterOperand(IP)); // -R1. R5 = -6. |
| 893 __ ldr(IP, Address(SP, 3 * kWordSize)); // R2. |
| 894 __ add(R5, R5, ShifterOperand(IP)); // +R2. R5 = +5. |
| 895 __ ldr(IP, Address(SP, 4 * kWordSize)); // R3. |
| 896 __ sub(R5, R5, ShifterOperand(IP)); // -R3. R5 = -26. |
| 897 __ ldm(IB_W, SP, (1 << R0 | 1 << R1 | 1 << R2 | 1 << R3)); |
| 898 // Same operations again. But this time from the restore registers. |
| 899 __ add(R5, R5, ShifterOperand(R0)); |
| 900 __ sub(R5, R5, ShifterOperand(R1)); |
| 901 __ add(R5, R5, ShifterOperand(R2)); |
| 902 __ sub(R0, R5, ShifterOperand(R3)); // R0 = result = -52. |
| 903 __ Pop(R1); // Remove storage slot. |
| 904 __ Pop(R5); // Restore R5. |
| 905 __ Pop(R5); // Restore R5. |
| 906 __ Pop(R5); // Restore R5. |
| 907 __ Pop(R5); // Restore R5. |
| 908 __ Pop(R5); // Restore R5. |
| 909 __ mov(PC, ShifterOperand(LR)); |
| 910 } |
| 911 |
| 912 |
| 913 ASSEMBLER_TEST_RUN(Ldm_stm_da, test) { |
| 914 EXPECT(test != NULL); |
| 915 typedef int (*Tst)(); |
| 916 EXPECT_EQ(-52, EXECUTE_TEST_CODE_INT32(Tst, test->entry())); |
| 917 } |
| 918 |
| 919 |
| 29 } // namespace dart | 920 } // namespace dart |
| 30 | 921 |
| 31 #endif // defined TARGET_ARCH_ARM | 922 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |