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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
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 867 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
878 __ testq(RAX, Immediate(kSmiTagMask)); | 878 __ testq(RAX, Immediate(kSmiTagMask)); |
879 __ j(ZERO, &smi_to_double); | 879 __ j(ZERO, &smi_to_double); |
880 __ CompareClassId(RAX, kDoubleCid); | 880 __ CompareClassId(RAX, kDoubleCid); |
881 __ j(NOT_EQUAL, &call_method); | 881 __ j(NOT_EQUAL, &call_method); |
882 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); | 882 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); |
883 __ Bind(&double_op); | 883 __ Bind(&double_op); |
884 __ sqrtsd(XMM0, XMM1); | 884 __ sqrtsd(XMM0, XMM1); |
885 AssemblerMacros::TryAllocate(assembler_, | 885 AssemblerMacros::TryAllocate(assembler_, |
886 double_class_, | 886 double_class_, |
887 &call_method, | 887 &call_method, |
| 888 Assembler::kNearJump, |
888 RAX); // Result register. | 889 RAX); // Result register. |
889 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); | 890 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); |
890 __ Drop(1); | 891 __ Drop(1); |
891 __ jmp(done); | 892 __ jmp(done); |
892 __ Bind(&smi_to_double); | 893 __ Bind(&smi_to_double); |
893 __ SmiUntag(RAX); | 894 __ SmiUntag(RAX); |
894 __ cvtsi2sd(XMM1, RAX); | 895 __ cvtsi2sd(XMM1, RAX); |
895 __ jmp(&double_op); | 896 __ jmp(&double_op); |
896 __ Bind(&call_method); | 897 __ Bind(&call_method); |
897 } | 898 } |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1107 __ movsd(result, FieldAddress(reg, Double::value_offset())); | 1108 __ movsd(result, FieldAddress(reg, Double::value_offset())); |
1108 __ jmp(&done); | 1109 __ jmp(&done); |
1109 __ Bind(&is_smi); | 1110 __ Bind(&is_smi); |
1110 __ movq(temp, reg); | 1111 __ movq(temp, reg); |
1111 __ SmiUntag(temp); | 1112 __ SmiUntag(temp); |
1112 __ cvtsi2sd(result, temp); | 1113 __ cvtsi2sd(result, temp); |
1113 __ Bind(&done); | 1114 __ Bind(&done); |
1114 } | 1115 } |
1115 | 1116 |
1116 | 1117 |
| 1118 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { |
| 1119 // TODO(vegorov): consider saving only caller save (volatile) registers. |
| 1120 const intptr_t xmm_regs_count = locs->live_registers()->xmm_regs_count(); |
| 1121 if (xmm_regs_count > 0) { |
| 1122 // Pointer maps don't support pushed untagged values so we reserve spill |
| 1123 // slots at the top of the spill slot area for live XMM registers. |
| 1124 intptr_t stack_offs = (StackSize() + 1) * kWordSize; |
| 1125 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
| 1126 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
| 1127 if (locs->live_registers()->ContainsXmmRegister(xmm_reg)) { |
| 1128 __ movsd(Address(RBP, -stack_offs), xmm_reg); |
| 1129 stack_offs += kDoubleSize; |
| 1130 } |
| 1131 } |
| 1132 } |
| 1133 |
| 1134 for (intptr_t reg_idx = 0; reg_idx < kNumberOfCpuRegisters; ++reg_idx) { |
| 1135 Register reg = static_cast<Register>(reg_idx); |
| 1136 if (locs->live_registers()->ContainsRegister(reg)) { |
| 1137 __ pushq(reg); |
| 1138 } |
| 1139 } |
| 1140 } |
| 1141 |
| 1142 |
| 1143 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) { |
| 1144 for (intptr_t reg_idx = kNumberOfCpuRegisters - 1; reg_idx >= 0; --reg_idx) { |
| 1145 Register reg = static_cast<Register>(reg_idx); |
| 1146 if (locs->live_registers()->ContainsRegister(reg)) { |
| 1147 __ popq(reg); |
| 1148 } |
| 1149 } |
| 1150 |
| 1151 const intptr_t xmm_regs_count = locs->live_registers()->xmm_regs_count(); |
| 1152 if (xmm_regs_count > 0) { |
| 1153 // Pointer maps don't support pushed untagged values so we reserve spill |
| 1154 // slots at the top of the spill slot area for live XMM registers. |
| 1155 intptr_t stack_offs = (StackSize() + 1) * kWordSize; |
| 1156 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
| 1157 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
| 1158 if (locs->live_registers()->ContainsXmmRegister(xmm_reg)) { |
| 1159 __ movsd(xmm_reg, Address(RBP, -stack_offs)); |
| 1160 stack_offs += kDoubleSize; |
| 1161 } |
| 1162 } |
| 1163 } |
| 1164 } |
| 1165 |
| 1166 |
1117 #undef __ | 1167 #undef __ |
1118 #define __ compiler_->assembler()-> | 1168 #define __ compiler_->assembler()-> |
1119 | 1169 |
1120 | 1170 |
1121 static Address ToStackSlotAddress(Location loc) { | 1171 static Address ToStackSlotAddress(Location loc) { |
1122 ASSERT(loc.IsStackSlot()); | |
1123 const intptr_t index = loc.stack_index(); | 1172 const intptr_t index = loc.stack_index(); |
1124 if (index < 0) { | 1173 if (index < 0) { |
1125 const intptr_t offset = (1 - index) * kWordSize; | 1174 const intptr_t offset = (1 - index) * kWordSize; |
1126 return Address(RBP, offset); | 1175 return Address(RBP, offset); |
1127 } else { | 1176 } else { |
1128 const intptr_t offset = | 1177 const intptr_t offset = |
1129 (ParsedFunction::kFirstLocalSlotIndex - index) * kWordSize; | 1178 (ParsedFunction::kFirstLocalSlotIndex - index) * kWordSize; |
1130 return Address(RBP, offset); | 1179 return Address(RBP, offset); |
1131 } | 1180 } |
1132 } | 1181 } |
(...skipping 12 matching lines...) Expand all Loading... |
1145 __ movq(ToStackSlotAddress(destination), source.reg()); | 1194 __ movq(ToStackSlotAddress(destination), source.reg()); |
1146 } | 1195 } |
1147 } else if (source.IsStackSlot()) { | 1196 } else if (source.IsStackSlot()) { |
1148 if (destination.IsRegister()) { | 1197 if (destination.IsRegister()) { |
1149 __ movq(destination.reg(), ToStackSlotAddress(source)); | 1198 __ movq(destination.reg(), ToStackSlotAddress(source)); |
1150 } else { | 1199 } else { |
1151 ASSERT(destination.IsStackSlot()); | 1200 ASSERT(destination.IsStackSlot()); |
1152 MoveMemoryToMemory(ToStackSlotAddress(destination), | 1201 MoveMemoryToMemory(ToStackSlotAddress(destination), |
1153 ToStackSlotAddress(source)); | 1202 ToStackSlotAddress(source)); |
1154 } | 1203 } |
| 1204 } else if (source.IsXmmRegister()) { |
| 1205 if (destination.IsXmmRegister()) { |
| 1206 // Optimization manual recommends using MOVAPS for register |
| 1207 // to register moves. |
| 1208 __ movaps(destination.xmm_reg(), source.xmm_reg()); |
| 1209 } else { |
| 1210 ASSERT(destination.IsDoubleStackSlot()); |
| 1211 __ movsd(ToStackSlotAddress(destination), source.xmm_reg()); |
| 1212 } |
| 1213 } else if (source.IsDoubleStackSlot()) { |
| 1214 if (destination.IsXmmRegister()) { |
| 1215 __ movsd(destination.xmm_reg(), ToStackSlotAddress(source)); |
| 1216 } else { |
| 1217 ASSERT(destination.IsDoubleStackSlot()); |
| 1218 __ movsd(XMM0, ToStackSlotAddress(source)); |
| 1219 __ movsd(ToStackSlotAddress(destination), XMM0); |
| 1220 } |
1155 } else { | 1221 } else { |
1156 ASSERT(source.IsConstant()); | 1222 ASSERT(source.IsConstant()); |
1157 if (destination.IsRegister()) { | 1223 if (destination.IsRegister()) { |
1158 __ LoadObject(destination.reg(), source.constant()); | 1224 __ LoadObject(destination.reg(), source.constant()); |
1159 } else { | 1225 } else { |
1160 ASSERT(destination.IsStackSlot()); | 1226 ASSERT(destination.IsStackSlot()); |
1161 StoreObject(ToStackSlotAddress(destination), source.constant()); | 1227 StoreObject(ToStackSlotAddress(destination), source.constant()); |
1162 } | 1228 } |
1163 } | 1229 } |
1164 | 1230 |
1165 move->Eliminate(); | 1231 move->Eliminate(); |
1166 } | 1232 } |
1167 | 1233 |
1168 | 1234 |
1169 void ParallelMoveResolver::EmitSwap(int index) { | 1235 void ParallelMoveResolver::EmitSwap(int index) { |
1170 MoveOperands* move = moves_[index]; | 1236 MoveOperands* move = moves_[index]; |
1171 const Location source = move->src(); | 1237 const Location source = move->src(); |
1172 const Location destination = move->dest(); | 1238 const Location destination = move->dest(); |
1173 | 1239 |
1174 if (source.IsRegister() && destination.IsRegister()) { | 1240 if (source.IsRegister() && destination.IsRegister()) { |
1175 __ xchgq(destination.reg(), source.reg()); | 1241 __ xchgq(destination.reg(), source.reg()); |
1176 } else if (source.IsRegister() && destination.IsStackSlot()) { | 1242 } else if (source.IsRegister() && destination.IsStackSlot()) { |
1177 Exchange(source.reg(), ToStackSlotAddress(destination)); | 1243 Exchange(source.reg(), ToStackSlotAddress(destination)); |
1178 } else if (source.IsStackSlot() && destination.IsRegister()) { | 1244 } else if (source.IsStackSlot() && destination.IsRegister()) { |
1179 Exchange(destination.reg(), ToStackSlotAddress(source)); | 1245 Exchange(destination.reg(), ToStackSlotAddress(source)); |
1180 } else if (source.IsStackSlot() && destination.IsStackSlot()) { | 1246 } else if (source.IsStackSlot() && destination.IsStackSlot()) { |
1181 Exchange(ToStackSlotAddress(destination), ToStackSlotAddress(source)); | 1247 Exchange(ToStackSlotAddress(destination), ToStackSlotAddress(source)); |
| 1248 } else if (source.IsXmmRegister() && destination.IsXmmRegister()) { |
| 1249 __ movaps(XMM0, source.xmm_reg()); |
| 1250 __ movaps(source.xmm_reg(), destination.xmm_reg()); |
| 1251 __ movaps(destination.xmm_reg(), XMM0); |
| 1252 } else if (source.IsXmmRegister() || destination.IsXmmRegister()) { |
| 1253 ASSERT(destination.IsDoubleStackSlot() || source.IsDoubleStackSlot()); |
| 1254 XmmRegister reg = source.IsXmmRegister() ? source.xmm_reg() |
| 1255 : destination.xmm_reg(); |
| 1256 Address slot_address = |
| 1257 ToStackSlotAddress(source.IsXmmRegister() ? destination : source); |
| 1258 |
| 1259 __ movsd(XMM0, slot_address); |
| 1260 __ movsd(slot_address, reg); |
| 1261 __ movaps(reg, XMM0); |
1182 } else { | 1262 } else { |
1183 UNREACHABLE(); | 1263 UNREACHABLE(); |
1184 } | 1264 } |
1185 | 1265 |
1186 // The swap of source and destination has executed a move from source to | 1266 // The swap of source and destination has executed a move from source to |
1187 // destination. | 1267 // destination. |
1188 move->Eliminate(); | 1268 move->Eliminate(); |
1189 | 1269 |
1190 // Any unperformed (including pending) move with a source of either | 1270 // Any unperformed (including pending) move with a source of either |
1191 // this move's source or destination needs to have their source | 1271 // this move's source or destination needs to have their source |
(...skipping 28 matching lines...) Expand all Loading... |
1220 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { | 1300 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { |
1221 __ Exchange(mem1, mem2); | 1301 __ Exchange(mem1, mem2); |
1222 } | 1302 } |
1223 | 1303 |
1224 | 1304 |
1225 #undef __ | 1305 #undef __ |
1226 | 1306 |
1227 } // namespace dart | 1307 } // namespace dart |
1228 | 1308 |
1229 #endif // defined TARGET_ARCH_X64 | 1309 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |