OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
9 | 9 |
10 #include "lib/error.h" | 10 #include "lib/error.h" |
(...skipping 862 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
873 __ testl(EAX, Immediate(kSmiTagMask)); | 873 __ testl(EAX, Immediate(kSmiTagMask)); |
874 __ j(ZERO, &smi_to_double); | 874 __ j(ZERO, &smi_to_double); |
875 __ CompareClassId(EAX, kDoubleCid, EBX); | 875 __ CompareClassId(EAX, kDoubleCid, EBX); |
876 __ j(NOT_EQUAL, &call_method); | 876 __ j(NOT_EQUAL, &call_method); |
877 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); | 877 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); |
878 __ Bind(&double_op); | 878 __ Bind(&double_op); |
879 __ sqrtsd(XMM0, XMM1); | 879 __ sqrtsd(XMM0, XMM1); |
880 AssemblerMacros::TryAllocate(assembler_, | 880 AssemblerMacros::TryAllocate(assembler_, |
881 double_class_, | 881 double_class_, |
882 &call_method, | 882 &call_method, |
| 883 Assembler::kNearJump, |
883 EAX); // Result register. | 884 EAX); // Result register. |
884 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); | 885 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); |
885 __ Drop(1); | 886 __ Drop(1); |
886 __ jmp(done); | 887 __ jmp(done); |
887 __ Bind(&smi_to_double); | 888 __ Bind(&smi_to_double); |
888 __ SmiUntag(EAX); | 889 __ SmiUntag(EAX); |
889 __ cvtsi2sd(XMM1, EAX); | 890 __ cvtsi2sd(XMM1, EAX); |
890 __ jmp(&double_op); | 891 __ jmp(&double_op); |
891 __ Bind(&call_method); | 892 __ Bind(&call_method); |
892 } | 893 } |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1099 __ movsd(result, FieldAddress(reg, Double::value_offset())); | 1100 __ movsd(result, FieldAddress(reg, Double::value_offset())); |
1100 __ jmp(&done); | 1101 __ jmp(&done); |
1101 __ Bind(&is_smi); | 1102 __ Bind(&is_smi); |
1102 __ movl(temp, reg); | 1103 __ movl(temp, reg); |
1103 __ SmiUntag(temp); | 1104 __ SmiUntag(temp); |
1104 __ cvtsi2sd(result, temp); | 1105 __ cvtsi2sd(result, temp); |
1105 __ Bind(&done); | 1106 __ Bind(&done); |
1106 } | 1107 } |
1107 | 1108 |
1108 | 1109 |
| 1110 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { |
| 1111 // TODO(vegorov): consider saving only caller save (volatile) registers. |
| 1112 const intptr_t xmm_regs_count = locs->live_registers()->xmm_regs_count(); |
| 1113 if (xmm_regs_count > 0) { |
| 1114 intptr_t stack_offs = (StackSize() + 1) * kWordSize; |
| 1115 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
| 1116 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
| 1117 if (locs->live_registers()->ContainsXmmRegister(xmm_reg)) { |
| 1118 __ movsd(Address(EBP, -stack_offs), xmm_reg); |
| 1119 stack_offs += kDoubleSize; |
| 1120 } |
| 1121 } |
| 1122 } |
| 1123 |
| 1124 for (intptr_t reg_idx = 0; reg_idx < kNumberOfCpuRegisters; ++reg_idx) { |
| 1125 Register reg = static_cast<Register>(reg_idx); |
| 1126 if (locs->live_registers()->ContainsRegister(reg)) { |
| 1127 __ pushl(reg); |
| 1128 } |
| 1129 } |
| 1130 } |
| 1131 |
| 1132 |
| 1133 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) { |
| 1134 for (intptr_t reg_idx = kNumberOfCpuRegisters - 1; reg_idx >= 0; --reg_idx) { |
| 1135 Register reg = static_cast<Register>(reg_idx); |
| 1136 if (locs->live_registers()->ContainsRegister(reg)) { |
| 1137 __ popl(reg); |
| 1138 } |
| 1139 } |
| 1140 |
| 1141 const intptr_t xmm_regs_count = locs->live_registers()->xmm_regs_count(); |
| 1142 if (xmm_regs_count > 0) { |
| 1143 intptr_t stack_offs = (StackSize() + 1) * kWordSize; |
| 1144 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
| 1145 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
| 1146 if (locs->live_registers()->ContainsXmmRegister(xmm_reg)) { |
| 1147 __ movsd(xmm_reg, Address(EBP, -stack_offs)); |
| 1148 stack_offs += kDoubleSize; |
| 1149 } |
| 1150 } |
| 1151 } |
| 1152 } |
| 1153 |
| 1154 |
1109 #undef __ | 1155 #undef __ |
1110 #define __ compiler_->assembler()-> | 1156 #define __ compiler_->assembler()-> |
1111 | 1157 |
1112 | 1158 |
1113 static Address ToStackSlotAddress(Location loc) { | 1159 static Address ToStackSlotAddress(Location loc) { |
1114 ASSERT(loc.IsStackSlot()); | |
1115 const intptr_t index = loc.stack_index(); | 1160 const intptr_t index = loc.stack_index(); |
1116 if (index < 0) { | 1161 if (index < 0) { |
1117 const intptr_t offset = (1 - index) * kWordSize; | 1162 const intptr_t offset = (1 - index) * kWordSize; |
1118 return Address(EBP, offset); | 1163 return Address(EBP, offset); |
1119 } else { | 1164 } else { |
1120 const intptr_t offset = | 1165 const intptr_t offset = |
1121 (ParsedFunction::kFirstLocalSlotIndex - index) * kWordSize; | 1166 (ParsedFunction::kFirstLocalSlotIndex - index) * kWordSize; |
1122 return Address(EBP, offset); | 1167 return Address(EBP, offset); |
1123 } | 1168 } |
1124 } | 1169 } |
(...skipping 12 matching lines...) Expand all Loading... |
1137 __ movl(ToStackSlotAddress(destination), source.reg()); | 1182 __ movl(ToStackSlotAddress(destination), source.reg()); |
1138 } | 1183 } |
1139 } else if (source.IsStackSlot()) { | 1184 } else if (source.IsStackSlot()) { |
1140 if (destination.IsRegister()) { | 1185 if (destination.IsRegister()) { |
1141 __ movl(destination.reg(), ToStackSlotAddress(source)); | 1186 __ movl(destination.reg(), ToStackSlotAddress(source)); |
1142 } else { | 1187 } else { |
1143 ASSERT(destination.IsStackSlot()); | 1188 ASSERT(destination.IsStackSlot()); |
1144 MoveMemoryToMemory(ToStackSlotAddress(destination), | 1189 MoveMemoryToMemory(ToStackSlotAddress(destination), |
1145 ToStackSlotAddress(source)); | 1190 ToStackSlotAddress(source)); |
1146 } | 1191 } |
| 1192 } else if (source.IsXmmRegister()) { |
| 1193 if (destination.IsXmmRegister()) { |
| 1194 // Optimization manual recommends using MOVAPS for register |
| 1195 // to register moves. |
| 1196 __ movaps(destination.xmm_reg(), source.xmm_reg()); |
| 1197 } else { |
| 1198 ASSERT(destination.IsDoubleStackSlot()); |
| 1199 __ movsd(ToStackSlotAddress(destination), source.xmm_reg()); |
| 1200 } |
| 1201 } else if (source.IsDoubleStackSlot()) { |
| 1202 if (destination.IsXmmRegister()) { |
| 1203 __ movsd(destination.xmm_reg(), ToStackSlotAddress(source)); |
| 1204 } else { |
| 1205 ASSERT(destination.IsDoubleStackSlot()); |
| 1206 __ movsd(XMM0, ToStackSlotAddress(source)); |
| 1207 __ movsd(ToStackSlotAddress(destination), XMM0); |
| 1208 } |
1147 } else { | 1209 } else { |
1148 ASSERT(source.IsConstant()); | 1210 ASSERT(source.IsConstant()); |
1149 if (destination.IsRegister()) { | 1211 if (destination.IsRegister()) { |
1150 __ LoadObject(destination.reg(), source.constant()); | 1212 __ LoadObject(destination.reg(), source.constant()); |
1151 } else { | 1213 } else { |
1152 ASSERT(destination.IsStackSlot()); | 1214 ASSERT(destination.IsStackSlot()); |
1153 StoreObject(ToStackSlotAddress(destination), source.constant()); | 1215 StoreObject(ToStackSlotAddress(destination), source.constant()); |
1154 } | 1216 } |
1155 } | 1217 } |
1156 | 1218 |
1157 move->Eliminate(); | 1219 move->Eliminate(); |
1158 } | 1220 } |
1159 | 1221 |
1160 | 1222 |
1161 void ParallelMoveResolver::EmitSwap(int index) { | 1223 void ParallelMoveResolver::EmitSwap(int index) { |
1162 MoveOperands* move = moves_[index]; | 1224 MoveOperands* move = moves_[index]; |
1163 const Location source = move->src(); | 1225 const Location source = move->src(); |
1164 const Location destination = move->dest(); | 1226 const Location destination = move->dest(); |
1165 | 1227 |
1166 if (source.IsRegister() && destination.IsRegister()) { | 1228 if (source.IsRegister() && destination.IsRegister()) { |
1167 __ xchgl(destination.reg(), source.reg()); | 1229 __ xchgl(destination.reg(), source.reg()); |
1168 } else if (source.IsRegister() && destination.IsStackSlot()) { | 1230 } else if (source.IsRegister() && destination.IsStackSlot()) { |
1169 Exchange(source.reg(), ToStackSlotAddress(destination)); | 1231 Exchange(source.reg(), ToStackSlotAddress(destination)); |
1170 } else if (source.IsStackSlot() && destination.IsRegister()) { | 1232 } else if (source.IsStackSlot() && destination.IsRegister()) { |
1171 Exchange(destination.reg(), ToStackSlotAddress(source)); | 1233 Exchange(destination.reg(), ToStackSlotAddress(source)); |
1172 } else if (source.IsStackSlot() && destination.IsStackSlot()) { | 1234 } else if (source.IsStackSlot() && destination.IsStackSlot()) { |
1173 Exchange(ToStackSlotAddress(destination), ToStackSlotAddress(source)); | 1235 Exchange(ToStackSlotAddress(destination), ToStackSlotAddress(source)); |
| 1236 } else if (source.IsXmmRegister() && destination.IsXmmRegister()) { |
| 1237 __ movaps(XMM0, source.xmm_reg()); |
| 1238 __ movaps(source.xmm_reg(), destination.xmm_reg()); |
| 1239 __ movaps(destination.xmm_reg(), XMM0); |
| 1240 } else if (source.IsXmmRegister() || destination.IsXmmRegister()) { |
| 1241 ASSERT(destination.IsDoubleStackSlot() || source.IsDoubleStackSlot()); |
| 1242 XmmRegister reg = source.IsXmmRegister() ? source.xmm_reg() |
| 1243 : destination.xmm_reg(); |
| 1244 Address slot_address = |
| 1245 ToStackSlotAddress(source.IsXmmRegister() ? destination : source); |
| 1246 |
| 1247 __ movsd(XMM0, slot_address); |
| 1248 __ movsd(slot_address, reg); |
| 1249 __ movaps(reg, XMM0); |
1174 } else { | 1250 } else { |
1175 UNREACHABLE(); | 1251 UNREACHABLE(); |
1176 } | 1252 } |
1177 | 1253 |
1178 // The swap of source and destination has executed a move from source to | 1254 // The swap of source and destination has executed a move from source to |
1179 // destination. | 1255 // destination. |
1180 move->Eliminate(); | 1256 move->Eliminate(); |
1181 | 1257 |
1182 // Any unperformed (including pending) move with a source of either | 1258 // Any unperformed (including pending) move with a source of either |
1183 // this move's source or destination needs to have their source | 1259 // this move's source or destination needs to have their source |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1234 __ popl(ECX); | 1310 __ popl(ECX); |
1235 __ popl(EAX); | 1311 __ popl(EAX); |
1236 } | 1312 } |
1237 | 1313 |
1238 | 1314 |
1239 #undef __ | 1315 #undef __ |
1240 | 1316 |
1241 } // namespace dart | 1317 } // namespace dart |
1242 | 1318 |
1243 #endif // defined TARGET_ARCH_IA32 | 1319 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |