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 852 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
863 __ testq(RAX, Immediate(kSmiTagMask)); | 863 __ testq(RAX, Immediate(kSmiTagMask)); |
864 __ j(ZERO, &smi_to_double); | 864 __ j(ZERO, &smi_to_double); |
865 __ CompareClassId(RAX, kDoubleCid); | 865 __ CompareClassId(RAX, kDoubleCid); |
866 __ j(NOT_EQUAL, &call_method); | 866 __ j(NOT_EQUAL, &call_method); |
867 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); | 867 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); |
868 __ Bind(&double_op); | 868 __ Bind(&double_op); |
869 __ sqrtsd(XMM0, XMM1); | 869 __ sqrtsd(XMM0, XMM1); |
870 AssemblerMacros::TryAllocate(assembler_, | 870 AssemblerMacros::TryAllocate(assembler_, |
871 double_class_, | 871 double_class_, |
872 &call_method, | 872 &call_method, |
| 873 Assembler::kNearJump, |
873 RAX); // Result register. | 874 RAX); // Result register. |
874 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); | 875 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); |
875 __ Drop(1); | 876 __ Drop(1); |
876 __ jmp(done); | 877 __ jmp(done); |
877 __ Bind(&smi_to_double); | 878 __ Bind(&smi_to_double); |
878 __ SmiUntag(RAX); | 879 __ SmiUntag(RAX); |
879 __ cvtsi2sd(XMM1, RAX); | 880 __ cvtsi2sd(XMM1, RAX); |
880 __ jmp(&double_op); | 881 __ jmp(&double_op); |
881 __ Bind(&call_method); | 882 __ Bind(&call_method); |
882 } | 883 } |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1087 __ movsd(result, FieldAddress(reg, Double::value_offset())); | 1088 __ movsd(result, FieldAddress(reg, Double::value_offset())); |
1088 __ jmp(&done); | 1089 __ jmp(&done); |
1089 __ Bind(&is_smi); | 1090 __ Bind(&is_smi); |
1090 __ movq(temp, reg); | 1091 __ movq(temp, reg); |
1091 __ SmiUntag(temp); | 1092 __ SmiUntag(temp); |
1092 __ cvtsi2sd(result, temp); | 1093 __ cvtsi2sd(result, temp); |
1093 __ Bind(&done); | 1094 __ Bind(&done); |
1094 } | 1095 } |
1095 | 1096 |
1096 | 1097 |
| 1098 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { |
| 1099 // TODO(vegorov): consider saving only caller save (volatile) registers. |
| 1100 const intptr_t xmm_regs_count = locs->live_registers()->xmm_regs_count(); |
| 1101 if (xmm_regs_count > 0) { |
| 1102 // Pointer maps don't support pushed untagged values so we reserve spill |
| 1103 // slots at the top of the spill slot area for live XMM registers. |
| 1104 intptr_t stack_offs = (StackSize() + 1) * kWordSize; |
| 1105 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
| 1106 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
| 1107 if (locs->live_registers()->ContainsXmmRegister(xmm_reg)) { |
| 1108 __ movsd(Address(RBP, -stack_offs), xmm_reg); |
| 1109 stack_offs += kDoubleSize; |
| 1110 } |
| 1111 } |
| 1112 } |
| 1113 |
| 1114 for (intptr_t reg_idx = 0; reg_idx < kNumberOfCpuRegisters; ++reg_idx) { |
| 1115 Register reg = static_cast<Register>(reg_idx); |
| 1116 if (locs->live_registers()->ContainsRegister(reg)) { |
| 1117 __ pushq(reg); |
| 1118 } |
| 1119 } |
| 1120 } |
| 1121 |
| 1122 |
| 1123 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) { |
| 1124 for (intptr_t reg_idx = kNumberOfCpuRegisters - 1; reg_idx >= 0; --reg_idx) { |
| 1125 Register reg = static_cast<Register>(reg_idx); |
| 1126 if (locs->live_registers()->ContainsRegister(reg)) { |
| 1127 __ popq(reg); |
| 1128 } |
| 1129 } |
| 1130 |
| 1131 const intptr_t xmm_regs_count = locs->live_registers()->xmm_regs_count(); |
| 1132 if (xmm_regs_count > 0) { |
| 1133 // Pointer maps don't support pushed untagged values so we reserve spill |
| 1134 // slots at the top of the spill slot area for live XMM registers. |
| 1135 intptr_t stack_offs = (StackSize() + 1) * kWordSize; |
| 1136 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
| 1137 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
| 1138 if (locs->live_registers()->ContainsXmmRegister(xmm_reg)) { |
| 1139 __ movsd(xmm_reg, Address(RBP, -stack_offs)); |
| 1140 stack_offs += kDoubleSize; |
| 1141 } |
| 1142 } |
| 1143 } |
| 1144 } |
| 1145 |
| 1146 |
1097 #undef __ | 1147 #undef __ |
1098 #define __ compiler_->assembler()-> | 1148 #define __ compiler_->assembler()-> |
1099 | 1149 |
1100 | 1150 |
1101 static Address ToStackSlotAddress(Location loc) { | 1151 static Address ToStackSlotAddress(Location loc) { |
1102 ASSERT(loc.IsStackSlot()); | |
1103 const intptr_t index = loc.stack_index(); | 1152 const intptr_t index = loc.stack_index(); |
1104 if (index < 0) { | 1153 if (index < 0) { |
1105 const intptr_t offset = (1 - index) * kWordSize; | 1154 const intptr_t offset = (1 - index) * kWordSize; |
1106 return Address(RBP, offset); | 1155 return Address(RBP, offset); |
1107 } else { | 1156 } else { |
1108 const intptr_t offset = | 1157 const intptr_t offset = |
1109 (ParsedFunction::kFirstLocalSlotIndex - index) * kWordSize; | 1158 (ParsedFunction::kFirstLocalSlotIndex - index) * kWordSize; |
1110 return Address(RBP, offset); | 1159 return Address(RBP, offset); |
1111 } | 1160 } |
1112 } | 1161 } |
(...skipping 12 matching lines...) Expand all Loading... |
1125 __ movq(ToStackSlotAddress(destination), source.reg()); | 1174 __ movq(ToStackSlotAddress(destination), source.reg()); |
1126 } | 1175 } |
1127 } else if (source.IsStackSlot()) { | 1176 } else if (source.IsStackSlot()) { |
1128 if (destination.IsRegister()) { | 1177 if (destination.IsRegister()) { |
1129 __ movq(destination.reg(), ToStackSlotAddress(source)); | 1178 __ movq(destination.reg(), ToStackSlotAddress(source)); |
1130 } else { | 1179 } else { |
1131 ASSERT(destination.IsStackSlot()); | 1180 ASSERT(destination.IsStackSlot()); |
1132 MoveMemoryToMemory(ToStackSlotAddress(destination), | 1181 MoveMemoryToMemory(ToStackSlotAddress(destination), |
1133 ToStackSlotAddress(source)); | 1182 ToStackSlotAddress(source)); |
1134 } | 1183 } |
| 1184 } else if (source.IsXmmRegister()) { |
| 1185 if (destination.IsXmmRegister()) { |
| 1186 // Optimization manual recommends using MOVAPS for register |
| 1187 // to register moves. |
| 1188 __ movaps(destination.xmm_reg(), source.xmm_reg()); |
| 1189 } else { |
| 1190 ASSERT(destination.IsDoubleStackSlot()); |
| 1191 __ movsd(ToStackSlotAddress(destination), source.xmm_reg()); |
| 1192 } |
| 1193 } else if (source.IsDoubleStackSlot()) { |
| 1194 if (destination.IsXmmRegister()) { |
| 1195 __ movsd(destination.xmm_reg(), ToStackSlotAddress(source)); |
| 1196 } else { |
| 1197 ASSERT(destination.IsDoubleStackSlot()); |
| 1198 __ movsd(XMM0, ToStackSlotAddress(source)); |
| 1199 __ movsd(ToStackSlotAddress(destination), XMM0); |
| 1200 } |
1135 } else { | 1201 } else { |
1136 ASSERT(source.IsConstant()); | 1202 ASSERT(source.IsConstant()); |
1137 if (destination.IsRegister()) { | 1203 if (destination.IsRegister()) { |
1138 __ LoadObject(destination.reg(), source.constant()); | 1204 __ LoadObject(destination.reg(), source.constant()); |
1139 } else { | 1205 } else { |
1140 ASSERT(destination.IsStackSlot()); | 1206 ASSERT(destination.IsStackSlot()); |
1141 StoreObject(ToStackSlotAddress(destination), source.constant()); | 1207 StoreObject(ToStackSlotAddress(destination), source.constant()); |
1142 } | 1208 } |
1143 } | 1209 } |
1144 | 1210 |
1145 move->Eliminate(); | 1211 move->Eliminate(); |
1146 } | 1212 } |
1147 | 1213 |
1148 | 1214 |
1149 void ParallelMoveResolver::EmitSwap(int index) { | 1215 void ParallelMoveResolver::EmitSwap(int index) { |
1150 MoveOperands* move = moves_[index]; | 1216 MoveOperands* move = moves_[index]; |
1151 const Location source = move->src(); | 1217 const Location source = move->src(); |
1152 const Location destination = move->dest(); | 1218 const Location destination = move->dest(); |
1153 | 1219 |
1154 if (source.IsRegister() && destination.IsRegister()) { | 1220 if (source.IsRegister() && destination.IsRegister()) { |
1155 __ xchgq(destination.reg(), source.reg()); | 1221 __ xchgq(destination.reg(), source.reg()); |
1156 } else if (source.IsRegister() && destination.IsStackSlot()) { | 1222 } else if (source.IsRegister() && destination.IsStackSlot()) { |
1157 Exchange(source.reg(), ToStackSlotAddress(destination)); | 1223 Exchange(source.reg(), ToStackSlotAddress(destination)); |
1158 } else if (source.IsStackSlot() && destination.IsRegister()) { | 1224 } else if (source.IsStackSlot() && destination.IsRegister()) { |
1159 Exchange(destination.reg(), ToStackSlotAddress(source)); | 1225 Exchange(destination.reg(), ToStackSlotAddress(source)); |
1160 } else if (source.IsStackSlot() && destination.IsStackSlot()) { | 1226 } else if (source.IsStackSlot() && destination.IsStackSlot()) { |
1161 Exchange(ToStackSlotAddress(destination), ToStackSlotAddress(source)); | 1227 Exchange(ToStackSlotAddress(destination), ToStackSlotAddress(source)); |
| 1228 } else if (source.IsXmmRegister() && destination.IsXmmRegister()) { |
| 1229 __ movaps(XMM0, source.xmm_reg()); |
| 1230 __ movaps(source.xmm_reg(), destination.xmm_reg()); |
| 1231 __ movaps(destination.xmm_reg(), XMM0); |
| 1232 } else if (source.IsXmmRegister() || destination.IsXmmRegister()) { |
| 1233 ASSERT(destination.IsDoubleStackSlot() || source.IsDoubleStackSlot()); |
| 1234 XmmRegister reg = source.IsXmmRegister() ? source.xmm_reg() |
| 1235 : destination.xmm_reg(); |
| 1236 Address slot_address = |
| 1237 ToStackSlotAddress(source.IsXmmRegister() ? destination : source); |
| 1238 |
| 1239 __ movsd(XMM0, slot_address); |
| 1240 __ movsd(slot_address, reg); |
| 1241 __ movaps(reg, XMM0); |
1162 } else { | 1242 } else { |
1163 UNREACHABLE(); | 1243 UNREACHABLE(); |
1164 } | 1244 } |
1165 | 1245 |
1166 // The swap of source and destination has executed a move from source to | 1246 // The swap of source and destination has executed a move from source to |
1167 // destination. | 1247 // destination. |
1168 move->Eliminate(); | 1248 move->Eliminate(); |
1169 | 1249 |
1170 // Any unperformed (including pending) move with a source of either | 1250 // Any unperformed (including pending) move with a source of either |
1171 // this move's source or destination needs to have their source | 1251 // this move's source or destination needs to have their source |
(...skipping 28 matching lines...) Expand all Loading... |
1200 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { | 1280 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { |
1201 __ Exchange(mem1, mem2); | 1281 __ Exchange(mem1, mem2); |
1202 } | 1282 } |
1203 | 1283 |
1204 | 1284 |
1205 #undef __ | 1285 #undef __ |
1206 | 1286 |
1207 } // namespace dart | 1287 } // namespace dart |
1208 | 1288 |
1209 #endif // defined TARGET_ARCH_X64 | 1289 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |