OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdarg.h> | 5 #include <stdarg.h> |
6 #include <stdlib.h> | 6 #include <stdlib.h> |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "v8.h" | 9 #include "v8.h" |
10 | 10 |
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 char* cache_valid_byte = cache_page->ValidityByte(offset); | 692 char* cache_valid_byte = cache_page->ValidityByte(offset); |
693 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); | 693 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); |
694 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); | 694 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); |
695 if (cache_hit) { | 695 if (cache_hit) { |
696 // Check that the data in memory matches the contents of the I-cache. | 696 // Check that the data in memory matches the contents of the I-cache. |
697 CHECK_EQ(0, | 697 CHECK_EQ(0, |
698 memcmp(reinterpret_cast<void*>(instr), | 698 memcmp(reinterpret_cast<void*>(instr), |
699 cache_page->CachedData(offset), Instruction::kInstrSize)); | 699 cache_page->CachedData(offset), Instruction::kInstrSize)); |
700 } else { | 700 } else { |
701 // Cache miss. Load memory into the cache. | 701 // Cache miss. Load memory into the cache. |
702 MemCopy(cached_line, line, CachePage::kLineLength); | 702 memcpy(cached_line, line, CachePage::kLineLength); |
703 *cache_valid_byte = CachePage::LINE_VALID; | 703 *cache_valid_byte = CachePage::LINE_VALID; |
704 } | 704 } |
705 } | 705 } |
706 | 706 |
707 | 707 |
708 void Simulator::Initialize(Isolate* isolate) { | 708 void Simulator::Initialize(Isolate* isolate) { |
709 if (isolate->simulator_initialized()) return; | 709 if (isolate->simulator_initialized()) return; |
710 isolate->set_simulator_initialized(true); | 710 isolate->set_simulator_initialized(true); |
711 ::v8::internal::ExternalReference::set_redirector(isolate, | 711 ::v8::internal::ExternalReference::set_redirector(isolate, |
712 &RedirectExternalReference); | 712 &RedirectExternalReference); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
887 } | 887 } |
888 | 888 |
889 | 889 |
890 double Simulator::get_double_from_register_pair(int reg) { | 890 double Simulator::get_double_from_register_pair(int reg) { |
891 ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0)); | 891 ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0)); |
892 | 892 |
893 double dm_val = 0.0; | 893 double dm_val = 0.0; |
894 // Read the bits from the unsigned integer register_[] array | 894 // Read the bits from the unsigned integer register_[] array |
895 // into the double precision floating point value and return it. | 895 // into the double precision floating point value and return it. |
896 char buffer[2 * sizeof(vfp_registers_[0])]; | 896 char buffer[2 * sizeof(vfp_registers_[0])]; |
897 MemCopy(buffer, ®isters_[reg], 2 * sizeof(registers_[0])); | 897 memcpy(buffer, ®isters_[reg], 2 * sizeof(registers_[0])); |
898 MemCopy(&dm_val, buffer, 2 * sizeof(registers_[0])); | 898 memcpy(&dm_val, buffer, 2 * sizeof(registers_[0])); |
899 return(dm_val); | 899 return(dm_val); |
900 } | 900 } |
901 | 901 |
902 | 902 |
903 void Simulator::set_register_pair_from_double(int reg, double* value) { | 903 void Simulator::set_register_pair_from_double(int reg, double* value) { |
904 ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0)); | 904 ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0)); |
905 memcpy(registers_ + reg, value, sizeof(*value)); | 905 memcpy(registers_ + reg, value, sizeof(*value)); |
906 } | 906 } |
907 | 907 |
908 | 908 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
992 } | 992 } |
993 | 993 |
994 | 994 |
995 template<class InputType, int register_size> | 995 template<class InputType, int register_size> |
996 void Simulator::SetVFPRegister(int reg_index, const InputType& value) { | 996 void Simulator::SetVFPRegister(int reg_index, const InputType& value) { |
997 ASSERT(reg_index >= 0); | 997 ASSERT(reg_index >= 0); |
998 if (register_size == 1) ASSERT(reg_index < num_s_registers); | 998 if (register_size == 1) ASSERT(reg_index < num_s_registers); |
999 if (register_size == 2) ASSERT(reg_index < DwVfpRegister::NumRegisters()); | 999 if (register_size == 2) ASSERT(reg_index < DwVfpRegister::NumRegisters()); |
1000 | 1000 |
1001 char buffer[register_size * sizeof(vfp_registers_[0])]; | 1001 char buffer[register_size * sizeof(vfp_registers_[0])]; |
1002 MemCopy(buffer, &value, register_size * sizeof(vfp_registers_[0])); | 1002 memcpy(buffer, &value, register_size * sizeof(vfp_registers_[0])); |
1003 MemCopy(&vfp_registers_[reg_index * register_size], buffer, | 1003 memcpy(&vfp_registers_[reg_index * register_size], buffer, |
1004 register_size * sizeof(vfp_registers_[0])); | 1004 register_size * sizeof(vfp_registers_[0])); |
1005 } | 1005 } |
1006 | 1006 |
1007 | 1007 |
1008 template<class ReturnType, int register_size> | 1008 template<class ReturnType, int register_size> |
1009 ReturnType Simulator::GetFromVFPRegister(int reg_index) { | 1009 ReturnType Simulator::GetFromVFPRegister(int reg_index) { |
1010 ASSERT(reg_index >= 0); | 1010 ASSERT(reg_index >= 0); |
1011 if (register_size == 1) ASSERT(reg_index < num_s_registers); | 1011 if (register_size == 1) ASSERT(reg_index < num_s_registers); |
1012 if (register_size == 2) ASSERT(reg_index < DwVfpRegister::NumRegisters()); | 1012 if (register_size == 2) ASSERT(reg_index < DwVfpRegister::NumRegisters()); |
1013 | 1013 |
1014 ReturnType value = 0; | 1014 ReturnType value = 0; |
1015 char buffer[register_size * sizeof(vfp_registers_[0])]; | 1015 char buffer[register_size * sizeof(vfp_registers_[0])]; |
1016 MemCopy(buffer, &vfp_registers_[register_size * reg_index], | 1016 memcpy(buffer, &vfp_registers_[register_size * reg_index], |
1017 register_size * sizeof(vfp_registers_[0])); | 1017 register_size * sizeof(vfp_registers_[0])); |
1018 MemCopy(&value, buffer, register_size * sizeof(vfp_registers_[0])); | 1018 memcpy(&value, buffer, register_size * sizeof(vfp_registers_[0])); |
1019 return value; | 1019 return value; |
1020 } | 1020 } |
1021 | 1021 |
1022 | 1022 |
1023 // Runtime FP routines take: | 1023 // Runtime FP routines take: |
1024 // - two double arguments | 1024 // - two double arguments |
1025 // - one double argument and zero or one integer arguments. | 1025 // - one double argument and zero or one integer arguments. |
1026 // All are consructed here from r0-r3 or d0, d1 and r0. | 1026 // All are consructed here from r0-r3 or d0, d1 and r0. |
1027 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) { | 1027 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) { |
1028 if (use_eabi_hardfloat()) { | 1028 if (use_eabi_hardfloat()) { |
1029 *x = get_double_from_d_register(0); | 1029 *x = get_double_from_d_register(0); |
1030 *y = get_double_from_d_register(1); | 1030 *y = get_double_from_d_register(1); |
1031 *z = get_register(0); | 1031 *z = get_register(0); |
1032 } else { | 1032 } else { |
1033 // Registers 0 and 1 -> x. | 1033 // Registers 0 and 1 -> x. |
1034 *x = get_double_from_register_pair(0); | 1034 *x = get_double_from_register_pair(0); |
1035 // Register 2 and 3 -> y. | 1035 // Register 2 and 3 -> y. |
1036 *y = get_double_from_register_pair(2); | 1036 *y = get_double_from_register_pair(2); |
1037 // Register 2 -> z | 1037 // Register 2 -> z |
1038 *z = get_register(2); | 1038 *z = get_register(2); |
1039 } | 1039 } |
1040 } | 1040 } |
1041 | 1041 |
1042 | 1042 |
1043 // The return value is either in r0/r1 or d0. | 1043 // The return value is either in r0/r1 or d0. |
1044 void Simulator::SetFpResult(const double& result) { | 1044 void Simulator::SetFpResult(const double& result) { |
1045 if (use_eabi_hardfloat()) { | 1045 if (use_eabi_hardfloat()) { |
1046 char buffer[2 * sizeof(vfp_registers_[0])]; | 1046 char buffer[2 * sizeof(vfp_registers_[0])]; |
1047 MemCopy(buffer, &result, sizeof(buffer)); | 1047 memcpy(buffer, &result, sizeof(buffer)); |
1048 // Copy result to d0. | 1048 // Copy result to d0. |
1049 MemCopy(vfp_registers_, buffer, sizeof(buffer)); | 1049 memcpy(vfp_registers_, buffer, sizeof(buffer)); |
1050 } else { | 1050 } else { |
1051 char buffer[2 * sizeof(registers_[0])]; | 1051 char buffer[2 * sizeof(registers_[0])]; |
1052 MemCopy(buffer, &result, sizeof(buffer)); | 1052 memcpy(buffer, &result, sizeof(buffer)); |
1053 // Copy result to r0 and r1. | 1053 // Copy result to r0 and r1. |
1054 MemCopy(registers_, buffer, sizeof(buffer)); | 1054 memcpy(registers_, buffer, sizeof(buffer)); |
1055 } | 1055 } |
1056 } | 1056 } |
1057 | 1057 |
1058 | 1058 |
1059 void Simulator::TrashCallerSaveRegisters() { | 1059 void Simulator::TrashCallerSaveRegisters() { |
1060 // We don't trash the registers with the return value. | 1060 // We don't trash the registers with the return value. |
1061 registers_[2] = 0x50Bad4U; | 1061 registers_[2] = 0x50Bad4U; |
1062 registers_[3] = 0x50Bad4U; | 1062 registers_[3] = 0x50Bad4U; |
1063 registers_[12] = 0x50Bad4U; | 1063 registers_[12] = 0x50Bad4U; |
1064 } | 1064 } |
(...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1628 get_sinteger_from_s_register(reg), instr); | 1628 get_sinteger_from_s_register(reg), instr); |
1629 } | 1629 } |
1630 address += 1; | 1630 address += 1; |
1631 } else { | 1631 } else { |
1632 if (load) { | 1632 if (load) { |
1633 int32_t data[] = { | 1633 int32_t data[] = { |
1634 ReadW(reinterpret_cast<int32_t>(address), instr), | 1634 ReadW(reinterpret_cast<int32_t>(address), instr), |
1635 ReadW(reinterpret_cast<int32_t>(address + 1), instr) | 1635 ReadW(reinterpret_cast<int32_t>(address + 1), instr) |
1636 }; | 1636 }; |
1637 double d; | 1637 double d; |
1638 MemCopy(&d, data, 8); | 1638 memcpy(&d, data, 8); |
1639 set_d_register_from_double(reg, d); | 1639 set_d_register_from_double(reg, d); |
1640 } else { | 1640 } else { |
1641 int32_t data[2]; | 1641 int32_t data[2]; |
1642 double d = get_double_from_d_register(reg); | 1642 double d = get_double_from_d_register(reg); |
1643 MemCopy(data, &d, 8); | 1643 memcpy(data, &d, 8); |
1644 WriteW(reinterpret_cast<int32_t>(address), data[0], instr); | 1644 WriteW(reinterpret_cast<int32_t>(address), data[0], instr); |
1645 WriteW(reinterpret_cast<int32_t>(address + 1), data[1], instr); | 1645 WriteW(reinterpret_cast<int32_t>(address + 1), data[1], instr); |
1646 } | 1646 } |
1647 address += 2; | 1647 address += 2; |
1648 } | 1648 } |
1649 } | 1649 } |
1650 ASSERT(reinterpret_cast<intptr_t>(address) - operand_size == end_address); | 1650 ASSERT(reinterpret_cast<intptr_t>(address) - operand_size == end_address); |
1651 if (instr->HasW()) { | 1651 if (instr->HasW()) { |
1652 set_register(instr->RnValue(), rn_val); | 1652 set_register(instr->RnValue(), rn_val); |
1653 } | 1653 } |
(...skipping 1359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3013 if ((instr->VCValue() == 0x0) && | 3013 if ((instr->VCValue() == 0x0) && |
3014 (instr->VAValue() == 0x0)) { | 3014 (instr->VAValue() == 0x0)) { |
3015 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); | 3015 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); |
3016 } else if ((instr->VLValue() == 0x0) && | 3016 } else if ((instr->VLValue() == 0x0) && |
3017 (instr->VCValue() == 0x1) && | 3017 (instr->VCValue() == 0x1) && |
3018 (instr->Bit(23) == 0x0)) { | 3018 (instr->Bit(23) == 0x0)) { |
3019 // vmov (ARM core register to scalar) | 3019 // vmov (ARM core register to scalar) |
3020 int vd = instr->Bits(19, 16) | (instr->Bit(7) << 4); | 3020 int vd = instr->Bits(19, 16) | (instr->Bit(7) << 4); |
3021 double dd_value = get_double_from_d_register(vd); | 3021 double dd_value = get_double_from_d_register(vd); |
3022 int32_t data[2]; | 3022 int32_t data[2]; |
3023 MemCopy(data, &dd_value, 8); | 3023 memcpy(data, &dd_value, 8); |
3024 data[instr->Bit(21)] = get_register(instr->RtValue()); | 3024 data[instr->Bit(21)] = get_register(instr->RtValue()); |
3025 MemCopy(&dd_value, data, 8); | 3025 memcpy(&dd_value, data, 8); |
3026 set_d_register_from_double(vd, dd_value); | 3026 set_d_register_from_double(vd, dd_value); |
3027 } else if ((instr->VLValue() == 0x1) && | 3027 } else if ((instr->VLValue() == 0x1) && |
3028 (instr->VCValue() == 0x1) && | 3028 (instr->VCValue() == 0x1) && |
3029 (instr->Bit(23) == 0x0)) { | 3029 (instr->Bit(23) == 0x0)) { |
3030 // vmov (scalar to ARM core register) | 3030 // vmov (scalar to ARM core register) |
3031 int vn = instr->Bits(19, 16) | (instr->Bit(7) << 4); | 3031 int vn = instr->Bits(19, 16) | (instr->Bit(7) << 4); |
3032 double dn_value = get_double_from_d_register(vn); | 3032 double dn_value = get_double_from_d_register(vn); |
3033 int32_t data[2]; | 3033 int32_t data[2]; |
3034 MemCopy(data, &dn_value, 8); | 3034 memcpy(data, &dn_value, 8); |
3035 set_register(instr->RtValue(), data[instr->Bit(21)]); | 3035 set_register(instr->RtValue(), data[instr->Bit(21)]); |
3036 } else if ((instr->VLValue() == 0x1) && | 3036 } else if ((instr->VLValue() == 0x1) && |
3037 (instr->VCValue() == 0x0) && | 3037 (instr->VCValue() == 0x0) && |
3038 (instr->VAValue() == 0x7) && | 3038 (instr->VAValue() == 0x7) && |
3039 (instr->Bits(19, 16) == 0x1)) { | 3039 (instr->Bits(19, 16) == 0x1)) { |
3040 // vmrs | 3040 // vmrs |
3041 uint32_t rt = instr->RtValue(); | 3041 uint32_t rt = instr->RtValue(); |
3042 if (rt == 0xF) { | 3042 if (rt == 0xF) { |
3043 Copy_FPSCR_to_APSR(); | 3043 Copy_FPSCR_to_APSR(); |
3044 } else { | 3044 } else { |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3375 // Load and store double to two GP registers | 3375 // Load and store double to two GP registers |
3376 if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) { | 3376 if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) { |
3377 UNIMPLEMENTED(); // Not used by V8. | 3377 UNIMPLEMENTED(); // Not used by V8. |
3378 } else { | 3378 } else { |
3379 int rt = instr->RtValue(); | 3379 int rt = instr->RtValue(); |
3380 int rn = instr->RnValue(); | 3380 int rn = instr->RnValue(); |
3381 int vm = instr->VFPMRegValue(kDoublePrecision); | 3381 int vm = instr->VFPMRegValue(kDoublePrecision); |
3382 if (instr->HasL()) { | 3382 if (instr->HasL()) { |
3383 int32_t data[2]; | 3383 int32_t data[2]; |
3384 double d = get_double_from_d_register(vm); | 3384 double d = get_double_from_d_register(vm); |
3385 MemCopy(data, &d, 8); | 3385 memcpy(data, &d, 8); |
3386 set_register(rt, data[0]); | 3386 set_register(rt, data[0]); |
3387 set_register(rn, data[1]); | 3387 set_register(rn, data[1]); |
3388 } else { | 3388 } else { |
3389 int32_t data[] = { get_register(rt), get_register(rn) }; | 3389 int32_t data[] = { get_register(rt), get_register(rn) }; |
3390 double d; | 3390 double d; |
3391 MemCopy(&d, data, 8); | 3391 memcpy(&d, data, 8); |
3392 set_d_register_from_double(vm, d); | 3392 set_d_register_from_double(vm, d); |
3393 } | 3393 } |
3394 } | 3394 } |
3395 break; | 3395 break; |
3396 case 0x8: | 3396 case 0x8: |
3397 case 0xA: | 3397 case 0xA: |
3398 case 0xC: | 3398 case 0xC: |
3399 case 0xE: { // Load and store double to memory. | 3399 case 0xE: { // Load and store double to memory. |
3400 int rn = instr->RnValue(); | 3400 int rn = instr->RnValue(); |
3401 int vd = instr->VFPDRegValue(kDoublePrecision); | 3401 int vd = instr->VFPDRegValue(kDoublePrecision); |
3402 int offset = instr->Immed8Value(); | 3402 int offset = instr->Immed8Value(); |
3403 if (!instr->HasU()) { | 3403 if (!instr->HasU()) { |
3404 offset = -offset; | 3404 offset = -offset; |
3405 } | 3405 } |
3406 int32_t address = get_register(rn) + 4 * offset; | 3406 int32_t address = get_register(rn) + 4 * offset; |
3407 if (instr->HasL()) { | 3407 if (instr->HasL()) { |
3408 // Load double from memory: vldr. | 3408 // Load double from memory: vldr. |
3409 int32_t data[] = { | 3409 int32_t data[] = { |
3410 ReadW(address, instr), | 3410 ReadW(address, instr), |
3411 ReadW(address + 4, instr) | 3411 ReadW(address + 4, instr) |
3412 }; | 3412 }; |
3413 double val; | 3413 double val; |
3414 MemCopy(&val, data, 8); | 3414 memcpy(&val, data, 8); |
3415 set_d_register_from_double(vd, val); | 3415 set_d_register_from_double(vd, val); |
3416 } else { | 3416 } else { |
3417 // Store double to memory: vstr. | 3417 // Store double to memory: vstr. |
3418 int32_t data[2]; | 3418 int32_t data[2]; |
3419 double val = get_double_from_d_register(vd); | 3419 double val = get_double_from_d_register(vd); |
3420 MemCopy(data, &val, 8); | 3420 memcpy(data, &val, 8); |
3421 WriteW(address, data[0], instr); | 3421 WriteW(address, data[0], instr); |
3422 WriteW(address + 4, data[1], instr); | 3422 WriteW(address + 4, data[1], instr); |
3423 } | 3423 } |
3424 break; | 3424 break; |
3425 } | 3425 } |
3426 case 0x4: | 3426 case 0x4: |
3427 case 0x5: | 3427 case 0x5: |
3428 case 0x6: | 3428 case 0x6: |
3429 case 0x7: | 3429 case 0x7: |
3430 case 0x9: | 3430 case 0x9: |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3829 uintptr_t address = *stack_slot; | 3829 uintptr_t address = *stack_slot; |
3830 set_register(sp, current_sp + sizeof(uintptr_t)); | 3830 set_register(sp, current_sp + sizeof(uintptr_t)); |
3831 return address; | 3831 return address; |
3832 } | 3832 } |
3833 | 3833 |
3834 } } // namespace v8::internal | 3834 } } // namespace v8::internal |
3835 | 3835 |
3836 #endif // USE_SIMULATOR | 3836 #endif // USE_SIMULATOR |
3837 | 3837 |
3838 #endif // V8_TARGET_ARCH_ARM | 3838 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |