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 234 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) { | |
srdjan
2011/12/06 17:37:44
Could you add tests for the new operations/mode in
regis
2011/12/06 21:41:52
Done.
| |
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 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
807 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 841 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
808 EmitUint8(0x0F); | 842 EmitUint8(0x0F); |
809 EmitUint8(0xAF); | 843 EmitUint8(0xAF); |
810 EmitOperand(dst, Operand(src)); | 844 EmitOperand(dst, Operand(src)); |
811 } | 845 } |
812 | 846 |
813 | 847 |
814 void Assembler::imull(Register reg, const Immediate& imm) { | 848 void Assembler::imull(Register reg, const Immediate& imm) { |
815 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 849 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
816 EmitUint8(0x69); | 850 EmitUint8(0x69); |
817 EmitOperand(reg, Operand(reg)); | 851 EmitOperand(reg & 7, Operand(reg)); |
818 EmitImmediate(imm); | 852 EmitImmediate(imm); |
819 } | 853 } |
820 | 854 |
821 | 855 |
822 void Assembler::imulq(Register dst, Register src) { | 856 void Assembler::imulq(Register dst, Register src) { |
823 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 857 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
824 Operand operand(src); | 858 Operand operand(src); |
825 EmitOperandREX(dst, operand, REX_W); | 859 EmitOperandREX(dst, operand, REX_W); |
826 EmitUint8(0x0F); | 860 EmitUint8(0x0F); |
827 EmitUint8(0xAF); | 861 EmitUint8(0xAF); |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1117 if (value == 1) { | 1151 if (value == 1) { |
1118 decq(reg); | 1152 decq(reg); |
1119 } else if (value != 0) { | 1153 } else if (value != 0) { |
1120 subq(reg, Immediate(value)); | 1154 subq(reg, Immediate(value)); |
1121 } | 1155 } |
1122 } | 1156 } |
1123 } | 1157 } |
1124 | 1158 |
1125 | 1159 |
1126 void Assembler::LoadObject(Register dst, const Object& object) { | 1160 void Assembler::LoadObject(Register dst, const Object& object) { |
1127 ASSERT(object.IsZoneHandle()); | 1161 if (object.IsSmi()) { |
1128 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1162 movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw()))); |
1129 EmitRegisterREX(dst, REX_W); | 1163 } else { |
1130 EmitUint8(0xB8 | (dst & 7)); | 1164 ASSERT(object.IsZoneHandle()); |
1131 buffer_.EmitObject(object); | 1165 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
1166 EmitRegisterREX(dst, REX_W); | |
1167 EmitUint8(0xB8 | (dst & 7)); | |
1168 buffer_.EmitObject(object); | |
1169 } | |
1132 } | 1170 } |
1133 | 1171 |
1134 | 1172 |
1135 void Assembler::PushObject(const Object& object) { | 1173 void Assembler::PushObject(const Object& object) { |
1136 LoadObject(TMP, object); | 1174 if (object.IsSmi()) { |
1137 pushq(TMP); | 1175 pushq(Immediate(reinterpret_cast<int64_t>(object.raw()))); |
1176 } else { | |
1177 LoadObject(TMP, object); | |
1178 pushq(TMP); | |
1179 } | |
1138 } | 1180 } |
1139 | 1181 |
1140 | 1182 |
1141 void Assembler::CompareObject(Register reg, const Object& object) { | 1183 void Assembler::CompareObject(Register reg, const Object& object) { |
1142 ASSERT(reg != TMP); | 1184 if (object.IsSmi()) { |
1143 LoadObject(TMP, object); | 1185 cmpq(reg, Immediate(reinterpret_cast<int64_t>(object.raw()))); |
1144 cmpq(reg, TMP); | 1186 } else { |
1187 ASSERT(reg != TMP); | |
1188 LoadObject(TMP, object); | |
1189 cmpq(reg, TMP); | |
1190 } | |
1145 } | 1191 } |
1146 | 1192 |
1147 | 1193 |
1148 void Assembler::Stop(const char* message) { | 1194 void Assembler::Stop(const char* message) { |
1149 // Emit the lower half and the higher half of the message address as immediate | 1195 // 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. | 1196 // operands in the test rax instructions, followed by the int3 instruction. |
1151 // Execution can be resumed with the 'cont' command in gdb. | 1197 // Execution can be resumed with the 'cont' command in gdb. |
1152 int64_t message_address = reinterpret_cast<int64_t>(message); | 1198 int64_t message_address = reinterpret_cast<int64_t>(message); |
1153 testl(RAX, Immediate(Utils::Low32Bits(message_address))); | 1199 testl(RAX, Immediate(Utils::Low32Bits(message_address))); |
1154 testl(RAX, Immediate(Utils::High32Bits(message_address))); | 1200 testl(RAX, Immediate(Utils::High32Bits(message_address))); |
(...skipping 13 matching lines...) Expand all Loading... | |
1168 while (label->HasNear()) { | 1214 while (label->HasNear()) { |
1169 int position = label->NearPosition(); | 1215 int position = label->NearPosition(); |
1170 int offset = bound - (position + 1); | 1216 int offset = bound - (position + 1); |
1171 ASSERT(Utils::IsInt(8, offset)); | 1217 ASSERT(Utils::IsInt(8, offset)); |
1172 buffer_.Store<int8_t>(position, offset); | 1218 buffer_.Store<int8_t>(position, offset); |
1173 } | 1219 } |
1174 label->BindTo(bound); | 1220 label->BindTo(bound); |
1175 } | 1221 } |
1176 | 1222 |
1177 | 1223 |
1224 void Assembler::EnterFrame(intptr_t frame_size) { | |
1225 if (prolog_offset_ == -1) { | |
1226 prolog_offset_ = CodeSize(); | |
1227 } | |
1228 pushq(RBP); | |
1229 movq(RBP, RSP); | |
1230 if (frame_size != 0) { | |
1231 Immediate frame_space(frame_size); | |
1232 subq(RSP, frame_space); | |
1233 } | |
1234 } | |
1235 | |
1236 | |
1237 void Assembler::LeaveFrame() { | |
1238 movq(RSP, RBP); | |
1239 popq(RBP); | |
1240 } | |
1241 | |
1242 | |
1243 void Assembler::CallRuntimeFromDart(const RuntimeEntry& entry) { | |
1244 entry.CallFromDart(this); | |
1245 } | |
1246 | |
1247 | |
1248 void Assembler::CallRuntimeFromStub(const RuntimeEntry& entry) { | |
1249 entry.CallFromStub(this); | |
1250 } | |
1251 | |
1252 | |
1178 void Assembler::Align(int alignment, int offset) { | 1253 void Assembler::Align(int alignment, int offset) { |
1179 UNIMPLEMENTED(); | 1254 UNIMPLEMENTED(); |
1180 } | 1255 } |
1181 | 1256 |
1182 | 1257 |
1183 void Assembler::EmitOperand(int rm, const Operand& operand) { | 1258 void Assembler::EmitOperand(int rm, const Operand& operand) { |
1184 ASSERT(rm >= 0 && rm < 8); | 1259 ASSERT(rm >= 0 && rm < 8); |
1185 const int length = operand.length_; | 1260 const int length = operand.length_; |
1186 ASSERT(length > 0); | 1261 ASSERT(length > 0); |
1187 // Emit the ModRM byte updated with the given RM value. | 1262 // Emit the ModRM byte updated with the given RM value. |
(...skipping 16 matching lines...) Expand all Loading... | |
1204 void Assembler::EmitImmediate(const Immediate& imm) { | 1279 void Assembler::EmitImmediate(const Immediate& imm) { |
1205 if (imm.is_int32()) { | 1280 if (imm.is_int32()) { |
1206 EmitInt32(static_cast<int32_t>(imm.value())); | 1281 EmitInt32(static_cast<int32_t>(imm.value())); |
1207 } else { | 1282 } else { |
1208 EmitInt64(imm.value()); | 1283 EmitInt64(imm.value()); |
1209 } | 1284 } |
1210 } | 1285 } |
1211 | 1286 |
1212 | 1287 |
1213 void Assembler::EmitComplex(int rm, | 1288 void Assembler::EmitComplex(int rm, |
1214 const Operand& operand, | 1289 const Operand& operand, |
1215 const Immediate& immediate) { | 1290 const Immediate& immediate) { |
1216 ASSERT(rm >= 0 && rm < 8); | 1291 ASSERT(rm >= 0 && rm < 8); |
1217 ASSERT(immediate.is_int32()); | 1292 ASSERT(immediate.is_int32()); |
1218 if (immediate.is_int8()) { | 1293 if (immediate.is_int8()) { |
1219 // Use sign-extended 8-bit immediate. | 1294 // Use sign-extended 8-bit immediate. |
1220 EmitUint8(0x83); | 1295 EmitUint8(0x83); |
1221 EmitOperand(rm, operand); | 1296 EmitOperand(rm, operand); |
1222 EmitUint8(immediate.value() & 0xFF); | 1297 EmitUint8(immediate.value() & 0xFF); |
1223 } else if (operand.IsRegister(RAX)) { | 1298 } else if (operand.IsRegister(RAX)) { |
1224 // Use short form if the destination is rax. | 1299 // Use short form if the destination is rax. |
1225 EmitUint8(0x05 + (rm << 3)); | 1300 EmitUint8(0x05 + (rm << 3)); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1292 } else { | 1367 } else { |
1293 EmitRegisterREX(operand, REX_NONE); | 1368 EmitRegisterREX(operand, REX_NONE); |
1294 } | 1369 } |
1295 EmitUint8(0xD3); | 1370 EmitUint8(0xD3); |
1296 EmitOperand(rm, Operand(operand)); | 1371 EmitOperand(rm, Operand(operand)); |
1297 } | 1372 } |
1298 | 1373 |
1299 } // namespace dart | 1374 } // namespace dart |
1300 | 1375 |
1301 #endif // defined TARGET_ARCH_X64 | 1376 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |