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 16 matching lines...) Expand all Loading... |
27 | 27 |
28 #include <stdlib.h> | 28 #include <stdlib.h> |
29 #include <math.h> | 29 #include <math.h> |
30 #include <cstdarg> | 30 #include <cstdarg> |
31 #include "v8.h" | 31 #include "v8.h" |
32 | 32 |
33 #if defined(V8_TARGET_ARCH_ARM) | 33 #if defined(V8_TARGET_ARCH_ARM) |
34 | 34 |
35 #include "disasm.h" | 35 #include "disasm.h" |
36 #include "assembler.h" | 36 #include "assembler.h" |
| 37 #include "codegen.h" |
37 #include "arm/constants-arm.h" | 38 #include "arm/constants-arm.h" |
38 #include "arm/simulator-arm.h" | 39 #include "arm/simulator-arm.h" |
39 | 40 |
40 #if defined(USE_SIMULATOR) | 41 #if defined(USE_SIMULATOR) |
41 | 42 |
42 // Only build the simulator if not compiling for real ARM hardware. | 43 // Only build the simulator if not compiling for real ARM hardware. |
43 namespace v8 { | 44 namespace v8 { |
44 namespace internal { | 45 namespace internal { |
45 | 46 |
46 // This macro provides a platform independent use of sscanf. The reason for | 47 // This macro provides a platform independent use of sscanf. The reason for |
(...skipping 710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
757 } | 758 } |
758 n_flag_ = false; | 759 n_flag_ = false; |
759 z_flag_ = false; | 760 z_flag_ = false; |
760 c_flag_ = false; | 761 c_flag_ = false; |
761 v_flag_ = false; | 762 v_flag_ = false; |
762 | 763 |
763 // Initializing VFP registers. | 764 // Initializing VFP registers. |
764 // All registers are initialized to zero to start with | 765 // All registers are initialized to zero to start with |
765 // even though s_registers_ & d_registers_ share the same | 766 // even though s_registers_ & d_registers_ share the same |
766 // physical registers in the target. | 767 // physical registers in the target. |
767 for (int i = 0; i < num_s_registers; i++) { | 768 for (int i = 0; i < num_d_registers * 2; i++) { |
768 vfp_register[i] = 0; | 769 vfp_register[i] = 0; |
769 } | 770 } |
770 n_flag_FPSCR_ = false; | 771 n_flag_FPSCR_ = false; |
771 z_flag_FPSCR_ = false; | 772 z_flag_FPSCR_ = false; |
772 c_flag_FPSCR_ = false; | 773 c_flag_FPSCR_ = false; |
773 v_flag_FPSCR_ = false; | 774 v_flag_FPSCR_ = false; |
774 FPSCR_rounding_mode_ = RZ; | 775 FPSCR_rounding_mode_ = RZ; |
775 | 776 |
776 inv_op_vfp_flag_ = false; | 777 inv_op_vfp_flag_ = false; |
777 div_zero_vfp_flag_ = false; | 778 div_zero_vfp_flag_ = false; |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
942 unsigned int Simulator::get_s_register(int sreg) const { | 943 unsigned int Simulator::get_s_register(int sreg) const { |
943 ASSERT((sreg >= 0) && (sreg < num_s_registers)); | 944 ASSERT((sreg >= 0) && (sreg < num_s_registers)); |
944 return vfp_register[sreg]; | 945 return vfp_register[sreg]; |
945 } | 946 } |
946 | 947 |
947 | 948 |
948 template<class InputType, int register_size> | 949 template<class InputType, int register_size> |
949 void Simulator::SetVFPRegister(int reg_index, const InputType& value) { | 950 void Simulator::SetVFPRegister(int reg_index, const InputType& value) { |
950 ASSERT(reg_index >= 0); | 951 ASSERT(reg_index >= 0); |
951 if (register_size == 1) ASSERT(reg_index < num_s_registers); | 952 if (register_size == 1) ASSERT(reg_index < num_s_registers); |
952 if (register_size == 2) ASSERT(reg_index < num_d_registers); | 953 if (register_size == 2) ASSERT(reg_index < DwVfpRegister::NumRegisters()); |
953 | 954 |
954 char buffer[register_size * sizeof(vfp_register[0])]; | 955 char buffer[register_size * sizeof(vfp_register[0])]; |
955 memcpy(buffer, &value, register_size * sizeof(vfp_register[0])); | 956 memcpy(buffer, &value, register_size * sizeof(vfp_register[0])); |
956 memcpy(&vfp_register[reg_index * register_size], buffer, | 957 memcpy(&vfp_register[reg_index * register_size], buffer, |
957 register_size * sizeof(vfp_register[0])); | 958 register_size * sizeof(vfp_register[0])); |
958 } | 959 } |
959 | 960 |
960 | 961 |
961 template<class ReturnType, int register_size> | 962 template<class ReturnType, int register_size> |
962 ReturnType Simulator::GetFromVFPRegister(int reg_index) { | 963 ReturnType Simulator::GetFromVFPRegister(int reg_index) { |
963 ASSERT(reg_index >= 0); | 964 ASSERT(reg_index >= 0); |
964 if (register_size == 1) ASSERT(reg_index < num_s_registers); | 965 if (register_size == 1) ASSERT(reg_index < num_s_registers); |
965 if (register_size == 2) ASSERT(reg_index < num_d_registers); | 966 if (register_size == 2) ASSERT(reg_index < DwVfpRegister::NumRegisters()); |
966 | 967 |
967 ReturnType value = 0; | 968 ReturnType value = 0; |
968 char buffer[register_size * sizeof(vfp_register[0])]; | 969 char buffer[register_size * sizeof(vfp_register[0])]; |
969 memcpy(buffer, &vfp_register[register_size * reg_index], | 970 memcpy(buffer, &vfp_register[register_size * reg_index], |
970 register_size * sizeof(vfp_register[0])); | 971 register_size * sizeof(vfp_register[0])); |
971 memcpy(&value, buffer, register_size * sizeof(vfp_register[0])); | 972 memcpy(&value, buffer, register_size * sizeof(vfp_register[0])); |
972 return value; | 973 return value; |
973 } | 974 } |
974 | 975 |
975 | 976 |
(...skipping 630 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1606 if (load) { | 1607 if (load) { |
1607 set_s_register_from_sinteger( | 1608 set_s_register_from_sinteger( |
1608 reg, ReadW(reinterpret_cast<int32_t>(address), instr)); | 1609 reg, ReadW(reinterpret_cast<int32_t>(address), instr)); |
1609 } else { | 1610 } else { |
1610 WriteW(reinterpret_cast<int32_t>(address), | 1611 WriteW(reinterpret_cast<int32_t>(address), |
1611 get_sinteger_from_s_register(reg), instr); | 1612 get_sinteger_from_s_register(reg), instr); |
1612 } | 1613 } |
1613 address += 1; | 1614 address += 1; |
1614 } else { | 1615 } else { |
1615 if (load) { | 1616 if (load) { |
1616 set_s_register_from_sinteger( | 1617 int32_t data[] = { |
1617 2 * reg, ReadW(reinterpret_cast<int32_t>(address), instr)); | 1618 ReadW(reinterpret_cast<int32_t>(address), instr), |
1618 set_s_register_from_sinteger( | 1619 ReadW(reinterpret_cast<int32_t>(address + 1), instr) |
1619 2 * reg + 1, ReadW(reinterpret_cast<int32_t>(address + 1), instr)); | 1620 }; |
| 1621 double d; |
| 1622 memcpy(&d, data, 8); |
| 1623 set_d_register_from_double(reg, d); |
1620 } else { | 1624 } else { |
1621 WriteW(reinterpret_cast<int32_t>(address), | 1625 int32_t data[2]; |
1622 get_sinteger_from_s_register(2 * reg), instr); | 1626 double d = get_double_from_d_register(reg); |
1623 WriteW(reinterpret_cast<int32_t>(address + 1), | 1627 memcpy(data, &d, 8); |
1624 get_sinteger_from_s_register(2 * reg + 1), instr); | 1628 WriteW(reinterpret_cast<int32_t>(address), data[0], instr); |
| 1629 WriteW(reinterpret_cast<int32_t>(address + 1), data[1], instr); |
1625 } | 1630 } |
1626 address += 2; | 1631 address += 2; |
1627 } | 1632 } |
1628 } | 1633 } |
1629 ASSERT(reinterpret_cast<intptr_t>(address) - operand_size == end_address); | 1634 ASSERT(reinterpret_cast<intptr_t>(address) - operand_size == end_address); |
1630 } | 1635 } |
1631 | 1636 |
1632 | 1637 |
1633 // Calls into the V8 runtime are based on this very simple interface. | 1638 // Calls into the V8 runtime are based on this very simple interface. |
1634 // Note: To be able to return two values from some calls the code in runtime.cc | 1639 // Note: To be able to return two values from some calls the code in runtime.cc |
(...skipping 1168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2803 double dd_value = dn_value / dm_value; | 2808 double dd_value = dn_value / dm_value; |
2804 div_zero_vfp_flag_ = (dm_value == 0); | 2809 div_zero_vfp_flag_ = (dm_value == 0); |
2805 set_d_register_from_double(vd, dd_value); | 2810 set_d_register_from_double(vd, dd_value); |
2806 } else { | 2811 } else { |
2807 UNIMPLEMENTED(); // Not used by V8. | 2812 UNIMPLEMENTED(); // Not used by V8. |
2808 } | 2813 } |
2809 } else { | 2814 } else { |
2810 if ((instr->VCValue() == 0x0) && | 2815 if ((instr->VCValue() == 0x0) && |
2811 (instr->VAValue() == 0x0)) { | 2816 (instr->VAValue() == 0x0)) { |
2812 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); | 2817 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); |
| 2818 } else if ((instr->VLValue() == 0x0) && |
| 2819 (instr->VCValue() == 0x1) && |
| 2820 (instr->Bit(23) == 0x0)) { |
| 2821 // vmov (ARM core register to scalar) |
| 2822 int vd = instr->Bits(19, 16) | (instr->Bit(7) << 4); |
| 2823 double dd_value = get_double_from_d_register(vd); |
| 2824 int32_t data[2]; |
| 2825 memcpy(data, &dd_value, 8); |
| 2826 data[instr->Bit(21)] = get_register(instr->RtValue()); |
| 2827 memcpy(&dd_value, data, 8); |
| 2828 set_d_register_from_double(vd, dd_value); |
2813 } else if ((instr->VLValue() == 0x1) && | 2829 } else if ((instr->VLValue() == 0x1) && |
2814 (instr->VCValue() == 0x0) && | 2830 (instr->VCValue() == 0x0) && |
2815 (instr->VAValue() == 0x7) && | 2831 (instr->VAValue() == 0x7) && |
2816 (instr->Bits(19, 16) == 0x1)) { | 2832 (instr->Bits(19, 16) == 0x1)) { |
2817 // vmrs | 2833 // vmrs |
2818 uint32_t rt = instr->RtValue(); | 2834 uint32_t rt = instr->RtValue(); |
2819 if (rt == 0xF) { | 2835 if (rt == 0xF) { |
2820 Copy_FPSCR_to_APSR(); | 2836 Copy_FPSCR_to_APSR(); |
2821 } else { | 2837 } else { |
2822 // Emulate FPSCR from the Simulator flags. | 2838 // Emulate FPSCR from the Simulator flags. |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3141 // Load/store multiple single from memory: vldm/vstm. | 3157 // Load/store multiple single from memory: vldm/vstm. |
3142 HandleVList(instr); | 3158 HandleVList(instr); |
3143 break; | 3159 break; |
3144 default: | 3160 default: |
3145 UNIMPLEMENTED(); // Not used by V8. | 3161 UNIMPLEMENTED(); // Not used by V8. |
3146 } | 3162 } |
3147 } else if (instr->CoprocessorValue() == 0xB) { | 3163 } else if (instr->CoprocessorValue() == 0xB) { |
3148 switch (instr->OpcodeValue()) { | 3164 switch (instr->OpcodeValue()) { |
3149 case 0x2: | 3165 case 0x2: |
3150 // Load and store double to two GP registers | 3166 // Load and store double to two GP registers |
3151 if (instr->Bits(7, 4) != 0x1) { | 3167 if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) { |
3152 UNIMPLEMENTED(); // Not used by V8. | 3168 UNIMPLEMENTED(); // Not used by V8. |
3153 } else { | 3169 } else { |
3154 int rt = instr->RtValue(); | 3170 int rt = instr->RtValue(); |
3155 int rn = instr->RnValue(); | 3171 int rn = instr->RnValue(); |
3156 int vm = instr->VmValue(); | 3172 int vm = instr->VFPMRegValue(kDoublePrecision); |
3157 if (instr->HasL()) { | 3173 if (instr->HasL()) { |
3158 int32_t rt_int_value = get_sinteger_from_s_register(2*vm); | 3174 int32_t data[2]; |
3159 int32_t rn_int_value = get_sinteger_from_s_register(2*vm+1); | 3175 double d = get_double_from_d_register(vm); |
3160 | 3176 memcpy(data, &d, 8); |
3161 set_register(rt, rt_int_value); | 3177 set_register(rt, data[0]); |
3162 set_register(rn, rn_int_value); | 3178 set_register(rn, data[1]); |
3163 } else { | 3179 } else { |
3164 int32_t rs_val = get_register(rt); | 3180 int32_t data[] = { get_register(rt), get_register(rn) }; |
3165 int32_t rn_val = get_register(rn); | 3181 double d; |
3166 | 3182 memcpy(&d, data, 8); |
3167 set_s_register_from_sinteger(2*vm, rs_val); | 3183 set_d_register_from_double(vm, d); |
3168 set_s_register_from_sinteger((2*vm+1), rn_val); | |
3169 } | 3184 } |
3170 } | 3185 } |
3171 break; | 3186 break; |
3172 case 0x8: | 3187 case 0x8: |
3173 case 0xC: { // Load and store double to memory. | 3188 case 0xA: |
| 3189 case 0xC: |
| 3190 case 0xE: { // Load and store double to memory. |
3174 int rn = instr->RnValue(); | 3191 int rn = instr->RnValue(); |
3175 int vd = instr->VdValue(); | 3192 int vd = instr->VFPDRegValue(kDoublePrecision); |
3176 int offset = instr->Immed8Value(); | 3193 int offset = instr->Immed8Value(); |
3177 if (!instr->HasU()) { | 3194 if (!instr->HasU()) { |
3178 offset = -offset; | 3195 offset = -offset; |
3179 } | 3196 } |
3180 int32_t address = get_register(rn) + 4 * offset; | 3197 int32_t address = get_register(rn) + 4 * offset; |
3181 if (instr->HasL()) { | 3198 if (instr->HasL()) { |
3182 // Load double from memory: vldr. | 3199 // Load double from memory: vldr. |
3183 set_s_register_from_sinteger(2*vd, ReadW(address, instr)); | 3200 int32_t data[] = { |
3184 set_s_register_from_sinteger(2*vd + 1, ReadW(address + 4, instr)); | 3201 ReadW(address, instr), |
| 3202 ReadW(address + 4, instr) |
| 3203 }; |
| 3204 double val; |
| 3205 memcpy(&val, data, 8); |
| 3206 set_d_register_from_double(vd, val); |
3185 } else { | 3207 } else { |
3186 // Store double to memory: vstr. | 3208 // Store double to memory: vstr. |
3187 WriteW(address, get_sinteger_from_s_register(2*vd), instr); | 3209 int32_t data[2]; |
3188 WriteW(address + 4, get_sinteger_from_s_register(2*vd + 1), instr); | 3210 double val = get_double_from_d_register(vd); |
| 3211 memcpy(data, &val, 8); |
| 3212 WriteW(address, data[0], instr); |
| 3213 WriteW(address + 4, data[1], instr); |
3189 } | 3214 } |
3190 break; | 3215 break; |
3191 } | 3216 } |
3192 case 0x4: | 3217 case 0x4: |
3193 case 0x5: | 3218 case 0x5: |
| 3219 case 0x6: |
| 3220 case 0x7: |
3194 case 0x9: | 3221 case 0x9: |
| 3222 case 0xB: |
3195 // Load/store multiple double from memory: vldm/vstm. | 3223 // Load/store multiple double from memory: vldm/vstm. |
3196 HandleVList(instr); | 3224 HandleVList(instr); |
3197 break; | 3225 break; |
3198 default: | 3226 default: |
3199 UNIMPLEMENTED(); // Not used by V8. | 3227 UNIMPLEMENTED(); // Not used by V8. |
3200 } | 3228 } |
3201 } else { | 3229 } else { |
3202 UNIMPLEMENTED(); // Not used by V8. | 3230 UNIMPLEMENTED(); // Not used by V8. |
3203 } | 3231 } |
3204 } | 3232 } |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3432 uintptr_t address = *stack_slot; | 3460 uintptr_t address = *stack_slot; |
3433 set_register(sp, current_sp + sizeof(uintptr_t)); | 3461 set_register(sp, current_sp + sizeof(uintptr_t)); |
3434 return address; | 3462 return address; |
3435 } | 3463 } |
3436 | 3464 |
3437 } } // namespace v8::internal | 3465 } } // namespace v8::internal |
3438 | 3466 |
3439 #endif // USE_SIMULATOR | 3467 #endif // USE_SIMULATOR |
3440 | 3468 |
3441 #endif // V8_TARGET_ARCH_ARM | 3469 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |