OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
714 char* cache_valid_byte = cache_page->ValidityByte(offset); | 714 char* cache_valid_byte = cache_page->ValidityByte(offset); |
715 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); | 715 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); |
716 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); | 716 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); |
717 if (cache_hit) { | 717 if (cache_hit) { |
718 // Check that the data in memory matches the contents of the I-cache. | 718 // Check that the data in memory matches the contents of the I-cache. |
719 CHECK(memcmp(reinterpret_cast<void*>(instr), | 719 CHECK(memcmp(reinterpret_cast<void*>(instr), |
720 cache_page->CachedData(offset), | 720 cache_page->CachedData(offset), |
721 Instruction::kInstrSize) == 0); | 721 Instruction::kInstrSize) == 0); |
722 } else { | 722 } else { |
723 // Cache miss. Load memory into the cache. | 723 // Cache miss. Load memory into the cache. |
724 memcpy(cached_line, line, CachePage::kLineLength); | 724 OS::MemCopy(cached_line, line, CachePage::kLineLength); |
725 *cache_valid_byte = CachePage::LINE_VALID; | 725 *cache_valid_byte = CachePage::LINE_VALID; |
726 } | 726 } |
727 } | 727 } |
728 | 728 |
729 | 729 |
730 void Simulator::Initialize(Isolate* isolate) { | 730 void Simulator::Initialize(Isolate* isolate) { |
731 if (isolate->simulator_initialized()) return; | 731 if (isolate->simulator_initialized()) return; |
732 isolate->set_simulator_initialized(true); | 732 isolate->set_simulator_initialized(true); |
733 ::v8::internal::ExternalReference::set_redirector(isolate, | 733 ::v8::internal::ExternalReference::set_redirector(isolate, |
734 &RedirectExternalReference); | 734 &RedirectExternalReference); |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
895 } | 895 } |
896 | 896 |
897 | 897 |
898 double Simulator::get_double_from_register_pair(int reg) { | 898 double Simulator::get_double_from_register_pair(int reg) { |
899 ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0)); | 899 ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0)); |
900 | 900 |
901 double dm_val = 0.0; | 901 double dm_val = 0.0; |
902 // Read the bits from the unsigned integer register_[] array | 902 // Read the bits from the unsigned integer register_[] array |
903 // into the double precision floating point value and return it. | 903 // into the double precision floating point value and return it. |
904 char buffer[2 * sizeof(vfp_registers_[0])]; | 904 char buffer[2 * sizeof(vfp_registers_[0])]; |
905 memcpy(buffer, ®isters_[reg], 2 * sizeof(registers_[0])); | 905 OS::MemCopy(buffer, ®isters_[reg], 2 * sizeof(registers_[0])); |
906 memcpy(&dm_val, buffer, 2 * sizeof(registers_[0])); | 906 OS::MemCopy(&dm_val, buffer, 2 * sizeof(registers_[0])); |
907 return(dm_val); | 907 return(dm_val); |
908 } | 908 } |
909 | 909 |
910 | 910 |
911 void Simulator::set_dw_register(int dreg, const int* dbl) { | 911 void Simulator::set_dw_register(int dreg, const int* dbl) { |
912 ASSERT((dreg >= 0) && (dreg < num_d_registers)); | 912 ASSERT((dreg >= 0) && (dreg < num_d_registers)); |
913 registers_[dreg] = dbl[0]; | 913 registers_[dreg] = dbl[0]; |
914 registers_[dreg + 1] = dbl[1]; | 914 registers_[dreg + 1] = dbl[1]; |
915 } | 915 } |
916 | 916 |
(...skipping 29 matching lines...) Expand all Loading... |
946 } | 946 } |
947 | 947 |
948 | 948 |
949 template<class InputType, int register_size> | 949 template<class InputType, int register_size> |
950 void Simulator::SetVFPRegister(int reg_index, const InputType& value) { | 950 void Simulator::SetVFPRegister(int reg_index, const InputType& value) { |
951 ASSERT(reg_index >= 0); | 951 ASSERT(reg_index >= 0); |
952 if (register_size == 1) ASSERT(reg_index < num_s_registers); | 952 if (register_size == 1) ASSERT(reg_index < num_s_registers); |
953 if (register_size == 2) ASSERT(reg_index < DwVfpRegister::NumRegisters()); | 953 if (register_size == 2) ASSERT(reg_index < DwVfpRegister::NumRegisters()); |
954 | 954 |
955 char buffer[register_size * sizeof(vfp_registers_[0])]; | 955 char buffer[register_size * sizeof(vfp_registers_[0])]; |
956 memcpy(buffer, &value, register_size * sizeof(vfp_registers_[0])); | 956 OS::MemCopy(buffer, &value, register_size * sizeof(vfp_registers_[0])); |
957 memcpy(&vfp_registers_[reg_index * register_size], buffer, | 957 OS::MemCopy(&vfp_registers_[reg_index * register_size], buffer, |
958 register_size * sizeof(vfp_registers_[0])); | 958 register_size * sizeof(vfp_registers_[0])); |
959 } | 959 } |
960 | 960 |
961 | 961 |
962 template<class ReturnType, int register_size> | 962 template<class ReturnType, int register_size> |
963 ReturnType Simulator::GetFromVFPRegister(int reg_index) { | 963 ReturnType Simulator::GetFromVFPRegister(int reg_index) { |
964 ASSERT(reg_index >= 0); | 964 ASSERT(reg_index >= 0); |
965 if (register_size == 1) ASSERT(reg_index < num_s_registers); | 965 if (register_size == 1) ASSERT(reg_index < num_s_registers); |
966 if (register_size == 2) ASSERT(reg_index < DwVfpRegister::NumRegisters()); | 966 if (register_size == 2) ASSERT(reg_index < DwVfpRegister::NumRegisters()); |
967 | 967 |
968 ReturnType value = 0; | 968 ReturnType value = 0; |
969 char buffer[register_size * sizeof(vfp_registers_[0])]; | 969 char buffer[register_size * sizeof(vfp_registers_[0])]; |
970 memcpy(buffer, &vfp_registers_[register_size * reg_index], | 970 OS::MemCopy(buffer, &vfp_registers_[register_size * reg_index], |
971 register_size * sizeof(vfp_registers_[0])); | 971 register_size * sizeof(vfp_registers_[0])); |
972 memcpy(&value, buffer, register_size * sizeof(vfp_registers_[0])); | 972 OS::MemCopy(&value, buffer, register_size * sizeof(vfp_registers_[0])); |
973 return value; | 973 return value; |
974 } | 974 } |
975 | 975 |
976 | 976 |
977 // Runtime FP routines take up to two double arguments and zero | 977 // Runtime FP routines take up to two double arguments and zero |
978 // or one integer arguments. All are constructed here, | 978 // or one integer arguments. All are constructed here, |
979 // from r0-r3 or d0 and d1. | 979 // from r0-r3 or d0 and d1. |
980 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) { | 980 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) { |
981 if (use_eabi_hardfloat()) { | 981 if (use_eabi_hardfloat()) { |
982 *x = vfp_registers_[0]; | 982 *x = vfp_registers_[0]; |
983 *y = vfp_registers_[1]; | 983 *y = vfp_registers_[1]; |
984 *z = registers_[1]; | 984 *z = registers_[1]; |
985 } else { | 985 } else { |
986 // We use a char buffer to get around the strict-aliasing rules which | 986 // We use a char buffer to get around the strict-aliasing rules which |
987 // otherwise allow the compiler to optimize away the copy. | 987 // otherwise allow the compiler to optimize away the copy. |
988 char buffer[sizeof(*x)]; | 988 char buffer[sizeof(*x)]; |
989 // Registers 0 and 1 -> x. | 989 // Registers 0 and 1 -> x. |
990 memcpy(buffer, registers_, sizeof(*x)); | 990 OS::MemCopy(buffer, registers_, sizeof(*x)); |
991 memcpy(x, buffer, sizeof(*x)); | 991 OS::MemCopy(x, buffer, sizeof(*x)); |
992 // Registers 2 and 3 -> y. | 992 // Registers 2 and 3 -> y. |
993 memcpy(buffer, registers_ + 2, sizeof(*y)); | 993 OS::MemCopy(buffer, registers_ + 2, sizeof(*y)); |
994 memcpy(y, buffer, sizeof(*y)); | 994 OS::MemCopy(y, buffer, sizeof(*y)); |
995 // Register 2 -> z. | 995 // Register 2 -> z. |
996 memcpy(buffer, registers_ + 2, sizeof(*z)); | 996 OS::MemCopy(buffer, registers_ + 2, sizeof(*z)); |
997 memcpy(z, buffer, sizeof(*z)); | 997 OS::MemCopy(z, buffer, sizeof(*z)); |
998 } | 998 } |
999 } | 999 } |
1000 | 1000 |
1001 | 1001 |
1002 // The return value is either in r0/r1 or d0. | 1002 // The return value is either in r0/r1 or d0. |
1003 void Simulator::SetFpResult(const double& result) { | 1003 void Simulator::SetFpResult(const double& result) { |
1004 if (use_eabi_hardfloat()) { | 1004 if (use_eabi_hardfloat()) { |
1005 char buffer[2 * sizeof(vfp_registers_[0])]; | 1005 char buffer[2 * sizeof(vfp_registers_[0])]; |
1006 memcpy(buffer, &result, sizeof(buffer)); | 1006 OS::MemCopy(buffer, &result, sizeof(buffer)); |
1007 // Copy result to d0. | 1007 // Copy result to d0. |
1008 memcpy(vfp_registers_, buffer, sizeof(buffer)); | 1008 OS::MemCopy(vfp_registers_, buffer, sizeof(buffer)); |
1009 } else { | 1009 } else { |
1010 char buffer[2 * sizeof(registers_[0])]; | 1010 char buffer[2 * sizeof(registers_[0])]; |
1011 memcpy(buffer, &result, sizeof(buffer)); | 1011 OS::MemCopy(buffer, &result, sizeof(buffer)); |
1012 // Copy result to r0 and r1. | 1012 // Copy result to r0 and r1. |
1013 memcpy(registers_, buffer, sizeof(buffer)); | 1013 OS::MemCopy(registers_, buffer, sizeof(buffer)); |
1014 } | 1014 } |
1015 } | 1015 } |
1016 | 1016 |
1017 | 1017 |
1018 void Simulator::TrashCallerSaveRegisters() { | 1018 void Simulator::TrashCallerSaveRegisters() { |
1019 // We don't trash the registers with the return value. | 1019 // We don't trash the registers with the return value. |
1020 registers_[2] = 0x50Bad4U; | 1020 registers_[2] = 0x50Bad4U; |
1021 registers_[3] = 0x50Bad4U; | 1021 registers_[3] = 0x50Bad4U; |
1022 registers_[12] = 0x50Bad4U; | 1022 registers_[12] = 0x50Bad4U; |
1023 } | 1023 } |
(...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1582 get_sinteger_from_s_register(reg), instr); | 1582 get_sinteger_from_s_register(reg), instr); |
1583 } | 1583 } |
1584 address += 1; | 1584 address += 1; |
1585 } else { | 1585 } else { |
1586 if (load) { | 1586 if (load) { |
1587 int32_t data[] = { | 1587 int32_t data[] = { |
1588 ReadW(reinterpret_cast<int32_t>(address), instr), | 1588 ReadW(reinterpret_cast<int32_t>(address), instr), |
1589 ReadW(reinterpret_cast<int32_t>(address + 1), instr) | 1589 ReadW(reinterpret_cast<int32_t>(address + 1), instr) |
1590 }; | 1590 }; |
1591 double d; | 1591 double d; |
1592 memcpy(&d, data, 8); | 1592 OS::MemCopy(&d, data, 8); |
1593 set_d_register_from_double(reg, d); | 1593 set_d_register_from_double(reg, d); |
1594 } else { | 1594 } else { |
1595 int32_t data[2]; | 1595 int32_t data[2]; |
1596 double d = get_double_from_d_register(reg); | 1596 double d = get_double_from_d_register(reg); |
1597 memcpy(data, &d, 8); | 1597 OS::MemCopy(data, &d, 8); |
1598 WriteW(reinterpret_cast<int32_t>(address), data[0], instr); | 1598 WriteW(reinterpret_cast<int32_t>(address), data[0], instr); |
1599 WriteW(reinterpret_cast<int32_t>(address + 1), data[1], instr); | 1599 WriteW(reinterpret_cast<int32_t>(address + 1), data[1], instr); |
1600 } | 1600 } |
1601 address += 2; | 1601 address += 2; |
1602 } | 1602 } |
1603 } | 1603 } |
1604 ASSERT(reinterpret_cast<intptr_t>(address) - operand_size == end_address); | 1604 ASSERT(reinterpret_cast<intptr_t>(address) - operand_size == end_address); |
1605 } | 1605 } |
1606 | 1606 |
1607 | 1607 |
(...skipping 1217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2825 if ((instr->VCValue() == 0x0) && | 2825 if ((instr->VCValue() == 0x0) && |
2826 (instr->VAValue() == 0x0)) { | 2826 (instr->VAValue() == 0x0)) { |
2827 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); | 2827 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); |
2828 } else if ((instr->VLValue() == 0x0) && | 2828 } else if ((instr->VLValue() == 0x0) && |
2829 (instr->VCValue() == 0x1) && | 2829 (instr->VCValue() == 0x1) && |
2830 (instr->Bit(23) == 0x0)) { | 2830 (instr->Bit(23) == 0x0)) { |
2831 // vmov (ARM core register to scalar) | 2831 // vmov (ARM core register to scalar) |
2832 int vd = instr->Bits(19, 16) | (instr->Bit(7) << 4); | 2832 int vd = instr->Bits(19, 16) | (instr->Bit(7) << 4); |
2833 double dd_value = get_double_from_d_register(vd); | 2833 double dd_value = get_double_from_d_register(vd); |
2834 int32_t data[2]; | 2834 int32_t data[2]; |
2835 memcpy(data, &dd_value, 8); | 2835 OS::MemCopy(data, &dd_value, 8); |
2836 data[instr->Bit(21)] = get_register(instr->RtValue()); | 2836 data[instr->Bit(21)] = get_register(instr->RtValue()); |
2837 memcpy(&dd_value, data, 8); | 2837 OS::MemCopy(&dd_value, data, 8); |
2838 set_d_register_from_double(vd, dd_value); | 2838 set_d_register_from_double(vd, dd_value); |
2839 } else if ((instr->VLValue() == 0x1) && | 2839 } else if ((instr->VLValue() == 0x1) && |
2840 (instr->VCValue() == 0x0) && | 2840 (instr->VCValue() == 0x0) && |
2841 (instr->VAValue() == 0x7) && | 2841 (instr->VAValue() == 0x7) && |
2842 (instr->Bits(19, 16) == 0x1)) { | 2842 (instr->Bits(19, 16) == 0x1)) { |
2843 // vmrs | 2843 // vmrs |
2844 uint32_t rt = instr->RtValue(); | 2844 uint32_t rt = instr->RtValue(); |
2845 if (rt == 0xF) { | 2845 if (rt == 0xF) { |
2846 Copy_FPSCR_to_APSR(); | 2846 Copy_FPSCR_to_APSR(); |
2847 } else { | 2847 } else { |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3176 // Load and store double to two GP registers | 3176 // Load and store double to two GP registers |
3177 if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) { | 3177 if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) { |
3178 UNIMPLEMENTED(); // Not used by V8. | 3178 UNIMPLEMENTED(); // Not used by V8. |
3179 } else { | 3179 } else { |
3180 int rt = instr->RtValue(); | 3180 int rt = instr->RtValue(); |
3181 int rn = instr->RnValue(); | 3181 int rn = instr->RnValue(); |
3182 int vm = instr->VFPMRegValue(kDoublePrecision); | 3182 int vm = instr->VFPMRegValue(kDoublePrecision); |
3183 if (instr->HasL()) { | 3183 if (instr->HasL()) { |
3184 int32_t data[2]; | 3184 int32_t data[2]; |
3185 double d = get_double_from_d_register(vm); | 3185 double d = get_double_from_d_register(vm); |
3186 memcpy(data, &d, 8); | 3186 OS::MemCopy(data, &d, 8); |
3187 set_register(rt, data[0]); | 3187 set_register(rt, data[0]); |
3188 set_register(rn, data[1]); | 3188 set_register(rn, data[1]); |
3189 } else { | 3189 } else { |
3190 int32_t data[] = { get_register(rt), get_register(rn) }; | 3190 int32_t data[] = { get_register(rt), get_register(rn) }; |
3191 double d; | 3191 double d; |
3192 memcpy(&d, data, 8); | 3192 OS::MemCopy(&d, data, 8); |
3193 set_d_register_from_double(vm, d); | 3193 set_d_register_from_double(vm, d); |
3194 } | 3194 } |
3195 } | 3195 } |
3196 break; | 3196 break; |
3197 case 0x8: | 3197 case 0x8: |
3198 case 0xA: | 3198 case 0xA: |
3199 case 0xC: | 3199 case 0xC: |
3200 case 0xE: { // Load and store double to memory. | 3200 case 0xE: { // Load and store double to memory. |
3201 int rn = instr->RnValue(); | 3201 int rn = instr->RnValue(); |
3202 int vd = instr->VFPDRegValue(kDoublePrecision); | 3202 int vd = instr->VFPDRegValue(kDoublePrecision); |
3203 int offset = instr->Immed8Value(); | 3203 int offset = instr->Immed8Value(); |
3204 if (!instr->HasU()) { | 3204 if (!instr->HasU()) { |
3205 offset = -offset; | 3205 offset = -offset; |
3206 } | 3206 } |
3207 int32_t address = get_register(rn) + 4 * offset; | 3207 int32_t address = get_register(rn) + 4 * offset; |
3208 if (instr->HasL()) { | 3208 if (instr->HasL()) { |
3209 // Load double from memory: vldr. | 3209 // Load double from memory: vldr. |
3210 int32_t data[] = { | 3210 int32_t data[] = { |
3211 ReadW(address, instr), | 3211 ReadW(address, instr), |
3212 ReadW(address + 4, instr) | 3212 ReadW(address + 4, instr) |
3213 }; | 3213 }; |
3214 double val; | 3214 double val; |
3215 memcpy(&val, data, 8); | 3215 OS::MemCopy(&val, data, 8); |
3216 set_d_register_from_double(vd, val); | 3216 set_d_register_from_double(vd, val); |
3217 } else { | 3217 } else { |
3218 // Store double to memory: vstr. | 3218 // Store double to memory: vstr. |
3219 int32_t data[2]; | 3219 int32_t data[2]; |
3220 double val = get_double_from_d_register(vd); | 3220 double val = get_double_from_d_register(vd); |
3221 memcpy(data, &val, 8); | 3221 OS::MemCopy(data, &val, 8); |
3222 WriteW(address, data[0], instr); | 3222 WriteW(address, data[0], instr); |
3223 WriteW(address + 4, data[1], instr); | 3223 WriteW(address + 4, data[1], instr); |
3224 } | 3224 } |
3225 break; | 3225 break; |
3226 } | 3226 } |
3227 case 0x4: | 3227 case 0x4: |
3228 case 0x5: | 3228 case 0x5: |
3229 case 0x6: | 3229 case 0x6: |
3230 case 0x7: | 3230 case 0x7: |
3231 case 0x9: | 3231 case 0x9: |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3434 } | 3434 } |
3435 | 3435 |
3436 | 3436 |
3437 double Simulator::CallFP(byte* entry, double d0, double d1) { | 3437 double Simulator::CallFP(byte* entry, double d0, double d1) { |
3438 if (use_eabi_hardfloat()) { | 3438 if (use_eabi_hardfloat()) { |
3439 set_d_register_from_double(0, d0); | 3439 set_d_register_from_double(0, d0); |
3440 set_d_register_from_double(1, d1); | 3440 set_d_register_from_double(1, d1); |
3441 } else { | 3441 } else { |
3442 int buffer[2]; | 3442 int buffer[2]; |
3443 ASSERT(sizeof(buffer[0]) * 2 == sizeof(d0)); | 3443 ASSERT(sizeof(buffer[0]) * 2 == sizeof(d0)); |
3444 memcpy(buffer, &d0, sizeof(d0)); | 3444 OS::MemCopy(buffer, &d0, sizeof(d0)); |
3445 set_dw_register(0, buffer); | 3445 set_dw_register(0, buffer); |
3446 memcpy(buffer, &d1, sizeof(d1)); | 3446 OS::MemCopy(buffer, &d1, sizeof(d1)); |
3447 set_dw_register(2, buffer); | 3447 set_dw_register(2, buffer); |
3448 } | 3448 } |
3449 CallInternal(entry); | 3449 CallInternal(entry); |
3450 if (use_eabi_hardfloat()) { | 3450 if (use_eabi_hardfloat()) { |
3451 return get_double_from_d_register(0); | 3451 return get_double_from_d_register(0); |
3452 } else { | 3452 } else { |
3453 return get_double_from_register_pair(0); | 3453 return get_double_from_register_pair(0); |
3454 } | 3454 } |
3455 } | 3455 } |
3456 | 3456 |
(...skipping 13 matching lines...) Expand all Loading... |
3470 uintptr_t address = *stack_slot; | 3470 uintptr_t address = *stack_slot; |
3471 set_register(sp, current_sp + sizeof(uintptr_t)); | 3471 set_register(sp, current_sp + sizeof(uintptr_t)); |
3472 return address; | 3472 return address; |
3473 } | 3473 } |
3474 | 3474 |
3475 } } // namespace v8::internal | 3475 } } // namespace v8::internal |
3476 | 3476 |
3477 #endif // USE_SIMULATOR | 3477 #endif // USE_SIMULATOR |
3478 | 3478 |
3479 #endif // V8_TARGET_ARCH_ARM | 3479 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |