Chromium Code Reviews| 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 |