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 846 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 __ testl(EAX, Immediate(kSmiTagMask)); | 857 __ testl(EAX, Immediate(kSmiTagMask)); |
858 __ j(ZERO, &smi_to_double); | 858 __ j(ZERO, &smi_to_double); |
859 __ CompareClassId(EAX, kDoubleCid, EBX); | 859 __ CompareClassId(EAX, kDoubleCid, EBX); |
860 __ j(NOT_EQUAL, &call_method); | 860 __ j(NOT_EQUAL, &call_method); |
861 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); | 861 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); |
862 __ Bind(&double_op); | 862 __ Bind(&double_op); |
863 __ sqrtsd(XMM0, XMM1); | 863 __ sqrtsd(XMM0, XMM1); |
864 AssemblerMacros::TryAllocate(assembler_, | 864 AssemblerMacros::TryAllocate(assembler_, |
865 double_class_, | 865 double_class_, |
866 &call_method, | 866 &call_method, |
| 867 Assembler::kNearJump, |
867 EAX); // Result register. | 868 EAX); // Result register. |
868 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); | 869 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); |
869 __ Drop(1); | 870 __ Drop(1); |
870 __ jmp(done); | 871 __ jmp(done); |
871 __ Bind(&smi_to_double); | 872 __ Bind(&smi_to_double); |
872 __ SmiUntag(EAX); | 873 __ SmiUntag(EAX); |
873 __ cvtsi2sd(XMM1, EAX); | 874 __ cvtsi2sd(XMM1, EAX); |
874 __ jmp(&double_op); | 875 __ jmp(&double_op); |
875 __ Bind(&call_method); | 876 __ Bind(&call_method); |
876 } | 877 } |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1079 __ movsd(result, FieldAddress(reg, Double::value_offset())); | 1080 __ movsd(result, FieldAddress(reg, Double::value_offset())); |
1080 __ jmp(&done); | 1081 __ jmp(&done); |
1081 __ Bind(&is_smi); | 1082 __ Bind(&is_smi); |
1082 __ movl(temp, reg); | 1083 __ movl(temp, reg); |
1083 __ SmiUntag(temp); | 1084 __ SmiUntag(temp); |
1084 __ cvtsi2sd(result, temp); | 1085 __ cvtsi2sd(result, temp); |
1085 __ Bind(&done); | 1086 __ Bind(&done); |
1086 } | 1087 } |
1087 | 1088 |
1088 | 1089 |
| 1090 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { |
| 1091 // TODO(vegorov): consider saving only caller save (volatile) registers. |
| 1092 const intptr_t xmm_regs_count = locs->live_registers()->xmm_regs_count(); |
| 1093 if (xmm_regs_count > 0) { |
| 1094 intptr_t stack_offs = (StackSize() + 1) * kWordSize; |
| 1095 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
| 1096 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
| 1097 if (locs->live_registers()->ContainsXmmRegister(xmm_reg)) { |
| 1098 __ movsd(Address(EBP, -stack_offs), xmm_reg); |
| 1099 stack_offs += kDoubleSize; |
| 1100 } |
| 1101 } |
| 1102 } |
| 1103 |
| 1104 for (intptr_t reg_idx = 0; reg_idx < kNumberOfCpuRegisters; ++reg_idx) { |
| 1105 Register reg = static_cast<Register>(reg_idx); |
| 1106 if (locs->live_registers()->ContainsRegister(reg)) { |
| 1107 __ pushl(reg); |
| 1108 } |
| 1109 } |
| 1110 } |
| 1111 |
| 1112 |
| 1113 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) { |
| 1114 for (intptr_t reg_idx = kNumberOfCpuRegisters - 1; reg_idx >= 0; --reg_idx) { |
| 1115 Register reg = static_cast<Register>(reg_idx); |
| 1116 if (locs->live_registers()->ContainsRegister(reg)) { |
| 1117 __ popl(reg); |
| 1118 } |
| 1119 } |
| 1120 |
| 1121 const intptr_t xmm_regs_count = locs->live_registers()->xmm_regs_count(); |
| 1122 if (xmm_regs_count > 0) { |
| 1123 intptr_t stack_offs = (StackSize() + 1) * kWordSize; |
| 1124 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
| 1125 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
| 1126 if (locs->live_registers()->ContainsXmmRegister(xmm_reg)) { |
| 1127 __ movsd(xmm_reg, Address(EBP, -stack_offs)); |
| 1128 stack_offs += kDoubleSize; |
| 1129 } |
| 1130 } |
| 1131 } |
| 1132 } |
| 1133 |
| 1134 |
1089 #undef __ | 1135 #undef __ |
1090 #define __ compiler_->assembler()-> | 1136 #define __ compiler_->assembler()-> |
1091 | 1137 |
1092 | 1138 |
1093 static Address ToStackSlotAddress(Location loc) { | 1139 static Address ToStackSlotAddress(Location loc) { |
1094 ASSERT(loc.IsStackSlot()); | |
1095 const intptr_t index = loc.stack_index(); | 1140 const intptr_t index = loc.stack_index(); |
1096 if (index < 0) { | 1141 if (index < 0) { |
1097 const intptr_t offset = (1 - index) * kWordSize; | 1142 const intptr_t offset = (1 - index) * kWordSize; |
1098 return Address(EBP, offset); | 1143 return Address(EBP, offset); |
1099 } else { | 1144 } else { |
1100 const intptr_t offset = | 1145 const intptr_t offset = |
1101 (ParsedFunction::kFirstLocalSlotIndex - index) * kWordSize; | 1146 (ParsedFunction::kFirstLocalSlotIndex - index) * kWordSize; |
1102 return Address(EBP, offset); | 1147 return Address(EBP, offset); |
1103 } | 1148 } |
1104 } | 1149 } |
(...skipping 12 matching lines...) Expand all Loading... |
1117 __ movl(ToStackSlotAddress(destination), source.reg()); | 1162 __ movl(ToStackSlotAddress(destination), source.reg()); |
1118 } | 1163 } |
1119 } else if (source.IsStackSlot()) { | 1164 } else if (source.IsStackSlot()) { |
1120 if (destination.IsRegister()) { | 1165 if (destination.IsRegister()) { |
1121 __ movl(destination.reg(), ToStackSlotAddress(source)); | 1166 __ movl(destination.reg(), ToStackSlotAddress(source)); |
1122 } else { | 1167 } else { |
1123 ASSERT(destination.IsStackSlot()); | 1168 ASSERT(destination.IsStackSlot()); |
1124 MoveMemoryToMemory(ToStackSlotAddress(destination), | 1169 MoveMemoryToMemory(ToStackSlotAddress(destination), |
1125 ToStackSlotAddress(source)); | 1170 ToStackSlotAddress(source)); |
1126 } | 1171 } |
| 1172 } else if (source.IsXmmRegister()) { |
| 1173 if (destination.IsXmmRegister()) { |
| 1174 // Optimization manual recommends using MOVAPS for register |
| 1175 // to register moves. |
| 1176 __ movaps(destination.xmm_reg(), source.xmm_reg()); |
| 1177 } else { |
| 1178 ASSERT(destination.IsDoubleStackSlot()); |
| 1179 __ movsd(ToStackSlotAddress(destination), source.xmm_reg()); |
| 1180 } |
| 1181 } else if (source.IsDoubleStackSlot()) { |
| 1182 if (destination.IsXmmRegister()) { |
| 1183 __ movsd(destination.xmm_reg(), ToStackSlotAddress(source)); |
| 1184 } else { |
| 1185 ASSERT(destination.IsDoubleStackSlot()); |
| 1186 __ movsd(XMM0, ToStackSlotAddress(source)); |
| 1187 __ movsd(ToStackSlotAddress(destination), XMM0); |
| 1188 } |
1127 } else { | 1189 } else { |
1128 ASSERT(source.IsConstant()); | 1190 ASSERT(source.IsConstant()); |
1129 if (destination.IsRegister()) { | 1191 if (destination.IsRegister()) { |
1130 __ LoadObject(destination.reg(), source.constant()); | 1192 __ LoadObject(destination.reg(), source.constant()); |
1131 } else { | 1193 } else { |
1132 ASSERT(destination.IsStackSlot()); | 1194 ASSERT(destination.IsStackSlot()); |
1133 StoreObject(ToStackSlotAddress(destination), source.constant()); | 1195 StoreObject(ToStackSlotAddress(destination), source.constant()); |
1134 } | 1196 } |
1135 } | 1197 } |
1136 | 1198 |
1137 move->Eliminate(); | 1199 move->Eliminate(); |
1138 } | 1200 } |
1139 | 1201 |
1140 | 1202 |
1141 void ParallelMoveResolver::EmitSwap(int index) { | 1203 void ParallelMoveResolver::EmitSwap(int index) { |
1142 MoveOperands* move = moves_[index]; | 1204 MoveOperands* move = moves_[index]; |
1143 const Location source = move->src(); | 1205 const Location source = move->src(); |
1144 const Location destination = move->dest(); | 1206 const Location destination = move->dest(); |
1145 | 1207 |
1146 if (source.IsRegister() && destination.IsRegister()) { | 1208 if (source.IsRegister() && destination.IsRegister()) { |
1147 __ xchgl(destination.reg(), source.reg()); | 1209 __ xchgl(destination.reg(), source.reg()); |
1148 } else if (source.IsRegister() && destination.IsStackSlot()) { | 1210 } else if (source.IsRegister() && destination.IsStackSlot()) { |
1149 Exchange(source.reg(), ToStackSlotAddress(destination)); | 1211 Exchange(source.reg(), ToStackSlotAddress(destination)); |
1150 } else if (source.IsStackSlot() && destination.IsRegister()) { | 1212 } else if (source.IsStackSlot() && destination.IsRegister()) { |
1151 Exchange(destination.reg(), ToStackSlotAddress(source)); | 1213 Exchange(destination.reg(), ToStackSlotAddress(source)); |
1152 } else if (source.IsStackSlot() && destination.IsStackSlot()) { | 1214 } else if (source.IsStackSlot() && destination.IsStackSlot()) { |
1153 Exchange(ToStackSlotAddress(destination), ToStackSlotAddress(source)); | 1215 Exchange(ToStackSlotAddress(destination), ToStackSlotAddress(source)); |
| 1216 } else if (source.IsXmmRegister() && destination.IsXmmRegister()) { |
| 1217 __ movaps(XMM0, source.xmm_reg()); |
| 1218 __ movaps(source.xmm_reg(), destination.xmm_reg()); |
| 1219 __ movaps(destination.xmm_reg(), XMM0); |
| 1220 } else if (source.IsXmmRegister() || destination.IsXmmRegister()) { |
| 1221 ASSERT(destination.IsDoubleStackSlot() || source.IsDoubleStackSlot()); |
| 1222 XmmRegister reg = source.IsXmmRegister() ? source.xmm_reg() |
| 1223 : destination.xmm_reg(); |
| 1224 Address slot_address = |
| 1225 ToStackSlotAddress(source.IsXmmRegister() ? destination : source); |
| 1226 |
| 1227 __ movsd(XMM0, slot_address); |
| 1228 __ movsd(slot_address, reg); |
| 1229 __ movaps(reg, XMM0); |
1154 } else { | 1230 } else { |
1155 UNREACHABLE(); | 1231 UNREACHABLE(); |
1156 } | 1232 } |
1157 | 1233 |
1158 // The swap of source and destination has executed a move from source to | 1234 // The swap of source and destination has executed a move from source to |
1159 // destination. | 1235 // destination. |
1160 move->Eliminate(); | 1236 move->Eliminate(); |
1161 | 1237 |
1162 // Any unperformed (including pending) move with a source of either | 1238 // Any unperformed (including pending) move with a source of either |
1163 // this move's source or destination needs to have their source | 1239 // this move's source or destination needs to have their source |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1214 __ popl(ECX); | 1290 __ popl(ECX); |
1215 __ popl(EAX); | 1291 __ popl(EAX); |
1216 } | 1292 } |
1217 | 1293 |
1218 | 1294 |
1219 #undef __ | 1295 #undef __ |
1220 | 1296 |
1221 } // namespace dart | 1297 } // namespace dart |
1222 | 1298 |
1223 #endif // defined TARGET_ARCH_IA32 | 1299 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |