OLD | NEW |
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
2 // All Rights Reserved. | 2 // All Rights Reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
6 // are met: | 6 // are met: |
7 // | 7 // |
8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
10 // | 10 // |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 // ----------------------------------------------------------------------------- | 48 // ----------------------------------------------------------------------------- |
49 // Implementation of CpuFeatures | 49 // Implementation of CpuFeatures |
50 | 50 |
51 #ifdef DEBUG | 51 #ifdef DEBUG |
52 bool CpuFeatures::initialized_ = false; | 52 bool CpuFeatures::initialized_ = false; |
53 #endif | 53 #endif |
54 uint64_t CpuFeatures::supported_ = 0; | 54 uint64_t CpuFeatures::supported_ = 0; |
55 uint64_t CpuFeatures::found_by_runtime_probing_ = 0; | 55 uint64_t CpuFeatures::found_by_runtime_probing_ = 0; |
56 | 56 |
57 | 57 |
| 58 // The Probe method needs executable memory, so it uses Heap::CreateCode. |
| 59 // Allocation failure is silent and leads to safe default. |
58 void CpuFeatures::Probe() { | 60 void CpuFeatures::Probe() { |
59 ASSERT(!initialized_); | 61 ASSERT(!initialized_); |
60 ASSERT(supported_ == 0); | 62 ASSERT(supported_ == 0); |
61 #ifdef DEBUG | 63 #ifdef DEBUG |
62 initialized_ = true; | 64 initialized_ = true; |
63 #endif | 65 #endif |
64 if (Serializer::enabled()) { | 66 if (Serializer::enabled()) { |
65 supported_ |= OS::CpuFeaturesImpliedByPlatform(); | 67 supported_ |= OS::CpuFeaturesImpliedByPlatform(); |
66 return; // No features if we might serialize. | 68 return; // No features if we might serialize. |
67 } | 69 } |
(...skipping 11 matching lines...) Expand all Loading... |
79 } | 81 } |
80 | 82 |
81 Assembler assm(NULL, memory->address(), kBufferSize); | 83 Assembler assm(NULL, memory->address(), kBufferSize); |
82 Label cpuid, done; | 84 Label cpuid, done; |
83 #define __ assm. | 85 #define __ assm. |
84 // Save old esp, since we are going to modify the stack. | 86 // Save old esp, since we are going to modify the stack. |
85 __ push(ebp); | 87 __ push(ebp); |
86 __ pushfd(); | 88 __ pushfd(); |
87 __ push(ecx); | 89 __ push(ecx); |
88 __ push(ebx); | 90 __ push(ebx); |
89 __ mov(ebp, Operand(esp)); | 91 __ mov(ebp, esp); |
90 | 92 |
91 // If we can modify bit 21 of the EFLAGS register, then CPUID is supported. | 93 // If we can modify bit 21 of the EFLAGS register, then CPUID is supported. |
92 __ pushfd(); | 94 __ pushfd(); |
93 __ pop(eax); | 95 __ pop(eax); |
94 __ mov(edx, Operand(eax)); | 96 __ mov(edx, eax); |
95 __ xor_(eax, 0x200000); // Flip bit 21. | 97 __ xor_(eax, 0x200000); // Flip bit 21. |
96 __ push(eax); | 98 __ push(eax); |
97 __ popfd(); | 99 __ popfd(); |
98 __ pushfd(); | 100 __ pushfd(); |
99 __ pop(eax); | 101 __ pop(eax); |
100 __ xor_(eax, Operand(edx)); // Different if CPUID is supported. | 102 __ xor_(eax, edx); // Different if CPUID is supported. |
101 __ j(not_zero, &cpuid); | 103 __ j(not_zero, &cpuid); |
102 | 104 |
103 // CPUID not supported. Clear the supported features in edx:eax. | 105 // CPUID not supported. Clear the supported features in edx:eax. |
104 __ xor_(eax, Operand(eax)); | 106 __ xor_(eax, eax); |
105 __ xor_(edx, Operand(edx)); | 107 __ xor_(edx, edx); |
106 __ jmp(&done); | 108 __ jmp(&done); |
107 | 109 |
108 // Invoke CPUID with 1 in eax to get feature information in | 110 // Invoke CPUID with 1 in eax to get feature information in |
109 // ecx:edx. Temporarily enable CPUID support because we know it's | 111 // ecx:edx. Temporarily enable CPUID support because we know it's |
110 // safe here. | 112 // safe here. |
111 __ bind(&cpuid); | 113 __ bind(&cpuid); |
112 __ mov(eax, 1); | 114 __ mov(eax, 1); |
113 supported_ = (1 << CPUID); | 115 supported_ = (1 << CPUID); |
114 { Scope fscope(CPUID); | 116 { Scope fscope(CPUID); |
115 __ cpuid(); | 117 __ cpuid(); |
116 } | 118 } |
117 supported_ = 0; | 119 supported_ = 0; |
118 | 120 |
119 // Move the result from ecx:edx to edx:eax and make sure to mark the | 121 // Move the result from ecx:edx to edx:eax and make sure to mark the |
120 // CPUID feature as supported. | 122 // CPUID feature as supported. |
121 __ mov(eax, Operand(edx)); | 123 __ mov(eax, edx); |
122 __ or_(eax, 1 << CPUID); | 124 __ or_(eax, 1 << CPUID); |
123 __ mov(edx, Operand(ecx)); | 125 __ mov(edx, ecx); |
124 | 126 |
125 // Done. | 127 // Done. |
126 __ bind(&done); | 128 __ bind(&done); |
127 __ mov(esp, Operand(ebp)); | 129 __ mov(esp, ebp); |
128 __ pop(ebx); | 130 __ pop(ebx); |
129 __ pop(ecx); | 131 __ pop(ecx); |
130 __ popfd(); | 132 __ popfd(); |
131 __ pop(ebp); | 133 __ pop(ebp); |
132 __ ret(0); | 134 __ ret(0); |
133 #undef __ | 135 #undef __ |
134 | 136 |
135 typedef uint64_t (*F0)(); | 137 typedef uint64_t (*F0)(); |
136 F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address())); | 138 F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address())); |
137 supported_ = probe(); | 139 supported_ = probe(); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 set_sib(scale, index, ebp); | 281 set_sib(scale, index, ebp); |
280 set_dispr(disp, rmode); | 282 set_dispr(disp, rmode); |
281 } | 283 } |
282 | 284 |
283 | 285 |
284 bool Operand::is_reg(Register reg) const { | 286 bool Operand::is_reg(Register reg) const { |
285 return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only. | 287 return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only. |
286 && ((buf_[0] & 0x07) == reg.code()); // register codes match. | 288 && ((buf_[0] & 0x07) == reg.code()); // register codes match. |
287 } | 289 } |
288 | 290 |
| 291 |
| 292 bool Operand::is_reg_only() const { |
| 293 return (buf_[0] & 0xF8) == 0xC0; // Addressing mode is register only. |
| 294 } |
| 295 |
| 296 |
| 297 Register Operand::reg() const { |
| 298 ASSERT(is_reg_only()); |
| 299 return Register::from_code(buf_[0] & 0x07); |
| 300 } |
| 301 |
| 302 |
289 // ----------------------------------------------------------------------------- | 303 // ----------------------------------------------------------------------------- |
290 // Implementation of Assembler. | 304 // Implementation of Assembler. |
291 | 305 |
292 // Emit a single byte. Must always be inlined. | 306 // Emit a single byte. Must always be inlined. |
293 #define EMIT(x) \ | 307 #define EMIT(x) \ |
294 *pc_++ = (x) | 308 *pc_++ = (x) |
295 | 309 |
296 | 310 |
297 #ifdef GENERATED_CODE_COVERAGE | 311 #ifdef GENERATED_CODE_COVERAGE |
298 static void InitCoverageLog(); | 312 static void InitCoverageLog(); |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 } | 708 } |
695 | 709 |
696 | 710 |
697 void Assembler::add(Register dst, const Operand& src) { | 711 void Assembler::add(Register dst, const Operand& src) { |
698 EnsureSpace ensure_space(this); | 712 EnsureSpace ensure_space(this); |
699 EMIT(0x03); | 713 EMIT(0x03); |
700 emit_operand(dst, src); | 714 emit_operand(dst, src); |
701 } | 715 } |
702 | 716 |
703 | 717 |
| 718 void Assembler::add(const Operand& dst, Register src) { |
| 719 EnsureSpace ensure_space(this); |
| 720 EMIT(0x01); |
| 721 emit_operand(src, dst); |
| 722 } |
| 723 |
| 724 |
704 void Assembler::add(const Operand& dst, const Immediate& x) { | 725 void Assembler::add(const Operand& dst, const Immediate& x) { |
705 ASSERT(reloc_info_writer.last_pc() != NULL); | 726 ASSERT(reloc_info_writer.last_pc() != NULL); |
706 EnsureSpace ensure_space(this); | 727 EnsureSpace ensure_space(this); |
707 emit_arith(0, dst, x); | 728 emit_arith(0, dst, x); |
708 } | 729 } |
709 | 730 |
710 | 731 |
711 void Assembler::and_(Register dst, int32_t imm32) { | 732 void Assembler::and_(Register dst, int32_t imm32) { |
712 and_(dst, Immediate(imm32)); | 733 and_(dst, Immediate(imm32)); |
713 } | 734 } |
(...skipping 20 matching lines...) Expand all Loading... |
734 | 755 |
735 void Assembler::and_(const Operand& dst, Register src) { | 756 void Assembler::and_(const Operand& dst, Register src) { |
736 EnsureSpace ensure_space(this); | 757 EnsureSpace ensure_space(this); |
737 EMIT(0x21); | 758 EMIT(0x21); |
738 emit_operand(src, dst); | 759 emit_operand(src, dst); |
739 } | 760 } |
740 | 761 |
741 | 762 |
742 void Assembler::cmpb(const Operand& op, int8_t imm8) { | 763 void Assembler::cmpb(const Operand& op, int8_t imm8) { |
743 EnsureSpace ensure_space(this); | 764 EnsureSpace ensure_space(this); |
744 EMIT(0x80); | 765 if (op.is_reg(eax)) { |
745 emit_operand(edi, op); // edi == 7 | 766 EMIT(0x3C); |
| 767 } else { |
| 768 EMIT(0x80); |
| 769 emit_operand(edi, op); // edi == 7 |
| 770 } |
746 EMIT(imm8); | 771 EMIT(imm8); |
747 } | 772 } |
748 | 773 |
749 | 774 |
750 void Assembler::cmpb(const Operand& dst, Register src) { | 775 void Assembler::cmpb(const Operand& op, Register reg) { |
751 ASSERT(src.is_byte_register()); | 776 ASSERT(reg.is_byte_register()); |
752 EnsureSpace ensure_space(this); | 777 EnsureSpace ensure_space(this); |
753 EMIT(0x38); | 778 EMIT(0x38); |
754 emit_operand(src, dst); | 779 emit_operand(reg, op); |
755 } | 780 } |
756 | 781 |
757 | 782 |
758 void Assembler::cmpb(Register dst, const Operand& src) { | 783 void Assembler::cmpb(Register reg, const Operand& op) { |
759 ASSERT(dst.is_byte_register()); | 784 ASSERT(reg.is_byte_register()); |
760 EnsureSpace ensure_space(this); | 785 EnsureSpace ensure_space(this); |
761 EMIT(0x3A); | 786 EMIT(0x3A); |
762 emit_operand(dst, src); | 787 emit_operand(reg, op); |
763 } | 788 } |
764 | 789 |
765 | 790 |
766 void Assembler::cmpw(const Operand& op, Immediate imm16) { | 791 void Assembler::cmpw(const Operand& op, Immediate imm16) { |
767 ASSERT(imm16.is_int16()); | 792 ASSERT(imm16.is_int16()); |
768 EnsureSpace ensure_space(this); | 793 EnsureSpace ensure_space(this); |
769 EMIT(0x66); | 794 EMIT(0x66); |
770 EMIT(0x81); | 795 EMIT(0x81); |
771 emit_operand(edi, op); | 796 emit_operand(edi, op); |
772 emit_w(imm16); | 797 emit_w(imm16); |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1062 } | 1087 } |
1063 | 1088 |
1064 | 1089 |
1065 void Assembler::shr_cl(Register dst) { | 1090 void Assembler::shr_cl(Register dst) { |
1066 EnsureSpace ensure_space(this); | 1091 EnsureSpace ensure_space(this); |
1067 EMIT(0xD3); | 1092 EMIT(0xD3); |
1068 EMIT(0xE8 | dst.code()); | 1093 EMIT(0xE8 | dst.code()); |
1069 } | 1094 } |
1070 | 1095 |
1071 | 1096 |
1072 void Assembler::subb(const Operand& op, int8_t imm8) { | |
1073 EnsureSpace ensure_space(this); | |
1074 if (op.is_reg(eax)) { | |
1075 EMIT(0x2c); | |
1076 } else { | |
1077 EMIT(0x80); | |
1078 emit_operand(ebp, op); // ebp == 5 | |
1079 } | |
1080 EMIT(imm8); | |
1081 } | |
1082 | |
1083 | |
1084 void Assembler::sub(const Operand& dst, const Immediate& x) { | 1097 void Assembler::sub(const Operand& dst, const Immediate& x) { |
1085 EnsureSpace ensure_space(this); | 1098 EnsureSpace ensure_space(this); |
1086 emit_arith(5, dst, x); | 1099 emit_arith(5, dst, x); |
1087 } | 1100 } |
1088 | 1101 |
1089 | 1102 |
1090 void Assembler::sub(Register dst, const Operand& src) { | 1103 void Assembler::sub(Register dst, const Operand& src) { |
1091 EnsureSpace ensure_space(this); | 1104 EnsureSpace ensure_space(this); |
1092 EMIT(0x2B); | 1105 EMIT(0x2B); |
1093 emit_operand(dst, src); | 1106 emit_operand(dst, src); |
1094 } | 1107 } |
1095 | 1108 |
1096 | 1109 |
1097 void Assembler::subb(Register dst, const Operand& src) { | |
1098 ASSERT(dst.code() < 4); | |
1099 EnsureSpace ensure_space(this); | |
1100 EMIT(0x2A); | |
1101 emit_operand(dst, src); | |
1102 } | |
1103 | |
1104 | |
1105 void Assembler::sub(const Operand& dst, Register src) { | 1110 void Assembler::sub(const Operand& dst, Register src) { |
1106 EnsureSpace ensure_space(this); | 1111 EnsureSpace ensure_space(this); |
1107 EMIT(0x29); | 1112 EMIT(0x29); |
1108 emit_operand(src, dst); | 1113 emit_operand(src, dst); |
1109 } | 1114 } |
1110 | 1115 |
1111 | 1116 |
1112 void Assembler::test(Register reg, const Immediate& imm) { | 1117 void Assembler::test(Register reg, const Immediate& imm) { |
1113 EnsureSpace ensure_space(this); | 1118 EnsureSpace ensure_space(this); |
1114 // Only use test against byte for registers that have a byte | 1119 // Only use test against byte for registers that have a byte |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1151 | 1156 |
1152 void Assembler::test(const Operand& op, const Immediate& imm) { | 1157 void Assembler::test(const Operand& op, const Immediate& imm) { |
1153 EnsureSpace ensure_space(this); | 1158 EnsureSpace ensure_space(this); |
1154 EMIT(0xF7); | 1159 EMIT(0xF7); |
1155 emit_operand(eax, op); | 1160 emit_operand(eax, op); |
1156 emit(imm); | 1161 emit(imm); |
1157 } | 1162 } |
1158 | 1163 |
1159 | 1164 |
1160 void Assembler::test_b(const Operand& op, uint8_t imm8) { | 1165 void Assembler::test_b(const Operand& op, uint8_t imm8) { |
| 1166 if (op.is_reg_only() && op.reg().code() >= 4) { |
| 1167 test(op, Immediate(imm8)); |
| 1168 return; |
| 1169 } |
1161 EnsureSpace ensure_space(this); | 1170 EnsureSpace ensure_space(this); |
1162 EMIT(0xF6); | 1171 EMIT(0xF6); |
1163 emit_operand(eax, op); | 1172 emit_operand(eax, op); |
1164 EMIT(imm8); | 1173 EMIT(imm8); |
1165 } | 1174 } |
1166 | 1175 |
1167 | 1176 |
1168 void Assembler::xor_(Register dst, int32_t imm32) { | 1177 void Assembler::xor_(Register dst, int32_t imm32) { |
1169 EnsureSpace ensure_space(this); | 1178 EnsureSpace ensure_space(this); |
1170 emit_arith(6, Operand(dst), Immediate(imm32)); | 1179 emit_arith(6, Operand(dst), Immediate(imm32)); |
1171 } | 1180 } |
1172 | 1181 |
1173 | 1182 |
1174 void Assembler::xor_(Register dst, const Operand& src) { | 1183 void Assembler::xor_(Register dst, const Operand& src) { |
1175 EnsureSpace ensure_space(this); | 1184 EnsureSpace ensure_space(this); |
1176 EMIT(0x33); | 1185 EMIT(0x33); |
1177 emit_operand(dst, src); | 1186 emit_operand(dst, src); |
1178 } | 1187 } |
1179 | 1188 |
1180 | 1189 |
1181 void Assembler::xor_(const Operand& src, Register dst) { | 1190 void Assembler::xor_(const Operand& dst, Register src) { |
1182 EnsureSpace ensure_space(this); | 1191 EnsureSpace ensure_space(this); |
1183 EMIT(0x31); | 1192 EMIT(0x31); |
1184 emit_operand(dst, src); | 1193 emit_operand(src, dst); |
1185 } | 1194 } |
1186 | 1195 |
1187 | 1196 |
1188 void Assembler::xor_(const Operand& dst, const Immediate& x) { | 1197 void Assembler::xor_(const Operand& dst, const Immediate& x) { |
1189 EnsureSpace ensure_space(this); | 1198 EnsureSpace ensure_space(this); |
1190 emit_arith(6, dst, x); | 1199 emit_arith(6, dst, x); |
1191 } | 1200 } |
1192 | 1201 |
1193 | 1202 |
1194 void Assembler::bt(const Operand& dst, Register src) { | 1203 void Assembler::bt(const Operand& dst, Register src) { |
(...skipping 1269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2464 if (rmode == RelocInfo::EXTERNAL_REFERENCE) { | 2473 if (rmode == RelocInfo::EXTERNAL_REFERENCE) { |
2465 #ifdef DEBUG | 2474 #ifdef DEBUG |
2466 if (!Serializer::enabled()) { | 2475 if (!Serializer::enabled()) { |
2467 Serializer::TooLateToEnableNow(); | 2476 Serializer::TooLateToEnableNow(); |
2468 } | 2477 } |
2469 #endif | 2478 #endif |
2470 if (!Serializer::enabled() && !emit_debug_code()) { | 2479 if (!Serializer::enabled() && !emit_debug_code()) { |
2471 return; | 2480 return; |
2472 } | 2481 } |
2473 } | 2482 } |
2474 RelocInfo rinfo(pc_, rmode, data); | 2483 RelocInfo rinfo(pc_, rmode, data, NULL); |
2475 reloc_info_writer.Write(&rinfo); | 2484 reloc_info_writer.Write(&rinfo); |
2476 } | 2485 } |
2477 | 2486 |
2478 | 2487 |
2479 #ifdef GENERATED_CODE_COVERAGE | 2488 #ifdef GENERATED_CODE_COVERAGE |
2480 static FILE* coverage_log = NULL; | 2489 static FILE* coverage_log = NULL; |
2481 | 2490 |
2482 | 2491 |
2483 static void InitCoverageLog() { | 2492 static void InitCoverageLog() { |
2484 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); | 2493 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); |
(...skipping 12 matching lines...) Expand all Loading... |
2497 fprintf(coverage_log, "%s\n", file_line); | 2506 fprintf(coverage_log, "%s\n", file_line); |
2498 fflush(coverage_log); | 2507 fflush(coverage_log); |
2499 } | 2508 } |
2500 } | 2509 } |
2501 | 2510 |
2502 #endif | 2511 #endif |
2503 | 2512 |
2504 } } // namespace v8::internal | 2513 } } // namespace v8::internal |
2505 | 2514 |
2506 #endif // V8_TARGET_ARCH_IA32 | 2515 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |