OLD | NEW |
(Empty) | |
| 1 // Copyright 2011 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 #include "v8.h" |
| 29 |
| 30 #include "macro-assembler.h" |
| 31 #include "factory.h" |
| 32 #include "platform.h" |
| 33 #include "serialize.h" |
| 34 #include "cctest.h" |
| 35 |
| 36 using namespace v8::internal; |
| 37 |
| 38 |
| 39 typedef int (*F0)(); |
| 40 |
| 41 |
| 42 static v8::Persistent<v8::Context> env; |
| 43 |
| 44 |
| 45 static void InitializeVM() { |
| 46 if (env.IsEmpty()) { |
| 47 env = v8::Context::New(); |
| 48 } |
| 49 } |
| 50 |
| 51 // We allow use of callee saved r8-r11 for the regression tests |
| 52 #define PROLOGUE() \ |
| 53 do { \ |
| 54 __ push(r8); \ |
| 55 __ push(r9); \ |
| 56 __ push(r10); \ |
| 57 __ push(r11); \ |
| 58 __ push(roots); \ |
| 59 ExternalReference roots_array_start = \ |
| 60 ExternalReference::roots_array_start(assm.isolate()); \ |
| 61 __ mov(roots, Operand(roots_array_start)); \ |
| 62 } while (0) |
| 63 |
| 64 #define EPILOGUE() \ |
| 65 do { \ |
| 66 __ pop(roots); \ |
| 67 __ pop(r11); \ |
| 68 __ pop(r10); \ |
| 69 __ pop(r9); \ |
| 70 __ pop(r8); \ |
| 71 } while (0) |
| 72 |
| 73 #define THE_HOLE_VALUE() (assm.isolate()->factory()->the_hole_value()) |
| 74 |
| 75 #define NAN_VALUE() (assm.isolate()->factory()->nan_value()) |
| 76 |
| 77 #define FALSE_VALUE() (assm.isolate()->factory()->false_value()) |
| 78 |
| 79 #define EMPTY_STRING() (assm.isolate()->factory()->empty_string()) |
| 80 |
| 81 #define GLOBAL_CONTEXT() (assm.isolate()->global_context()) |
| 82 |
| 83 #define GLOBAL_CONTEXT_MAP() (assm.isolate()->factory()->global_context_map()) |
| 84 |
| 85 #define HEAP_NUMBER_MAP() (assm.isolate()->factory()->heap_number_map()) |
| 86 |
| 87 #define STRING_MAP() (assm.isolate()->factory()->string_map()) |
| 88 |
| 89 #define BEGIN() \ |
| 90 /* Disable compilation of natives. */ \ |
| 91 i::FLAG_disable_native_files = true; \ |
| 92 i::FLAG_code_comments = true; \ |
| 93 \ |
| 94 InitializeVM(); \ |
| 95 v8::HandleScope scope; \ |
| 96 MacroAssembler assm(Isolate::Current(), NULL, 0); |
| 97 |
| 98 #define JIT() \ |
| 99 CodeDesc desc; \ |
| 100 assm.GetCode(&desc); \ |
| 101 Object* code = HEAP->CreateCode( \ |
| 102 desc, \ |
| 103 Code::ComputeFlags(Code::STUB), \ |
| 104 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); \ |
| 105 CHECK(code->IsCode()); |
| 106 |
| 107 #define CMT(msg) do { Comment cmnt(&assm, msg); } while (0) |
| 108 |
| 109 #define __ assm. |
| 110 |
| 111 // This macro stores in r10 the line number before branching to the error label. |
| 112 // At the error label r10 can be moved to r0 such that return code of the |
| 113 // function if not 0 indicates an error at the line of the branch. |
| 114 #define B_LINE(cond, target) do { \ |
| 115 __ mov(r10, Operand(__LINE__)); \ |
| 116 if (cond == al) { \ |
| 117 __ b(target); \ |
| 118 } else { \ |
| 119 __ b(cond, target); \ |
| 120 } \ |
| 121 } while (0); |
| 122 |
| 123 |
| 124 // Test Move(...) |
| 125 TEST(sh4_ma_0) { |
| 126 BEGIN(); |
| 127 |
| 128 Label error; |
| 129 |
| 130 PROLOGUE(); |
| 131 |
| 132 // Verify Move with Immediate |
| 133 __ Move(r0, Handle<Object>(reinterpret_cast<Object *>(0x12345678))); |
| 134 __ mov(r1, Operand(0x12345678)); |
| 135 __ cmp(r0, r1); |
| 136 B_LINE(ne, &error); |
| 137 |
| 138 |
| 139 // Verify register move |
| 140 __ mov(r0, Operand(~0x00110011)); // encodes 0xffeeffee |
| 141 __ Move(r1, r0); |
| 142 __ cmp(r0, r1); |
| 143 B_LINE(ne, &error); |
| 144 |
| 145 |
| 146 // Verify register move to same register does not emit anything |
| 147 __ mov(r0, Operand(~0x11001100)); // encodes 0xeeffeeff |
| 148 int offset = assm.pc_offset(); |
| 149 __ Move(r0, r0); |
| 150 offset = assm.pc_offset() - offset; |
| 151 __ mov(r1, Operand(offset)); |
| 152 __ cmp(r1, Operand(0)); |
| 153 B_LINE(ne, &error); |
| 154 |
| 155 |
| 156 // All ok. |
| 157 __ mov(r0, Operand(0)); |
| 158 EPILOGUE(); |
| 159 __ rts(); |
| 160 |
| 161 __ bind(&error); |
| 162 __ mov(r0, r10); |
| 163 EPILOGUE(); |
| 164 __ rts(); |
| 165 |
| 166 JIT(); |
| 167 #ifdef DEBUG |
| 168 Code::cast(code)->Print(); |
| 169 #endif |
| 170 |
| 171 int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())(); |
| 172 ::printf("f() = %d\n", res); |
| 173 CHECK_EQ(0, res); |
| 174 } |
| 175 |
| 176 |
| 177 // Test Bfc/Ubfx/Sbfx/Bfi/Usat |
| 178 TEST(sh4_ma_1) { |
| 179 BEGIN(); |
| 180 |
| 181 Label error; |
| 182 |
| 183 PROLOGUE(); |
| 184 |
| 185 CMT("Verify Bfc(0xfdeccdefu, 0, 32) == 0"); |
| 186 __ mov(r0, Operand(0xfdeccdefu)); |
| 187 __ mov(r1, r0); |
| 188 __ Bfc(r1, 0, 32); // a full clear |
| 189 __ cmp(r1, Operand(0)); |
| 190 B_LINE(ne, &error); |
| 191 CMT("Verify Bfc(0xfdeccdefu, 0, 31) == 0x80000000"); |
| 192 __ mov(r1, r0); |
| 193 __ Bfc(r1, 0, 31); |
| 194 __ cmp(r1, Operand(0x80000000u)); |
| 195 B_LINE(ne, &error); |
| 196 CMT("Verify Bfc(0xfdeccdefu, 1, 31) == 0x80000000"); |
| 197 __ mov(r1, r0); |
| 198 __ Bfc(r1, 1, 30); |
| 199 __ cmp(r1, Operand(0x80000001u)); |
| 200 B_LINE(ne, &error); |
| 201 CMT("Verify Bfc(0xfdeccdefu, 9, 16) == 0xfc0001ef"); |
| 202 __ mov(r1, r0); |
| 203 __ Bfc(r1, 9, 16); |
| 204 __ cmp(r1, Operand(0xfc0001efu)); |
| 205 B_LINE(ne, &error); |
| 206 |
| 207 CMT("Verify Ubfx(0xfdeccdefu, 0, 32) == 0xfdeccdef"); |
| 208 __ mov(r0, Operand(0xfdeccdefu)); |
| 209 __ Ubfx(r1, r0, 0, 32); // a mov actually |
| 210 __ cmp(r1, Operand(0xfdeccdefu)); |
| 211 B_LINE(ne, &error); |
| 212 CMT("Verify Ubfx(0xfdeccdef, 0, 31) == 0x7deccdef"); |
| 213 __ Ubfx(r1, r0, 0, 31); |
| 214 __ cmp(r1, Operand(0x7deccdef)); |
| 215 B_LINE(ne, &error); |
| 216 CMT("Verify Ubfx(0xfdeccdef, 1, 30) == 0x3ef666f7"); |
| 217 __ Ubfx(r1, r0, 1, 30); |
| 218 __ cmp(r1, Operand(0x3ef666f7)); |
| 219 B_LINE(ne, &error); |
| 220 CMT("Verify Ubfx(0xfdeccdef, 9, 16) == 0xf666"); |
| 221 __ Ubfx(r1, r0, 9, 16); |
| 222 __ cmp(r1, Operand(0xf666)); |
| 223 B_LINE(ne, &error); |
| 224 |
| 225 CMT("Verify Sbfx(0xfdeccdef, 0, 32) == 0xfdeccdef"); |
| 226 __ mov(r0, Operand(0xfdeccdefu)); |
| 227 __ Sbfx(r1, r0, 0, 32); // a mov actually |
| 228 __ cmp(r1, Operand(0xfdeccdefu)); |
| 229 B_LINE(ne, &error); |
| 230 CMT("Verify Sbfx(0xfdeccdef, 0, 31) == 0xfdeccdef"); |
| 231 __ Sbfx(r1, r0, 0, 31); |
| 232 __ cmp(r1, Operand(0xfdeccdefu)); |
| 233 B_LINE(ne, &error); |
| 234 CMT("Verify Sbfx(0xfdeccdef, 1, 31) == 0xfef666f7"); |
| 235 __ Sbfx(r1, r0, 1, 30); |
| 236 __ cmp(r1, Operand(0xfef666f7u)); |
| 237 B_LINE(ne, &error); |
| 238 CMT("Verify Sbfx(0xfdeccdef, 9, 16) == 0xfffff666"); |
| 239 __ Sbfx(r1, r0, 9, 16); |
| 240 __ cmp(r1, Operand(0xfffff666)); |
| 241 B_LINE(ne, &error); |
| 242 |
| 243 CMT("Verify Bfi(0xfdeccdef, 0xaaaaaaaa, 0, 0) == 0xfdeccdef"); |
| 244 __ mov(r2, Operand(0xaaaaaa)); |
| 245 __ mov(r0, Operand(0xfdeccdefu)); |
| 246 __ mov(r1, r0); |
| 247 __ Bfi(r1, r2, r4, 0, 0); // a nop |
| 248 __ cmp(r1, r0); |
| 249 B_LINE(ne, &error); |
| 250 CMT("Verify Bfi(0xfdeccdef, 0xaaaaaaaa, 0, 32) == 0xaaaaaaaa"); |
| 251 __ mov(r1, r0); |
| 252 __ Bfi(r1, r2, r4, 0, 32); // a mov actually |
| 253 __ cmp(r1, r2); |
| 254 B_LINE(ne, &error); |
| 255 CMT("Verify Bfi(0xfdeccdef, 0xaaaaaaaa, 0, 16) == 0xfdecaaaa"); |
| 256 __ mov(r1, r0); |
| 257 __ Bfi(r1, r2, r4, 0, 16); |
| 258 __ cmp(r1, Operand(0xfdecaaaau)); |
| 259 B_LINE(ne, &error); |
| 260 CMT("Verify Bfi(0xfdeccdef, 0xaaaaaaaa, 4, 28) == 0xfd5555ef"); |
| 261 __ mov(r1, r0); |
| 262 __ Bfi(r1, r2, r4, 9, 16); |
| 263 __ cmp(r1, Operand(0xfd5555efu)); |
| 264 B_LINE(ne, &error); |
| 265 |
| 266 CMT("Verify Usat(-10, 8) == 0"); |
| 267 __ mov(r0, Operand(-10)); |
| 268 __ Usat(r1, 8, r0); |
| 269 __ cmp(r1, Operand(0)); |
| 270 B_LINE(ne, &error); |
| 271 CMT("Verify Usat(256, 8) == 255"); |
| 272 __ mov(r0, Operand(256)); |
| 273 __ Usat(r0, 8, r0); |
| 274 __ cmp(r0, Operand(255)); |
| 275 B_LINE(ne, &error); |
| 276 |
| 277 // All ok. |
| 278 __ mov(r0, Operand(0)); |
| 279 EPILOGUE(); |
| 280 __ rts(); |
| 281 |
| 282 __ bind(&error); |
| 283 __ mov(r0, r10); |
| 284 EPILOGUE(); |
| 285 __ rts(); |
| 286 |
| 287 JIT(); |
| 288 #ifdef DEBUG |
| 289 Code::cast(code)->Print(); |
| 290 #endif |
| 291 |
| 292 int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())(); |
| 293 ::printf("f() = %d\n", res); |
| 294 CHECK_EQ(0, res); |
| 295 } |
| 296 |
| 297 // Test Stack Pointer changes |
| 298 TEST(sh4_ma_2) { |
| 299 BEGIN(); |
| 300 |
| 301 Label error; |
| 302 |
| 303 PROLOGUE(); |
| 304 |
| 305 __ mov(r8, sp); |
| 306 |
| 307 __ add(sp, sp, Operand(-16)); |
| 308 |
| 309 __ mov(sp, r8); |
| 310 |
| 311 __ mov(r0, Operand(0)); |
| 312 |
| 313 EPILOGUE(); |
| 314 __ rts(); |
| 315 |
| 316 JIT(); |
| 317 #ifdef DEBUG |
| 318 Code::cast(code)->Print(); |
| 319 #endif |
| 320 |
| 321 int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())(); |
| 322 ::printf("f() = %d\n", res); |
| 323 CHECK_EQ(0, res); |
| 324 } |
| 325 |
| 326 |
| 327 // Test Pop/Push |
| 328 TEST(sh4_ma_3) { |
| 329 BEGIN(); |
| 330 |
| 331 Label error; |
| 332 |
| 333 PROLOGUE(); |
| 334 |
| 335 __ mov(r8, sp); |
| 336 |
| 337 // Verify Pop and Push |
| 338 __ mov(r0, Operand(3)); |
| 339 __ mov(r1, Operand(5)); |
| 340 __ mov(r2, Operand(7)); |
| 341 __ mov(r3, Operand(11)); |
| 342 __ Push(r0, r1); |
| 343 __ mov(r0, Operand(0xdeadbeef)); |
| 344 __ mov(r1, Operand(0xdeadbeef)); |
| 345 __ Pop(r0, r1); |
| 346 __ cmp(r0, Operand(3)); |
| 347 B_LINE(ne, &error); |
| 348 __ cmp(r1, Operand(5)); |
| 349 B_LINE(ne, &error); |
| 350 |
| 351 __ Push(r0, r1, r2); |
| 352 __ mov(r0, Operand(0xdeadbeef)); |
| 353 __ mov(r1, Operand(0xdeadbeef)); |
| 354 __ mov(r2, Operand(0xdeadbeef)); |
| 355 __ pop(r2); |
| 356 __ Pop(r0, r1); |
| 357 __ cmp(r0, Operand(3)); |
| 358 B_LINE(ne, &error); |
| 359 __ cmp(r1, Operand(5)); |
| 360 B_LINE(ne, &error); |
| 361 __ cmp(r2, Operand(7)); |
| 362 B_LINE(ne, &error); |
| 363 |
| 364 __ Push(r0, r1, r2, r3); |
| 365 __ mov(r0, Operand(0xdeadbeef)); |
| 366 __ mov(r1, Operand(0xdeadbeef)); |
| 367 __ mov(r2, Operand(0xdeadbeef)); |
| 368 __ mov(r3, Operand(0xdeadbeef)); |
| 369 __ Pop(r2, r3); |
| 370 __ Pop(r0, r1); |
| 371 __ cmp(r0, Operand(3)); |
| 372 B_LINE(ne, &error); |
| 373 __ cmp(r1, Operand(5)); |
| 374 B_LINE(ne, &error); |
| 375 __ cmp(r2, Operand(7)); |
| 376 B_LINE(ne, &error); |
| 377 __ cmp(r3, Operand(11)); |
| 378 B_LINE(ne, &error); |
| 379 |
| 380 |
| 381 // All ok. |
| 382 __ mov(sp, r8); |
| 383 __ mov(r0, Operand(0)); |
| 384 EPILOGUE(); |
| 385 __ rts(); |
| 386 |
| 387 __ bind(&error); |
| 388 __ mov(sp, r8); |
| 389 __ mov(r0, r10); |
| 390 EPILOGUE(); |
| 391 __ rts(); |
| 392 |
| 393 JIT(); |
| 394 #ifdef DEBUG |
| 395 Code::cast(code)->Print(); |
| 396 #endif |
| 397 |
| 398 int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())(); |
| 399 ::printf("f() = %d\n", res); |
| 400 CHECK_EQ(0, res); |
| 401 } |
| 402 |
| 403 // Test Ldrd/Strd |
| 404 TEST(sh4_ma_4) { |
| 405 BEGIN(); |
| 406 |
| 407 Label error; |
| 408 |
| 409 PROLOGUE(); |
| 410 |
| 411 __ mov(r8, sp); |
| 412 |
| 413 // Verify Pop and Push |
| 414 __ mov(r0, Operand(3)); |
| 415 __ mov(r1, Operand(5)); |
| 416 __ mov(r2, Operand(7)); |
| 417 __ mov(r3, Operand(11)); |
| 418 __ Push(r0, r1, r2, r3); |
| 419 __ mov(r0, Operand(0xdeadbeef)); |
| 420 __ mov(r1, Operand(0xdeadbeef)); |
| 421 __ mov(r2, Operand(0xdeadbeef)); |
| 422 __ mov(r3, Operand(0xdeadbeef)); |
| 423 |
| 424 __ Ldrd(r0, r1, MemOperand(sp, 8)); |
| 425 __ cmp(r1, Operand(3)); |
| 426 B_LINE(ne, &error); |
| 427 __ cmp(r0, Operand(5)); |
| 428 B_LINE(ne, &error); |
| 429 |
| 430 __ Ldrd(r2, r3, MemOperand(sp, 0)); |
| 431 __ cmp(r2, Operand(11)); |
| 432 B_LINE(ne, &error); |
| 433 __ cmp(r3, Operand(7)); |
| 434 B_LINE(ne, &error); |
| 435 |
| 436 __ mov(r2, Operand(0xdeadbeef)); |
| 437 __ mov(r3, Operand(0xdeadbeef)); |
| 438 __ mov(r2, sp); // Test case where base is also destination |
| 439 __ Ldrd(r2, r3, MemOperand(r2, 0)); |
| 440 __ cmp(r2, Operand(11)); |
| 441 B_LINE(ne, &error); |
| 442 __ cmp(r3, Operand(7)); |
| 443 B_LINE(ne, &error); |
| 444 |
| 445 __ Strd(r0, r1, MemOperand(sp, 0)); |
| 446 __ Strd(r2, r3, MemOperand(sp, 8)); |
| 447 __ Pop(r1, r0); |
| 448 __ Pop(r3, r2); |
| 449 __ cmp(r0, Operand(5)); |
| 450 B_LINE(ne, &error); |
| 451 __ cmp(r1, Operand(3)); |
| 452 B_LINE(ne, &error); |
| 453 __ cmp(r2, Operand(11)); |
| 454 B_LINE(ne, &error); |
| 455 __ cmp(r3, Operand(7)); |
| 456 B_LINE(ne, &error); |
| 457 |
| 458 // All ok. |
| 459 __ mov(sp, r8); |
| 460 __ mov(r0, Operand(0)); |
| 461 EPILOGUE(); |
| 462 __ rts(); |
| 463 |
| 464 __ bind(&error); |
| 465 __ mov(sp, r8); |
| 466 __ mov(r0, r10); |
| 467 EPILOGUE(); |
| 468 __ rts(); |
| 469 |
| 470 JIT(); |
| 471 #ifdef DEBUG |
| 472 Code::cast(code)->Print(); |
| 473 #endif |
| 474 |
| 475 int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())(); |
| 476 ::printf("f() = %d\n", res); |
| 477 CHECK_EQ(0, res); |
| 478 } |
| 479 |
| 480 |
| 481 // Test JumpIfSmi(), JumpIfNotSmi(), LoadRoot(), StoreRoot(), CompareRoot(), |
| 482 // CheckMap(), IsObjectStringType() |
| 483 TEST(sh4_ma_5) { |
| 484 BEGIN(); |
| 485 |
| 486 Label error; |
| 487 |
| 488 PROLOGUE(); |
| 489 |
| 490 __ LoadRoot(r1, Heap::kRealStackLimitRootIndex); |
| 491 __ tst(r1, Operand(1)); // Check that it is a Smi |
| 492 B_LINE(ne, &error); |
| 493 __ cmphs(sp, r1); // Check that stack limit is lower than sp |
| 494 B_LINE(ne, &error); |
| 495 |
| 496 __ LoadRoot(r0, Heap::kRealStackLimitRootIndex); |
| 497 __ mov(r1, Operand(0xdead)); |
| 498 __ StoreRoot(r1, Heap::kRealStackLimitRootIndex); |
| 499 __ LoadRoot(r1, Heap::kRealStackLimitRootIndex); |
| 500 __ cmp(r1, Operand(0xdead)); |
| 501 B_LINE(ne, &error); |
| 502 __ StoreRoot(r0, Heap::kRealStackLimitRootIndex); |
| 503 |
| 504 __ mov(r0, Operand(THE_HOLE_VALUE())); |
| 505 __ LoadRoot(r1, Heap::kTheHoleValueRootIndex); |
| 506 __ cmp(r0, r1); |
| 507 B_LINE(ne, &error); |
| 508 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); |
| 509 B_LINE(ne, &error); |
| 510 |
| 511 Label is_smi1, fail_is_smi1, fail_is_smi2, skip_is_smi1, skip_is_smi2; |
| 512 __ mov(r0, Operand(2)); // Smi integer 1 |
| 513 __ JumpIfSmi(r0, &is_smi1); |
| 514 B_LINE(al, &error); // should not be there |
| 515 __ bind(&is_smi1); |
| 516 |
| 517 __ mov(r0, Operand(1)); // Heap object 0 |
| 518 __ JumpIfSmi(r0, &fail_is_smi1); |
| 519 __ jmp(&skip_is_smi1); |
| 520 __ bind(&fail_is_smi1); |
| 521 B_LINE(al, &error); |
| 522 __ bind(&skip_is_smi1); |
| 523 |
| 524 __ mov(r0, Operand(3)); // Failure object 0 |
| 525 __ JumpIfSmi(r0, &fail_is_smi2); |
| 526 __ jmp(&skip_is_smi2); |
| 527 __ bind(&fail_is_smi2); |
| 528 B_LINE(al, &error); |
| 529 __ bind(&skip_is_smi2); |
| 530 |
| 531 |
| 532 Label is_not_smi1, is_not_smi2, fail_is_not_smi1, skip_is_not_smi1; |
| 533 __ mov(r0, Operand(1)); // Heap object 0 |
| 534 __ JumpIfNotSmi(r0, &is_not_smi1); |
| 535 B_LINE(al, &error); // should not be there |
| 536 __ bind(&is_not_smi1); |
| 537 |
| 538 __ mov(r0, Operand(3)); // Failure object 0 |
| 539 __ JumpIfNotSmi(r0, &is_not_smi2); |
| 540 B_LINE(al, &error); // should not be there |
| 541 __ bind(&is_not_smi2); |
| 542 |
| 543 __ mov(r0, Operand(2)); // Smi integer 1 |
| 544 __ JumpIfNotSmi(r0, &fail_is_not_smi1); |
| 545 __ jmp(&skip_is_not_smi1); |
| 546 __ bind(&fail_is_not_smi1); |
| 547 B_LINE(al, &error); |
| 548 __ bind(&skip_is_not_smi1); |
| 549 |
| 550 Label no_map1, no_map2, no_map3, no_map4, no_map5, skip_no_map1; |
| 551 __ mov(r0, Operand(2)); // Smi integer 1 |
| 552 __ CheckMap(r0, r1/*scratch*/, GLOBAL_CONTEXT_MAP(), |
| 553 &no_map1, DO_SMI_CHECK); // Check that Smi fails |
| 554 B_LINE(al, &error); // should not be there |
| 555 __ bind(&no_map1); |
| 556 |
| 557 __ mov(r0, Operand(EMPTY_STRING())); // String object |
| 558 __ CheckMap(r0, r1/*scratch*/, HEAP_NUMBER_MAP(), |
| 559 &no_map2, DO_SMI_CHECK); // Not the right map |
| 560 B_LINE(al, &error); // should not be there |
| 561 __ bind(&no_map2); |
| 562 |
| 563 __ mov(r0, Operand(EMPTY_STRING())); // String object |
| 564 // Heap object but not the right map |
| 565 __ CheckMap(r0, r1/*scratch*/, HEAP_NUMBER_MAP(), |
| 566 &no_map3, DONT_DO_SMI_CHECK); |
| 567 B_LINE(al, &error); // should not be there |
| 568 __ bind(&no_map3); |
| 569 |
| 570 __ mov(r0, Operand(EMPTY_STRING())); // String object |
| 571 // Heap object but not the right map |
| 572 __ CheckMap(r0, r1/*scratch*/, Heap::kHeapNumberMapRootIndex, |
| 573 &no_map4, DONT_DO_SMI_CHECK); |
| 574 B_LINE(al, &error); // should not be there |
| 575 __ bind(&no_map4); |
| 576 |
| 577 __ mov(r0, Operand(NAN_VALUE())); // HeapNumber object |
| 578 __ CheckMap(r0, r1/*scratch*/, HEAP_NUMBER_MAP(), |
| 579 &no_map5, DO_SMI_CHECK); // This is the right map |
| 580 __ CheckMap(r0, r1/*scratch*/, HEAP_NUMBER_MAP(), |
| 581 &no_map5, DONT_DO_SMI_CHECK); |
| 582 __ CheckMap(r0, r1/*scratch*/, Heap::kHeapNumberMapRootIndex, |
| 583 &no_map5, DO_SMI_CHECK); |
| 584 __ CheckMap(r0, r1/*scratch*/, Heap::kHeapNumberMapRootIndex, |
| 585 &no_map5, DONT_DO_SMI_CHECK); |
| 586 __ jmp(&skip_no_map1); |
| 587 __ bind(&no_map5); |
| 588 B_LINE(al, &error); // should not be there |
| 589 __ bind(&skip_no_map1); |
| 590 |
| 591 Label skip_is_string; |
| 592 __ mov(r0, Operand(EMPTY_STRING())); // String object |
| 593 Condition cond = assm.IsObjectStringType(r0, r1); |
| 594 __ b(cond, &skip_is_string); |
| 595 B_LINE(al, &error); |
| 596 __ bind(&skip_is_string); |
| 597 __ mov(r0, Operand(NAN_VALUE())); // HeapNumber object |
| 598 cond = assm.IsObjectStringType(r0, r1); |
| 599 B_LINE(cond, &error); |
| 600 |
| 601 // All ok. |
| 602 __ mov(r0, Operand(0)); |
| 603 EPILOGUE(); |
| 604 __ rts(); |
| 605 |
| 606 __ bind(&error); |
| 607 __ mov(r0, r10); |
| 608 EPILOGUE(); |
| 609 __ rts(); |
| 610 |
| 611 JIT(); |
| 612 #ifdef DEBUG |
| 613 Code::cast(code)->Print(); |
| 614 #endif |
| 615 |
| 616 int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())(); |
| 617 ::printf("f() = %d\n", res); |
| 618 CHECK_EQ(0, res); |
| 619 } |
| 620 |
| 621 |
| 622 // Test SmiTag(), SmiUntag(), TrySmiTag(), |
| 623 // GetLeastBitsFromSmi(), GetLeastBitsFromInt32() |
| 624 // JumpIfNotPowerOfTwoOrZero(), JumpIfNotPowerOfTwoOrZeroAndNeg() |
| 625 // JumpIfNotBothSmi()/JumpIfEitherSmi() |
| 626 TEST(sh4_ma_6) { |
| 627 BEGIN(); |
| 628 |
| 629 Label error; |
| 630 |
| 631 PROLOGUE(); |
| 632 |
| 633 __ mov(r0, Operand(1)); |
| 634 __ SmiTag(r0); |
| 635 __ cmp(r0, Operand(2)); |
| 636 B_LINE(ne, &error); |
| 637 __ SmiUntag(r0); |
| 638 __ cmp(r0, Operand(1)); |
| 639 B_LINE(ne, &error); |
| 640 |
| 641 __ mov(r0, Operand(0x3fffffff)); |
| 642 __ SmiTag(r1, r0); |
| 643 __ cmp(r1, Operand(0x7ffffffe)); |
| 644 B_LINE(ne, &error); |
| 645 __ SmiUntag(r0, r1); |
| 646 __ cmp(r0, Operand(0x3fffffff)); |
| 647 B_LINE(ne, &error); |
| 648 |
| 649 __ mov(r0, Operand(0xc0000000)); |
| 650 __ SmiTag(r0); |
| 651 __ cmp(r0, Operand(0x80000000)); |
| 652 B_LINE(ne, &error); |
| 653 __ SmiUntag(r1, r0); |
| 654 __ cmp(r1, Operand(0xc0000000)); |
| 655 B_LINE(ne, &error); |
| 656 |
| 657 CMT("Check GetLeastBitsFromSmi(Smi(33), 5) == 1"); |
| 658 __ mov(r0, Operand(33<<1)); |
| 659 __ mov(r2, Operand(1)); |
| 660 __ GetLeastBitsFromSmi(r1, r0, 5); |
| 661 __ cmp(r1, r2); |
| 662 B_LINE(ne, &error); |
| 663 |
| 664 CMT("Check GetLeastBitsFromInt32(34, 5) == 2"); |
| 665 __ mov(r0, Operand(34)); |
| 666 __ mov(r2, Operand(2)); |
| 667 __ GetLeastBitsFromInt32(r1, r0, 5); |
| 668 __ cmp(r1, r2); |
| 669 B_LINE(ne, &error); |
| 670 |
| 671 Label not_smi1, not_smi2, not_smi3, skip_smi1; |
| 672 __ mov(r0, Operand(0xc0000000)); |
| 673 __ TrySmiTag(r0, ¬_smi1, r1/*scratch*/); |
| 674 __ cmp(r0, Operand(0x80000000)); |
| 675 B_LINE(ne, &error); |
| 676 __ jmp(&skip_smi1); |
| 677 __ bind(¬_smi1); |
| 678 B_LINE(ne, &error); |
| 679 __ bind(&skip_smi1); |
| 680 |
| 681 __ mov(r0, Operand(0x80000000)); // not a smi |
| 682 __ TrySmiTag(r0, ¬_smi2, r1/*scratch*/); |
| 683 B_LINE(ne, &error); |
| 684 __ bind(¬_smi2); |
| 685 |
| 686 __ mov(r0, Operand(0x40000000)); // not a smi |
| 687 __ TrySmiTag(r0, ¬_smi3, r1/*scratch*/); |
| 688 B_LINE(ne, &error); |
| 689 __ bind(¬_smi3); |
| 690 |
| 691 |
| 692 Label not_power1, not_power2, not_power3, not_power4, |
| 693 skip_power1, skip_power2, skip_power3; |
| 694 __ mov(r0, Operand(0)); |
| 695 __ JumpIfNotPowerOfTwoOrZero(r0, r1, ¬_power1); |
| 696 B_LINE(al, &error); |
| 697 __ bind(¬_power1); |
| 698 |
| 699 __ mov(r0, Operand(0x80000000)); |
| 700 // r1 will contain (r0 - 1) (the power of two mask) |
| 701 __ JumpIfNotPowerOfTwoOrZero(r0, r1, ¬_power2); |
| 702 __ jmp(&skip_power2); |
| 703 __ bind(¬_power2); |
| 704 B_LINE(al, &error); |
| 705 __ bind(&skip_power2); |
| 706 __ cmp(r1, Operand(0x7fffffff)); |
| 707 B_LINE(ne, &error); |
| 708 |
| 709 __ mov(r0, Operand(1)); |
| 710 __ JumpIfNotPowerOfTwoOrZero(r0, r1, ¬_power2); |
| 711 __ jmp(&skip_power3); |
| 712 __ bind(¬_power3); |
| 713 B_LINE(al, &error); |
| 714 __ bind(&skip_power3); |
| 715 __ cmp(r1, Operand(0)); |
| 716 B_LINE(ne, &error); |
| 717 |
| 718 __ mov(r0, Operand(0x30)); |
| 719 __ JumpIfNotPowerOfTwoOrZero(r0, r1, ¬_power4); |
| 720 B_LINE(al, &error); |
| 721 __ bind(¬_power4); |
| 722 |
| 723 Label not_pow1, zero_neg1, not_pow2, zero_neg2, not_pow3, zero_neg3, |
| 724 not_pow4, zero_neg4, not_pow5, zero_neg5, not_pow6, zero_neg6, |
| 725 skip_pow5, skip_pow6, skip_pow2; |
| 726 __ mov(r0, Operand(0)); |
| 727 __ JumpIfNotPowerOfTwoOrZeroAndNeg(r0, r1, &zero_neg1, ¬_pow1); |
| 728 B_LINE(al, &error); |
| 729 __ bind(¬_pow1); |
| 730 B_LINE(al, &error); |
| 731 __ bind(&zero_neg1); |
| 732 |
| 733 __ mov(r0, Operand(0x80000000)); |
| 734 __ JumpIfNotPowerOfTwoOrZeroAndNeg(r0, r1, &zero_neg2, ¬_pow2); |
| 735 __ jmp(&skip_pow2); |
| 736 __ bind(¬_pow2); |
| 737 B_LINE(al, &error); |
| 738 __ bind(&zero_neg2); |
| 739 B_LINE(al, &error); |
| 740 __ bind(&skip_pow2); |
| 741 __ cmp(r1, Operand(0x7fffffff)); |
| 742 B_LINE(ne, &error); |
| 743 |
| 744 __ mov(r0, Operand(-1)); |
| 745 __ JumpIfNotPowerOfTwoOrZeroAndNeg(r0, r1, &zero_neg3, ¬_pow3); |
| 746 B_LINE(al, &error); |
| 747 __ bind(¬_pow3); |
| 748 B_LINE(al, &error); |
| 749 __ bind(&zero_neg3); |
| 750 |
| 751 __ mov(r0, Operand(0x30)); |
| 752 __ JumpIfNotPowerOfTwoOrZeroAndNeg(r0, r1, &zero_neg4, ¬_pow4); |
| 753 B_LINE(al, &error); |
| 754 __ bind(&zero_neg4); |
| 755 B_LINE(al, &error); |
| 756 __ bind(¬_pow4); |
| 757 |
| 758 __ mov(r0, Operand(1)); |
| 759 __ JumpIfNotPowerOfTwoOrZeroAndNeg(r0, r1, &zero_neg5, ¬_pow5); |
| 760 __ jmp(&skip_pow5); |
| 761 __ bind(¬_pow5); |
| 762 B_LINE(al, &error); |
| 763 __ bind(&zero_neg5); |
| 764 B_LINE(al, &error); |
| 765 __ bind(&skip_pow5); |
| 766 __ cmp(r1, Operand(0)); |
| 767 B_LINE(ne, &error); |
| 768 |
| 769 __ mov(r0, Operand(0x40000000)); |
| 770 __ JumpIfNotPowerOfTwoOrZeroAndNeg(r0, r1, &zero_neg6, ¬_pow6); |
| 771 __ jmp(&skip_pow6); |
| 772 __ bind(¬_pow6); |
| 773 B_LINE(al, &error); |
| 774 __ bind(&zero_neg6); |
| 775 B_LINE(al, &error); |
| 776 __ bind(&skip_pow6); |
| 777 __ cmp(r1, Operand(0x3fffffff)); |
| 778 B_LINE(ne, &error); |
| 779 |
| 780 Label not_both_smi1, skip_not_both_smi1, not_both_smi2, not_both_smi3, |
| 781 not_both_smi4; |
| 782 CMT("Check JumpIfNotBothSmi(): both Smi"); |
| 783 __ mov(r0, Operand(Smi::FromInt(1))); |
| 784 __ mov(r1, Operand(Smi::FromInt(2))); |
| 785 __ JumpIfNotBothSmi(r0, r1, ¬_both_smi1); |
| 786 __ jmp(&skip_not_both_smi1); |
| 787 __ bind(¬_both_smi1); |
| 788 B_LINE(al, &error); |
| 789 __ bind(&skip_not_both_smi1); |
| 790 |
| 791 CMT("Check JumpIfNotBothSmi(): left Smi"); |
| 792 __ mov(r0, Operand(Smi::FromInt(1))); |
| 793 __ mov(r1, Operand(0x41)); // not a smi |
| 794 __ JumpIfNotBothSmi(r0, r1, ¬_both_smi2); |
| 795 B_LINE(al, &error); |
| 796 __ bind(¬_both_smi2); |
| 797 |
| 798 CMT("Check JumpIfNotBothSmi(): right Smi"); |
| 799 __ JumpIfNotBothSmi(r1, r0, ¬_both_smi3); |
| 800 B_LINE(al, &error); |
| 801 __ bind(¬_both_smi3); |
| 802 |
| 803 CMT("Check JumpIfNotBothSmi(): none Smi"); |
| 804 __ mov(r0, Operand(0x33)); // not a smi |
| 805 __ JumpIfNotBothSmi(r1, r0, ¬_both_smi4); |
| 806 B_LINE(al, &error); |
| 807 __ bind(¬_both_smi4); |
| 808 |
| 809 |
| 810 Label either_smi1, either_smi2, either_smi3, either_smi4, |
| 811 skip_either_smi4; |
| 812 CMT("Check JumpIfEitherSmi(): both Smi"); |
| 813 __ mov(r0, Operand(Smi::FromInt(1))); |
| 814 __ mov(r1, Operand(Smi::FromInt(2))); |
| 815 __ JumpIfEitherSmi(r0, r1, &either_smi1); |
| 816 B_LINE(al, &error); |
| 817 __ bind(&either_smi1); |
| 818 |
| 819 CMT("Check JumpIfEitherSmi(): left Smi"); |
| 820 __ mov(r0, Operand(Smi::FromInt(1))); |
| 821 __ mov(r1, Operand(0x41)); // not a smi |
| 822 __ JumpIfEitherSmi(r0, r1, &either_smi2); |
| 823 B_LINE(al, &error); |
| 824 __ bind(&either_smi2); |
| 825 |
| 826 CMT("Check JumpIfEitherSmi(): right Smi"); |
| 827 __ JumpIfEitherSmi(r1, r0, &either_smi3); |
| 828 B_LINE(al, &error); |
| 829 __ bind(&either_smi3); |
| 830 |
| 831 CMT("Check JumpIfEitherSmi(): none Smi"); |
| 832 __ mov(r0, Operand(0x33)); // not a smi also |
| 833 __ JumpIfEitherSmi(r1, r0, &either_smi4); |
| 834 __ jmp(&skip_either_smi4); |
| 835 __ bind(&either_smi4); |
| 836 B_LINE(al, &error); |
| 837 __ bind(&skip_either_smi4); |
| 838 |
| 839 |
| 840 // All ok. |
| 841 __ mov(r0, Operand(0)); |
| 842 EPILOGUE(); |
| 843 __ rts(); |
| 844 |
| 845 __ bind(&error); |
| 846 __ mov(r0, r10); |
| 847 EPILOGUE(); |
| 848 __ rts(); |
| 849 |
| 850 JIT(); |
| 851 #ifdef DEBUG |
| 852 Code::cast(code)->Print(); |
| 853 #endif |
| 854 |
| 855 int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())(); |
| 856 ::printf("f() = %d\n", res); |
| 857 CHECK_EQ(0, res); |
| 858 } |
| 859 |
| 860 |
| 861 // Test ConvertToInt32() |
| 862 TEST(sh4_ma_7) { |
| 863 BEGIN(); |
| 864 |
| 865 Label error; |
| 866 PROLOGUE(); |
| 867 |
| 868 Label not_int32_1, skip_int32_1, not_int32_2, not_int32_3; |
| 869 Handle<Object> num; |
| 870 CMT("Check ConvertToInt32(4.1) == 4"); |
| 871 num = assm.isolate()->factory()->NewNumber(4.1, TENURED); |
| 872 __ mov(r0, Operand(4)); |
| 873 __ mov(r1, Operand(num)); |
| 874 __ ConvertToInt32(r1, r2, r3, r4, dr0, ¬_int32_1); |
| 875 __ cmp(r2, r0); |
| 876 B_LINE(ne, &error); |
| 877 __ jmp(&skip_int32_1); |
| 878 __ bind(¬_int32_1); |
| 879 B_LINE(al, &error); |
| 880 __ bind(&skip_int32_1); |
| 881 |
| 882 CMT("Check ConvertToInt32(nan) == not int32"); |
| 883 __ mov(r1, Operand(NAN_VALUE())); |
| 884 __ ConvertToInt32(r1, r2, r3, r4, dr0, ¬_int32_2); |
| 885 B_LINE(al, &error); |
| 886 __ bind(¬_int32_2); |
| 887 |
| 888 CMT("Check ConvertToInt32(0X80000000) == not int32"); |
| 889 num = assm.isolate()->factory()->NewNumber(static_cast<double>(0x80000000U), |
| 890 TENURED); |
| 891 __ mov(r1, Operand(num)); |
| 892 __ ConvertToInt32(r1, r2, r3, r4, dr0, ¬_int32_3); |
| 893 B_LINE(al, &error); |
| 894 __ bind(¬_int32_3); |
| 895 |
| 896 // All ok. |
| 897 __ mov(r0, Operand(0)); |
| 898 EPILOGUE(); |
| 899 __ rts(); |
| 900 |
| 901 __ bind(&error); |
| 902 __ mov(r0, r10); |
| 903 EPILOGUE(); |
| 904 __ rts(); |
| 905 |
| 906 JIT(); |
| 907 #ifdef DEBUG |
| 908 Code::cast(code)->Print(); |
| 909 #endif |
| 910 |
| 911 int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())(); |
| 912 ::printf("f() = %d\n", res); |
| 913 CHECK_EQ(0, res); |
| 914 } |
| 915 |
| 916 // Test CountLeadingZeros |
| 917 TEST(sh4_ma_8) { |
| 918 BEGIN(); |
| 919 |
| 920 Label error; |
| 921 |
| 922 PROLOGUE(); |
| 923 |
| 924 __ mov(r0, Operand(0)); |
| 925 __ mov(r1, Operand(0)); |
| 926 __ CountLeadingZeros(r0, r1, r3); |
| 927 __ cmpeq(r0, Operand(32)); |
| 928 B_LINE(ne, &error); |
| 929 |
| 930 __ mov(r0, Operand(0)); |
| 931 __ mov(r1, Operand(1)); |
| 932 __ CountLeadingZeros(r0, r1, r3); |
| 933 __ cmpeq(r0, Operand(31)); |
| 934 B_LINE(ne, &error); |
| 935 |
| 936 // Test same register for input and output |
| 937 __ mov(r0, Operand(3)); |
| 938 __ CountLeadingZeros(r0, r0, r3); |
| 939 __ cmpeq(r0, Operand(30)); |
| 940 B_LINE(ne, &error); |
| 941 |
| 942 // Test same register for input and scratch |
| 943 __ mov(r0, Operand(0)); |
| 944 __ mov(r1, Operand(5)); |
| 945 __ CountLeadingZeros(r0, r1, r1); |
| 946 __ cmpeq(r0, Operand(29)); |
| 947 B_LINE(ne, &error); |
| 948 |
| 949 __ mov(r0, Operand(0)); |
| 950 __ mov(r1, Operand(13)); |
| 951 __ CountLeadingZeros(r0, r1, r3); |
| 952 __ cmpeq(r0, Operand(28)); |
| 953 B_LINE(ne, &error); |
| 954 |
| 955 __ mov(r0, Operand(0)); |
| 956 __ mov(r1, Operand(24)); |
| 957 __ CountLeadingZeros(r0, r1, r3); |
| 958 __ cmpeq(r0, Operand(27)); |
| 959 B_LINE(ne, &error); |
| 960 |
| 961 __ mov(r0, Operand(0)); |
| 962 __ mov(r1, Operand(41)); |
| 963 __ CountLeadingZeros(r0, r1, r3); |
| 964 __ cmpeq(r0, Operand(26)); |
| 965 B_LINE(ne, &error); |
| 966 |
| 967 __ mov(r0, Operand(0)); |
| 968 __ mov(r1, Operand(83)); |
| 969 __ CountLeadingZeros(r0, r1, r3); |
| 970 __ cmpeq(r0, Operand(25)); |
| 971 B_LINE(ne, &error); |
| 972 |
| 973 __ mov(r0, Operand(0)); |
| 974 __ mov(r1, Operand(211)); |
| 975 __ CountLeadingZeros(r0, r1, r3); |
| 976 __ cmpeq(r0, Operand(24)); |
| 977 B_LINE(ne, &error); |
| 978 |
| 979 __ mov(r0, Operand(0)); |
| 980 __ mov(r1, Operand(467)); |
| 981 __ CountLeadingZeros(r0, r1, r3); |
| 982 __ cmpeq(r0, Operand(23)); |
| 983 B_LINE(ne, &error); |
| 984 |
| 985 __ mov(r0, Operand(0)); |
| 986 __ mov(r1, Operand(726)); |
| 987 __ CountLeadingZeros(r0, r1, r3); |
| 988 __ cmpeq(r0, Operand(22)); |
| 989 B_LINE(ne, &error); |
| 990 |
| 991 __ mov(r0, Operand(0)); |
| 992 __ mov(r1, Operand(1782)); |
| 993 __ CountLeadingZeros(r0, r1, r3); |
| 994 __ cmpeq(r0, Operand(21)); |
| 995 B_LINE(ne, &error); |
| 996 |
| 997 __ mov(r0, Operand(0)); |
| 998 __ mov(r1, Operand(3824)); |
| 999 __ CountLeadingZeros(r0, r1, r3); |
| 1000 __ cmpeq(r0, Operand(20)); |
| 1001 B_LINE(ne, &error); |
| 1002 |
| 1003 __ mov(r0, Operand(0)); |
| 1004 __ mov(r1, Operand(4336)); |
| 1005 __ CountLeadingZeros(r0, r1, r3); |
| 1006 __ cmpeq(r0, Operand(19)); |
| 1007 B_LINE(ne, &error); |
| 1008 |
| 1009 __ mov(r0, Operand(0)); |
| 1010 __ mov(r1, Operand(8388607)); |
| 1011 __ CountLeadingZeros(r0, r1, r3); |
| 1012 __ cmpeq(r0, Operand(9)); |
| 1013 B_LINE(ne, &error); |
| 1014 |
| 1015 __ mov(r0, Operand(0)); |
| 1016 __ mov(r1, Operand(1082130431)); |
| 1017 __ CountLeadingZeros(r0, r1, r3); |
| 1018 __ cmpeq(r0, Operand(1)); |
| 1019 B_LINE(ne, &error); |
| 1020 |
| 1021 __ mov(r0, Operand(0)); |
| 1022 __ mov(r1, Operand(3229614079u)); |
| 1023 __ CountLeadingZeros(r0, r1, r3); |
| 1024 __ cmpeq(r0, Operand(0)); |
| 1025 B_LINE(ne, &error); |
| 1026 |
| 1027 |
| 1028 |
| 1029 EPILOGUE(); |
| 1030 __ mov(r0, Operand(0)); |
| 1031 __ rts(); |
| 1032 |
| 1033 __ bind(&error); |
| 1034 __ mov(r0, r10); |
| 1035 EPILOGUE(); |
| 1036 __ rts(); |
| 1037 |
| 1038 JIT(); |
| 1039 #ifdef DEBUG |
| 1040 Code::cast(code)->Print(); |
| 1041 #endif |
| 1042 |
| 1043 int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())(); |
| 1044 ::printf("f() = %d\n", res); |
| 1045 CHECK_EQ(0, res); |
| 1046 } |
| 1047 |
| 1048 // Test CopyBytes |
| 1049 TEST(sh4_ma_9) { |
| 1050 BEGIN(); |
| 1051 |
| 1052 Label error; |
| 1053 |
| 1054 PROLOGUE(); |
| 1055 |
| 1056 // Push garbage values on the stack |
| 1057 __ push(Operand(0xdeadbeef)); |
| 1058 __ push(Operand(0xdeadbeef)); |
| 1059 __ push(Operand(0xdeadbeef)); |
| 1060 __ push(Operand(0xdeadbeef)); |
| 1061 __ push(Operand(0xdeadbeef)); |
| 1062 __ push(Operand(0xdeadbeef)); |
| 1063 __ push(Operand(0xdeadbeef)); |
| 1064 __ push(Operand(0xdeadbeef)); |
| 1065 __ push(Operand(0xdeadbeef)); |
| 1066 __ push(Operand(0xdeadbeef)); |
| 1067 __ mov(r0, sp); |
| 1068 |
| 1069 // Push nice values that will be copied |
| 1070 __ push(Operand(0xf0000000)); |
| 1071 __ push(Operand(0x0f000000)); |
| 1072 __ push(Operand(0x00f00000)); |
| 1073 __ push(Operand(0x000f0000)); |
| 1074 __ push(Operand(0x00000f00)); |
| 1075 __ push(Operand(0x000000f0)); |
| 1076 __ push(Operand(0x0000000f)); |
| 1077 __ push(Operand(0x13453abb)); |
| 1078 __ push(Operand(0xabcdef01)); |
| 1079 __ push(Operand(0x789abcde)); |
| 1080 __ mov(r1, sp); |
| 1081 |
| 1082 __ mov(r2, Operand(40)); |
| 1083 __ CopyBytes(r1, r0, r2, r3); |
| 1084 |
| 1085 // Check that the src is untouched |
| 1086 #define POP_AND_CHECK(addr, val) \ |
| 1087 __ pop(r0); \ |
| 1088 __ cmpeq(r0, Operand(addr)); \ |
| 1089 __ mov(r1, Operand(val)); \ |
| 1090 B_LINE(ne, &error); |
| 1091 |
| 1092 POP_AND_CHECK(0x789abcde, 19 * 4); |
| 1093 POP_AND_CHECK(0xabcdef01, 18 * 4); |
| 1094 POP_AND_CHECK(0x13453abb, 17 * 4); |
| 1095 POP_AND_CHECK(0x0000000f, 16 * 4); |
| 1096 POP_AND_CHECK(0x000000f0, 15 * 4); |
| 1097 POP_AND_CHECK(0x00000f00, 14 * 4); |
| 1098 POP_AND_CHECK(0x000f0000, 13 * 4); |
| 1099 POP_AND_CHECK(0x00f00000, 12 * 4); |
| 1100 POP_AND_CHECK(0x0f000000, 11 * 4); |
| 1101 POP_AND_CHECK(0xf0000000, 10 * 4); |
| 1102 |
| 1103 // check that the dst is modified |
| 1104 POP_AND_CHECK(0x789abcde, 9 * 4); |
| 1105 POP_AND_CHECK(0xabcdef01, 8 * 4); |
| 1106 POP_AND_CHECK(0x13453abb, 7 * 4); |
| 1107 POP_AND_CHECK(0x0000000f, 6 * 4); |
| 1108 POP_AND_CHECK(0x000000f0, 5 * 4); |
| 1109 POP_AND_CHECK(0x00000f00, 4 * 4); |
| 1110 POP_AND_CHECK(0x000f0000, 3 * 4); |
| 1111 POP_AND_CHECK(0x00f00000, 2 * 4); |
| 1112 POP_AND_CHECK(0x0f000000, 1 * 4); |
| 1113 POP_AND_CHECK(0xf0000000, 0 * 4); |
| 1114 |
| 1115 #undef POP_AND_CHECK |
| 1116 |
| 1117 // Test that copying 0 bytes dos not do anything |
| 1118 __ push(Operand(0xdeadbeef)); |
| 1119 __ mov(r0, sp); |
| 1120 __ push(Operand(0x00000ff0)); |
| 1121 __ mov(r1, sp); |
| 1122 |
| 1123 __ mov(r2, Operand(0)); |
| 1124 __ CopyBytes(r1, r0, r2, r3); |
| 1125 __ pop(r0); |
| 1126 __ cmpeq(r0, Operand(0x00000ff0)); |
| 1127 __ mov(r1, Operand(1 * 4)); |
| 1128 B_LINE(ne, &error); |
| 1129 |
| 1130 __ pop(r0); |
| 1131 __ cmpeq(r0, Operand(0xdeadbeef)); |
| 1132 __ mov(r1, Operand(0 * 4)); |
| 1133 B_LINE(ne, &error); |
| 1134 |
| 1135 EPILOGUE(); |
| 1136 __ mov(r0, Operand(0)); |
| 1137 __ rts(); |
| 1138 |
| 1139 __ bind(&error); |
| 1140 __ add(sp, sp, r1); |
| 1141 __ mov(r0, r10); |
| 1142 EPILOGUE(); |
| 1143 __ rts(); |
| 1144 |
| 1145 JIT(); |
| 1146 #ifdef DEBUG |
| 1147 Code::cast(code)->Print(); |
| 1148 #endif |
| 1149 |
| 1150 int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())(); |
| 1151 ::printf("f() = %d\n", res); |
| 1152 CHECK_EQ(0, res); |
| 1153 } |
OLD | NEW |