OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/heap.h" | 9 #include "vm/heap.h" |
10 #include "vm/memory_region.h" | 10 #include "vm/memory_region.h" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 | 56 |
57 | 57 |
58 void Assembler::pushq(const Address& address) { | 58 void Assembler::pushq(const Address& address) { |
59 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 59 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
60 EmitOperandREX(6, address, REX_NONE); | 60 EmitOperandREX(6, address, REX_NONE); |
61 EmitUint8(0xFF); | 61 EmitUint8(0xFF); |
62 EmitOperand(6, address); | 62 EmitOperand(6, address); |
63 } | 63 } |
64 | 64 |
65 | 65 |
| 66 void Assembler::pushq(const Immediate& imm) { |
| 67 if (imm.is_int32()) { |
| 68 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 69 EmitUint8(0x68); |
| 70 EmitImmediate(imm); |
| 71 } else { |
| 72 movq(TMP, imm); |
| 73 pushq(TMP); |
| 74 } |
| 75 } |
| 76 |
| 77 |
66 void Assembler::popq(Register reg) { | 78 void Assembler::popq(Register reg) { |
67 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 79 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
68 EmitRegisterREX(reg, REX_NONE); | 80 EmitRegisterREX(reg, REX_NONE); |
69 EmitUint8(0x58 | (reg & 7)); | 81 EmitUint8(0x58 | (reg & 7)); |
70 } | 82 } |
71 | 83 |
72 | 84 |
73 void Assembler::popq(const Address& address) { | 85 void Assembler::popq(const Address& address) { |
74 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 86 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
75 EmitOperandREX(0, address, REX_NONE); | 87 EmitOperandREX(0, address, REX_NONE); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 | 280 |
269 void Assembler::movq(const Address& dst, Register src) { | 281 void Assembler::movq(const Address& dst, Register src) { |
270 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 282 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
271 EmitOperandREX(src, dst, REX_W); | 283 EmitOperandREX(src, dst, REX_W); |
272 EmitUint8(0x89); | 284 EmitUint8(0x89); |
273 EmitOperand(src & 7, dst); | 285 EmitOperand(src & 7, dst); |
274 } | 286 } |
275 | 287 |
276 | 288 |
277 void Assembler::movq(const Address& dst, const Immediate& imm) { | 289 void Assembler::movq(const Address& dst, const Immediate& imm) { |
278 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 290 if (imm.is_int32()) { |
279 ASSERT(imm.is_int32()); | 291 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
280 Operand operand(dst); | 292 Operand operand(dst); |
281 EmitOperandREX(0, operand, REX_W); | 293 EmitOperandREX(0, operand, REX_W); |
282 EmitUint8(0xC7); | 294 EmitUint8(0xC7); |
283 EmitOperand(0, operand); | 295 EmitOperand(0, operand); |
284 EmitImmediate(imm); | 296 EmitImmediate(imm); |
| 297 } else { |
| 298 movq(TMP, imm); |
| 299 movq(dst, TMP); |
| 300 } |
285 } | 301 } |
286 | 302 |
287 | 303 |
288 void Assembler::movsxl(Register dst, const Address& src) { | 304 void Assembler::movsxl(Register dst, const Address& src) { |
289 UNIMPLEMENTED(); | 305 UNIMPLEMENTED(); |
290 } | 306 } |
291 | 307 |
292 | 308 |
293 void Assembler::leaq(Register dst, const Address& src) { | 309 void Assembler::leaq(Register dst, const Address& src) { |
294 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 310 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 EmitXmmRegisterOperand(src & 7, dst); | 349 EmitXmmRegisterOperand(src & 7, dst); |
334 } | 350 } |
335 | 351 |
336 | 352 |
337 void Assembler::movd(XmmRegister dst, Register src) { | 353 void Assembler::movd(XmmRegister dst, Register src) { |
338 ASSERT(dst <= XMM7); | 354 ASSERT(dst <= XMM7); |
339 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 355 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
340 EmitUint8(0x66); | 356 EmitUint8(0x66); |
341 EmitUint8(0x0F); | 357 EmitUint8(0x0F); |
342 EmitUint8(0x6E); | 358 EmitUint8(0x6E); |
343 EmitOperand(dst, Operand(src)); | 359 EmitOperand(dst & 7, Operand(src)); |
344 } | 360 } |
345 | 361 |
346 | 362 |
347 void Assembler::movd(Register dst, XmmRegister src) { | 363 void Assembler::movd(Register dst, XmmRegister src) { |
348 ASSERT(src <= XMM7); | 364 ASSERT(src <= XMM7); |
349 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 365 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
350 EmitUint8(0x66); | 366 EmitUint8(0x66); |
351 EmitUint8(0x0F); | 367 EmitUint8(0x0F); |
352 EmitUint8(0x7E); | 368 EmitUint8(0x7E); |
353 EmitOperand(src, Operand(dst)); | 369 EmitOperand(src & 7, Operand(dst)); |
354 } | 370 } |
355 | 371 |
356 | 372 |
357 void Assembler::addss(XmmRegister dst, XmmRegister src) { | 373 void Assembler::addss(XmmRegister dst, XmmRegister src) { |
358 // TODO(srdjan): implement and test XMM8 - XMM15. | 374 // TODO(srdjan): implement and test XMM8 - XMM15. |
359 ASSERT(src <= XMM7); | 375 ASSERT(src <= XMM7); |
360 ASSERT(dst <= XMM7); | 376 ASSERT(dst <= XMM7); |
361 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 377 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
362 EmitUint8(0xF3); | 378 EmitUint8(0xF3); |
363 EmitUint8(0x0F); | 379 EmitUint8(0x0F); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 | 545 |
530 | 546 |
531 void Assembler::cmpl(const Address& address, const Immediate& imm) { | 547 void Assembler::cmpl(const Address& address, const Immediate& imm) { |
532 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 548 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
533 Operand operand(address); | 549 Operand operand(address); |
534 EmitOperandREX(7, operand, REX_NONE); | 550 EmitOperandREX(7, operand, REX_NONE); |
535 EmitComplex(7, operand, imm); | 551 EmitComplex(7, operand, imm); |
536 } | 552 } |
537 | 553 |
538 | 554 |
| 555 void Assembler::cmpq(const Address& address, Register reg) { |
| 556 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 557 EmitOperandREX(reg, address, REX_W); |
| 558 EmitUint8(0x39); |
| 559 EmitOperand(reg & 7, address); |
| 560 } |
| 561 |
| 562 |
539 void Assembler::cmpq(const Address& address, const Immediate& imm) { | 563 void Assembler::cmpq(const Address& address, const Immediate& imm) { |
540 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 564 if (imm.is_int32()) { |
541 Operand operand(address); | 565 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
542 EmitOperandREX(7, operand, REX_W); | 566 Operand operand(address); |
543 EmitComplex(7, operand, imm); | 567 EmitOperandREX(7, operand, REX_W); |
| 568 EmitComplex(7, operand, imm); |
| 569 } else { |
| 570 movq(TMP, imm); |
| 571 cmpq(address, TMP); |
| 572 } |
544 } | 573 } |
545 | 574 |
546 | 575 |
547 void Assembler::cmpq(Register reg, const Immediate& imm) { | 576 void Assembler::cmpq(Register reg, const Immediate& imm) { |
548 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 577 if (imm.is_int32()) { |
549 EmitRegisterREX(reg, REX_W); | 578 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
550 EmitComplex(7, Operand(reg), imm); | 579 EmitRegisterREX(reg, REX_W); |
| 580 EmitComplex(7, Operand(reg), imm); |
| 581 } else { |
| 582 movq(TMP, imm); |
| 583 cmpq(reg, TMP); |
| 584 } |
551 } | 585 } |
552 | 586 |
553 | 587 |
554 void Assembler::cmpq(Register reg0, Register reg1) { | 588 void Assembler::cmpq(Register reg0, Register reg1) { |
555 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 589 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
556 Operand operand(reg1); | 590 Operand operand(reg1); |
557 EmitOperandREX(reg0, operand, REX_W); | 591 EmitOperandREX(reg0, operand, REX_W); |
558 EmitUint8(0x3B); | 592 EmitUint8(0x3B); |
559 EmitOperand(reg0 & 7, operand); | 593 EmitOperand(reg0 & 7, operand); |
560 } | 594 } |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
798 void Assembler::idivq(Register reg) { | 832 void Assembler::idivq(Register reg) { |
799 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 833 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
800 EmitRegisterREX(reg, REX_W); | 834 EmitRegisterREX(reg, REX_W); |
801 EmitUint8(0xF7); | 835 EmitUint8(0xF7); |
802 EmitUint8(0xF8 | (reg & 7)); | 836 EmitUint8(0xF8 | (reg & 7)); |
803 } | 837 } |
804 | 838 |
805 | 839 |
806 void Assembler::imull(Register dst, Register src) { | 840 void Assembler::imull(Register dst, Register src) { |
807 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 841 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 842 Operand operand(src); |
| 843 EmitOperandREX(dst, operand, REX_NONE); |
808 EmitUint8(0x0F); | 844 EmitUint8(0x0F); |
809 EmitUint8(0xAF); | 845 EmitUint8(0xAF); |
810 EmitOperand(dst, Operand(src)); | 846 EmitOperand(dst & 7, Operand(src)); |
811 } | 847 } |
812 | 848 |
813 | 849 |
814 void Assembler::imull(Register reg, const Immediate& imm) { | 850 void Assembler::imull(Register reg, const Immediate& imm) { |
815 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 851 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 852 EmitRegisterREX(reg, REX_NONE); |
816 EmitUint8(0x69); | 853 EmitUint8(0x69); |
817 EmitOperand(reg, Operand(reg)); | 854 EmitOperand(reg & 7, Operand(reg)); |
818 EmitImmediate(imm); | 855 EmitImmediate(imm); |
819 } | 856 } |
820 | 857 |
821 | 858 |
822 void Assembler::imulq(Register dst, Register src) { | 859 void Assembler::imulq(Register dst, Register src) { |
823 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 860 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
824 Operand operand(src); | 861 Operand operand(src); |
825 EmitOperandREX(dst, operand, REX_W); | 862 EmitOperandREX(dst, operand, REX_W); |
826 EmitUint8(0x0F); | 863 EmitUint8(0x0F); |
827 EmitUint8(0xAF); | 864 EmitUint8(0xAF); |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1117 if (value == 1) { | 1154 if (value == 1) { |
1118 decq(reg); | 1155 decq(reg); |
1119 } else if (value != 0) { | 1156 } else if (value != 0) { |
1120 subq(reg, Immediate(value)); | 1157 subq(reg, Immediate(value)); |
1121 } | 1158 } |
1122 } | 1159 } |
1123 } | 1160 } |
1124 | 1161 |
1125 | 1162 |
1126 void Assembler::LoadObject(Register dst, const Object& object) { | 1163 void Assembler::LoadObject(Register dst, const Object& object) { |
1127 ASSERT(object.IsZoneHandle()); | 1164 if (object.IsSmi()) { |
1128 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1165 movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw()))); |
1129 EmitRegisterREX(dst, REX_W); | 1166 } else { |
1130 EmitUint8(0xB8 | (dst & 7)); | 1167 ASSERT(object.IsZoneHandle()); |
1131 buffer_.EmitObject(object); | 1168 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1169 EmitRegisterREX(dst, REX_W); |
| 1170 EmitUint8(0xB8 | (dst & 7)); |
| 1171 buffer_.EmitObject(object); |
| 1172 } |
1132 } | 1173 } |
1133 | 1174 |
1134 | 1175 |
1135 void Assembler::PushObject(const Object& object) { | 1176 void Assembler::PushObject(const Object& object) { |
1136 LoadObject(TMP, object); | 1177 if (object.IsSmi()) { |
1137 pushq(TMP); | 1178 pushq(Immediate(reinterpret_cast<int64_t>(object.raw()))); |
| 1179 } else { |
| 1180 LoadObject(TMP, object); |
| 1181 pushq(TMP); |
| 1182 } |
1138 } | 1183 } |
1139 | 1184 |
1140 | 1185 |
1141 void Assembler::CompareObject(Register reg, const Object& object) { | 1186 void Assembler::CompareObject(Register reg, const Object& object) { |
1142 ASSERT(reg != TMP); | 1187 if (object.IsSmi()) { |
1143 LoadObject(TMP, object); | 1188 cmpq(reg, Immediate(reinterpret_cast<int64_t>(object.raw()))); |
1144 cmpq(reg, TMP); | 1189 } else { |
| 1190 ASSERT(reg != TMP); |
| 1191 LoadObject(TMP, object); |
| 1192 cmpq(reg, TMP); |
| 1193 } |
1145 } | 1194 } |
1146 | 1195 |
1147 | 1196 |
1148 void Assembler::Stop(const char* message) { | 1197 void Assembler::Stop(const char* message) { |
1149 // Emit the lower half and the higher half of the message address as immediate | 1198 // Emit the lower half and the higher half of the message address as immediate |
1150 // operands in the test rax instructions, followed by the int3 instruction. | 1199 // operands in the test rax instructions, followed by the int3 instruction. |
1151 // Execution can be resumed with the 'cont' command in gdb. | 1200 // Execution can be resumed with the 'cont' command in gdb. |
1152 int64_t message_address = reinterpret_cast<int64_t>(message); | 1201 int64_t message_address = reinterpret_cast<int64_t>(message); |
1153 testl(RAX, Immediate(Utils::Low32Bits(message_address))); | 1202 testl(RAX, Immediate(Utils::Low32Bits(message_address))); |
1154 testl(RAX, Immediate(Utils::High32Bits(message_address))); | 1203 testl(RAX, Immediate(Utils::High32Bits(message_address))); |
(...skipping 13 matching lines...) Expand all Loading... |
1168 while (label->HasNear()) { | 1217 while (label->HasNear()) { |
1169 int position = label->NearPosition(); | 1218 int position = label->NearPosition(); |
1170 int offset = bound - (position + 1); | 1219 int offset = bound - (position + 1); |
1171 ASSERT(Utils::IsInt(8, offset)); | 1220 ASSERT(Utils::IsInt(8, offset)); |
1172 buffer_.Store<int8_t>(position, offset); | 1221 buffer_.Store<int8_t>(position, offset); |
1173 } | 1222 } |
1174 label->BindTo(bound); | 1223 label->BindTo(bound); |
1175 } | 1224 } |
1176 | 1225 |
1177 | 1226 |
| 1227 void Assembler::EnterFrame(intptr_t frame_size) { |
| 1228 if (prolog_offset_ == -1) { |
| 1229 prolog_offset_ = CodeSize(); |
| 1230 } |
| 1231 pushq(RBP); |
| 1232 movq(RBP, RSP); |
| 1233 if (frame_size != 0) { |
| 1234 Immediate frame_space(frame_size); |
| 1235 subq(RSP, frame_space); |
| 1236 } |
| 1237 } |
| 1238 |
| 1239 |
| 1240 void Assembler::LeaveFrame() { |
| 1241 movq(RSP, RBP); |
| 1242 popq(RBP); |
| 1243 } |
| 1244 |
| 1245 |
| 1246 void Assembler::CallRuntimeFromDart(const RuntimeEntry& entry) { |
| 1247 entry.CallFromDart(this); |
| 1248 } |
| 1249 |
| 1250 |
| 1251 void Assembler::CallRuntimeFromStub(const RuntimeEntry& entry) { |
| 1252 entry.CallFromStub(this); |
| 1253 } |
| 1254 |
| 1255 |
1178 void Assembler::Align(int alignment, int offset) { | 1256 void Assembler::Align(int alignment, int offset) { |
1179 UNIMPLEMENTED(); | 1257 UNIMPLEMENTED(); |
1180 } | 1258 } |
1181 | 1259 |
1182 | 1260 |
1183 void Assembler::EmitOperand(int rm, const Operand& operand) { | 1261 void Assembler::EmitOperand(int rm, const Operand& operand) { |
1184 ASSERT(rm >= 0 && rm < 8); | 1262 ASSERT(rm >= 0 && rm < 8); |
1185 const int length = operand.length_; | 1263 const int length = operand.length_; |
1186 ASSERT(length > 0); | 1264 ASSERT(length > 0); |
1187 // Emit the ModRM byte updated with the given RM value. | 1265 // Emit the ModRM byte updated with the given RM value. |
(...skipping 16 matching lines...) Expand all Loading... |
1204 void Assembler::EmitImmediate(const Immediate& imm) { | 1282 void Assembler::EmitImmediate(const Immediate& imm) { |
1205 if (imm.is_int32()) { | 1283 if (imm.is_int32()) { |
1206 EmitInt32(static_cast<int32_t>(imm.value())); | 1284 EmitInt32(static_cast<int32_t>(imm.value())); |
1207 } else { | 1285 } else { |
1208 EmitInt64(imm.value()); | 1286 EmitInt64(imm.value()); |
1209 } | 1287 } |
1210 } | 1288 } |
1211 | 1289 |
1212 | 1290 |
1213 void Assembler::EmitComplex(int rm, | 1291 void Assembler::EmitComplex(int rm, |
1214 const Operand& operand, | 1292 const Operand& operand, |
1215 const Immediate& immediate) { | 1293 const Immediate& immediate) { |
1216 ASSERT(rm >= 0 && rm < 8); | 1294 ASSERT(rm >= 0 && rm < 8); |
1217 ASSERT(immediate.is_int32()); | 1295 ASSERT(immediate.is_int32()); |
1218 if (immediate.is_int8()) { | 1296 if (immediate.is_int8()) { |
1219 // Use sign-extended 8-bit immediate. | 1297 // Use sign-extended 8-bit immediate. |
1220 EmitUint8(0x83); | 1298 EmitUint8(0x83); |
1221 EmitOperand(rm, operand); | 1299 EmitOperand(rm, operand); |
1222 EmitUint8(immediate.value() & 0xFF); | 1300 EmitUint8(immediate.value() & 0xFF); |
1223 } else if (operand.IsRegister(RAX)) { | 1301 } else if (operand.IsRegister(RAX)) { |
1224 // Use short form if the destination is rax. | 1302 // Use short form if the destination is rax. |
1225 EmitUint8(0x05 + (rm << 3)); | 1303 EmitUint8(0x05 + (rm << 3)); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1292 } else { | 1370 } else { |
1293 EmitRegisterREX(operand, REX_NONE); | 1371 EmitRegisterREX(operand, REX_NONE); |
1294 } | 1372 } |
1295 EmitUint8(0xD3); | 1373 EmitUint8(0xD3); |
1296 EmitOperand(rm, Operand(operand)); | 1374 EmitOperand(rm, Operand(operand)); |
1297 } | 1375 } |
1298 | 1376 |
1299 } // namespace dart | 1377 } // namespace dart |
1300 | 1378 |
1301 #endif // defined TARGET_ARCH_X64 | 1379 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |