OLD | NEW |
1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 | 83 |
84 Debugger::Debugger(Simulator* sim) { | 84 Debugger::Debugger(Simulator* sim) { |
85 sim_ = sim; | 85 sim_ = sim; |
86 } | 86 } |
87 | 87 |
88 | 88 |
89 Debugger::~Debugger() { | 89 Debugger::~Debugger() { |
90 } | 90 } |
91 | 91 |
92 | 92 |
| 93 |
| 94 #ifdef ARM_GENERATED_CODE_COVERAGE |
| 95 static FILE* coverage_log = NULL; |
| 96 |
| 97 |
| 98 static void InitializeCoverage() { |
| 99 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); |
| 100 if (file_name != NULL) { |
| 101 coverage_log = fopen(file_name, "aw+"); |
| 102 } |
| 103 } |
| 104 |
| 105 |
| 106 void Debugger::Stop(Instr* instr) { |
| 107 char* str = reinterpret_cast<char*>(instr->InstructionBits() & 0x0fffffff); |
| 108 if (strlen(str) > 0) { |
| 109 if (coverage_log != NULL) { |
| 110 fprintf(coverage_log, "Simulator hit %s\n", str); |
| 111 fflush(coverage_log); |
| 112 } |
| 113 instr->SetInstructionBits(0xe1a00000); // Overwrite with nop. |
| 114 } |
| 115 sim_->set_pc(sim_->get_pc() + Instr::kInstrSize); |
| 116 } |
| 117 |
| 118 #else // ndef ARM_GENERATED_CODE_COVERAGE |
| 119 |
| 120 static void InitializeCoverage() { |
| 121 } |
| 122 |
| 123 |
93 void Debugger::Stop(Instr* instr) { | 124 void Debugger::Stop(Instr* instr) { |
94 const char* str = (const char*)(instr->InstructionBits() & 0x0fffffff); | 125 const char* str = (const char*)(instr->InstructionBits() & 0x0fffffff); |
95 PrintF("Simulator hit %s\n", str); | 126 PrintF("Simulator hit %s\n", str); |
96 sim_->set_pc(sim_->get_pc() + Instr::kInstrSize); | 127 sim_->set_pc(sim_->get_pc() + Instr::kInstrSize); |
97 Debug(); | 128 Debug(); |
98 } | 129 } |
| 130 #endif |
99 | 131 |
100 | 132 |
101 static const char* reg_names[] = { "r0", "r1", "r2", "r3", | 133 static const char* reg_names[] = { "r0", "r1", "r2", "r3", |
102 "r4", "r5", "r6", "r7", | 134 "r4", "r5", "r6", "r7", |
103 "r8", "r9", "r10", "r11", | 135 "r8", "r9", "r10", "r11", |
104 "r12", "r13", "r14", "r15", | 136 "r12", "r13", "r14", "r15", |
105 "pc", "lr", "sp", "ip", | 137 "pc", "lr", "sp", "ip", |
106 "fp", "sl", ""}; | 138 "fp", "sl", ""}; |
107 | 139 |
108 static int reg_nums[] = { 0, 1, 2, 3, | 140 static int reg_nums[] = { 0, 1, 2, 3, |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 v_flag_ = false; | 400 v_flag_ = false; |
369 | 401 |
370 // The sp is initialized to point to the bottom (high address) of the | 402 // The sp is initialized to point to the bottom (high address) of the |
371 // allocated stack area. To be safe in potential stack underflows we leave | 403 // allocated stack area. To be safe in potential stack underflows we leave |
372 // some buffer below. | 404 // some buffer below. |
373 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; | 405 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; |
374 // The lr and pc are initialized to a known bad value that will cause an | 406 // The lr and pc are initialized to a known bad value that will cause an |
375 // access violation if the simulator ever tries to execute it. | 407 // access violation if the simulator ever tries to execute it. |
376 registers_[pc] = bad_lr; | 408 registers_[pc] = bad_lr; |
377 registers_[lr] = bad_lr; | 409 registers_[lr] = bad_lr; |
| 410 InitializeCoverage(); |
378 } | 411 } |
379 | 412 |
380 | 413 |
381 // Create one simulator per thread and keep it in thread local storage. | 414 // Create one simulator per thread and keep it in thread local storage. |
382 static v8::internal::Thread::LocalStorageKey simulator_key = | 415 static v8::internal::Thread::LocalStorageKey simulator_key = |
383 v8::internal::Thread::CreateThreadLocalKey(); | 416 v8::internal::Thread::CreateThreadLocalKey(); |
384 | 417 |
385 // Get the active Simulator for the current thread. | 418 // Get the active Simulator for the current thread. |
386 Simulator* Simulator::current() { | 419 Simulator* Simulator::current() { |
387 Simulator* sim = reinterpret_cast<Simulator*>( | 420 Simulator* sim = reinterpret_cast<Simulator*>( |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 registers_[pc] = value; | 453 registers_[pc] = value; |
421 } | 454 } |
422 | 455 |
423 | 456 |
424 // Raw access to the PC register without the special adjustment when reading. | 457 // Raw access to the PC register without the special adjustment when reading. |
425 int32_t Simulator::get_pc() const { | 458 int32_t Simulator::get_pc() const { |
426 return registers_[pc]; | 459 return registers_[pc]; |
427 } | 460 } |
428 | 461 |
429 | 462 |
| 463 // For use in calls that take two double values, constructed from r0, r1, r2 |
| 464 // and r3. |
| 465 void Simulator::GetFpArgs(double* x, double* y) { |
| 466 // We use a char buffer to get around the strict-aliasing rules which |
| 467 // otherwise allow the compiler to optimize away the copy. |
| 468 char buffer[2 * sizeof(registers_[0])]; |
| 469 // Registers 0 and 1 -> x. |
| 470 memcpy(buffer, registers_, sizeof(buffer)); |
| 471 memcpy(x, buffer, sizeof(buffer)); |
| 472 // Registers 2 and 3 -> y. |
| 473 memcpy(buffer, registers_ + 2, sizeof(buffer)); |
| 474 memcpy(y, buffer, sizeof(buffer)); |
| 475 } |
| 476 |
| 477 |
| 478 void Simulator::SetFpResult(const double& result) { |
| 479 char buffer[2 * sizeof(registers_[0])]; |
| 480 memcpy(buffer, &result, sizeof(buffer)); |
| 481 // result -> registers 0 and 1. |
| 482 memcpy(registers_, buffer, sizeof(buffer)); |
| 483 } |
| 484 |
| 485 |
| 486 void Simulator::TrashCallerSaveRegisters() { |
| 487 // We don't trash the registers with the return value. |
| 488 registers_[2] = 0x50Bad4U; |
| 489 registers_[3] = 0x50Bad4U; |
| 490 registers_[12] = 0x50Bad4U; |
| 491 } |
| 492 |
| 493 |
430 // The ARM cannot do unaligned reads and writes. On some ARM platforms an | 494 // The ARM cannot do unaligned reads and writes. On some ARM platforms an |
431 // interrupt is caused. On others it does a funky rotation thing. For now we | 495 // interrupt is caused. On others it does a funky rotation thing. For now we |
432 // simply disallow unaligned reads, but at some point we may want to move to | 496 // simply disallow unaligned reads, but at some point we may want to move to |
433 // emulating the rotate behaviour. Note that simulator runs have the runtime | 497 // emulating the rotate behaviour. Note that simulator runs have the runtime |
434 // system running directly on the host system and only generated code is | 498 // system running directly on the host system and only generated code is |
435 // executed in the simulator. Since the host is typically IA32 we will not | 499 // executed in the simulator. Since the host is typically IA32 we will not |
436 // get the correct ARM-like behaviour on unaligned accesses. | 500 // get the correct ARM-like behaviour on unaligned accesses. |
437 | 501 |
438 int Simulator::ReadW(int32_t addr, Instr* instr) { | 502 int Simulator::ReadW(int32_t addr, Instr* instr) { |
439 if ((addr & 3) == 0) { | 503 if ((addr & 3) == 0) { |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
855 // uses the ObjectPair which is essentially two 32-bit values stuffed into a | 919 // uses the ObjectPair which is essentially two 32-bit values stuffed into a |
856 // 64-bit value. With the code below we assume that all runtime calls return | 920 // 64-bit value. With the code below we assume that all runtime calls return |
857 // 64 bits of result. If they don't, the r1 result register contains a bogus | 921 // 64 bits of result. If they don't, the r1 result register contains a bogus |
858 // value, which is fine because it is caller-saved. | 922 // value, which is fine because it is caller-saved. |
859 typedef int64_t (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1); | 923 typedef int64_t (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1); |
860 | 924 |
861 | 925 |
862 // Software interrupt instructions are used by the simulator to call into the | 926 // Software interrupt instructions are used by the simulator to call into the |
863 // C-based V8 runtime. | 927 // C-based V8 runtime. |
864 void Simulator::SoftwareInterrupt(Instr* instr) { | 928 void Simulator::SoftwareInterrupt(Instr* instr) { |
865 switch (instr->SwiField()) { | 929 int swi = instr->SwiField(); |
| 930 switch (swi) { |
866 case call_rt_r5: { | 931 case call_rt_r5: { |
867 SimulatorRuntimeCall target = | 932 SimulatorRuntimeCall target = |
868 reinterpret_cast<SimulatorRuntimeCall>(get_register(r5)); | 933 reinterpret_cast<SimulatorRuntimeCall>(get_register(r5)); |
869 intptr_t arg0 = get_register(r0); | 934 intptr_t arg0 = get_register(r0); |
870 intptr_t arg1 = get_register(r1); | 935 intptr_t arg1 = get_register(r1); |
871 int64_t result = target(arg0, arg1); | 936 int64_t result = target(arg0, arg1); |
872 int32_t lo_res = static_cast<int32_t>(result); | 937 int32_t lo_res = static_cast<int32_t>(result); |
873 int32_t hi_res = static_cast<int32_t>(result >> 32); | 938 int32_t hi_res = static_cast<int32_t>(result >> 32); |
874 set_register(r0, lo_res); | 939 set_register(r0, lo_res); |
875 set_register(r1, hi_res); | 940 set_register(r1, hi_res); |
(...skipping 11 matching lines...) Expand all Loading... |
887 set_register(r0, lo_res); | 952 set_register(r0, lo_res); |
888 set_register(r1, hi_res); | 953 set_register(r1, hi_res); |
889 set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); | 954 set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); |
890 break; | 955 break; |
891 } | 956 } |
892 case break_point: { | 957 case break_point: { |
893 Debugger dbg(this); | 958 Debugger dbg(this); |
894 dbg.Debug(); | 959 dbg.Debug(); |
895 break; | 960 break; |
896 } | 961 } |
| 962 { |
| 963 double x, y, z; |
| 964 case simulator_fp_add: |
| 965 GetFpArgs(&x, &y); |
| 966 z = x + y; |
| 967 SetFpResult(z); |
| 968 TrashCallerSaveRegisters(); |
| 969 set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); |
| 970 break; |
| 971 case simulator_fp_sub: |
| 972 GetFpArgs(&x, &y); |
| 973 z = x - y; |
| 974 SetFpResult(z); |
| 975 TrashCallerSaveRegisters(); |
| 976 set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); |
| 977 break; |
| 978 case simulator_fp_mul: |
| 979 GetFpArgs(&x, &y); |
| 980 z = x * y; |
| 981 SetFpResult(z); |
| 982 TrashCallerSaveRegisters(); |
| 983 set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); |
| 984 break; |
| 985 } |
897 default: { | 986 default: { |
898 UNREACHABLE(); | 987 UNREACHABLE(); |
899 break; | 988 break; |
900 } | 989 } |
901 } | 990 } |
902 } | 991 } |
903 | 992 |
904 | 993 |
905 // Handle execution based on instruction types. | 994 // Handle execution based on instruction types. |
906 | 995 |
(...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1589 set_register(r10, r10_val); | 1678 set_register(r10, r10_val); |
1590 set_register(r11, r11_val); | 1679 set_register(r11, r11_val); |
1591 | 1680 |
1592 int result = get_register(r0); | 1681 int result = get_register(r0); |
1593 return reinterpret_cast<Object*>(result); | 1682 return reinterpret_cast<Object*>(result); |
1594 } | 1683 } |
1595 | 1684 |
1596 } } // namespace assembler::arm | 1685 } } // namespace assembler::arm |
1597 | 1686 |
1598 #endif // !defined(__arm__) | 1687 #endif // !defined(__arm__) |
OLD | NEW |