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 25 matching lines...) Expand all Loading... |
36 | 36 |
37 void Assembler::call(Label* label) { | 37 void Assembler::call(Label* label) { |
38 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 38 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
39 static const int kSize = 5; | 39 static const int kSize = 5; |
40 EmitUint8(0xE8); | 40 EmitUint8(0xE8); |
41 EmitLabel(label, kSize); | 41 EmitLabel(label, kSize); |
42 } | 42 } |
43 | 43 |
44 | 44 |
45 void Assembler::call(const ExternalLabel* label) { | 45 void Assembler::call(const ExternalLabel* label) { |
46 movq(TMP, Immediate(label->address())); | 46 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
47 call(TMP); | 47 intptr_t call_start = buffer_.GetPosition(); |
| 48 |
| 49 // Encode movq(TMP, Immediate(label->address())), but always as imm64. |
| 50 EmitRegisterREX(TMP, REX_W); |
| 51 EmitUint8(0xB8 | (TMP & 7)); |
| 52 EmitInt64(label->address()); |
| 53 |
| 54 // Encode call(TMP). |
| 55 Operand operand(TMP); |
| 56 EmitOperandREX(2, operand, REX_NONE); |
| 57 EmitUint8(0xFF); |
| 58 EmitOperand(2, operand); |
| 59 |
| 60 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); |
48 } | 61 } |
49 | 62 |
50 | 63 |
51 void Assembler::pushq(Register reg) { | 64 void Assembler::pushq(Register reg) { |
52 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 65 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
53 EmitRegisterREX(reg, REX_NONE); | 66 EmitRegisterREX(reg, REX_NONE); |
54 EmitUint8(0x50 | (reg & 7)); | 67 EmitUint8(0x50 | (reg & 7)); |
55 } | 68 } |
56 | 69 |
57 | 70 |
(...skipping 817 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
875 } | 888 } |
876 | 889 |
877 | 890 |
878 void Assembler::subq(Register reg, const Immediate& imm) { | 891 void Assembler::subq(Register reg, const Immediate& imm) { |
879 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 892 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
880 EmitRegisterREX(reg, REX_W); | 893 EmitRegisterREX(reg, REX_W); |
881 EmitComplex(5, Operand(reg), imm); | 894 EmitComplex(5, Operand(reg), imm); |
882 } | 895 } |
883 | 896 |
884 | 897 |
| 898 void Assembler::subq(Register reg, const Address& address) { |
| 899 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 900 EmitOperandREX(reg, address, REX_W); |
| 901 EmitUint8(0x2B); |
| 902 EmitOperand(reg & 7, address); |
| 903 } |
| 904 |
| 905 |
885 void Assembler::shll(Register reg, const Immediate& imm) { | 906 void Assembler::shll(Register reg, const Immediate& imm) { |
886 EmitGenericShift(false, 4, reg, imm); | 907 EmitGenericShift(false, 4, reg, imm); |
887 } | 908 } |
888 | 909 |
889 | 910 |
890 void Assembler::shll(Register operand, Register shifter) { | 911 void Assembler::shll(Register operand, Register shifter) { |
891 EmitGenericShift(false, 4, operand, shifter); | 912 EmitGenericShift(false, 4, operand, shifter); |
892 } | 913 } |
893 | 914 |
894 | 915 |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1027 EmitUint8(0xC9); | 1048 EmitUint8(0xC9); |
1028 } | 1049 } |
1029 | 1050 |
1030 | 1051 |
1031 void Assembler::ret() { | 1052 void Assembler::ret() { |
1032 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1053 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
1033 EmitUint8(0xC3); | 1054 EmitUint8(0xC3); |
1034 } | 1055 } |
1035 | 1056 |
1036 | 1057 |
1037 void Assembler::nop() { | 1058 void Assembler::nop(int size) { |
1038 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1059 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
1039 EmitUint8(0x90); | 1060 // There are nops up to size 15, but for now just provide up to size 8. |
| 1061 ASSERT(0 < size && size <= MAX_NOP_SIZE); |
| 1062 switch (size) { |
| 1063 case 1: |
| 1064 EmitUint8(0x90); |
| 1065 break; |
| 1066 case 2: |
| 1067 EmitUint8(0x66); |
| 1068 EmitUint8(0x90); |
| 1069 break; |
| 1070 case 3: |
| 1071 EmitUint8(0x0F); |
| 1072 EmitUint8(0x1F); |
| 1073 EmitUint8(0x00); |
| 1074 break; |
| 1075 case 4: |
| 1076 EmitUint8(0x0F); |
| 1077 EmitUint8(0x1F); |
| 1078 EmitUint8(0x40); |
| 1079 EmitUint8(0x00); |
| 1080 break; |
| 1081 case 5: |
| 1082 EmitUint8(0x0F); |
| 1083 EmitUint8(0x1F); |
| 1084 EmitUint8(0x44); |
| 1085 EmitUint8(0x00); |
| 1086 EmitUint8(0x00); |
| 1087 break; |
| 1088 case 6: |
| 1089 EmitUint8(0x66); |
| 1090 EmitUint8(0x0F); |
| 1091 EmitUint8(0x1F); |
| 1092 EmitUint8(0x44); |
| 1093 EmitUint8(0x00); |
| 1094 EmitUint8(0x00); |
| 1095 break; |
| 1096 case 7: |
| 1097 EmitUint8(0x0F); |
| 1098 EmitUint8(0x1F); |
| 1099 EmitUint8(0x80); |
| 1100 EmitUint8(0x00); |
| 1101 EmitUint8(0x00); |
| 1102 EmitUint8(0x00); |
| 1103 EmitUint8(0x00); |
| 1104 break; |
| 1105 case 8: |
| 1106 EmitUint8(0x0F); |
| 1107 EmitUint8(0x1F); |
| 1108 EmitUint8(0x84); |
| 1109 EmitUint8(0x00); |
| 1110 EmitUint8(0x00); |
| 1111 EmitUint8(0x00); |
| 1112 EmitUint8(0x00); |
| 1113 EmitUint8(0x00); |
| 1114 break; |
| 1115 default: |
| 1116 UNIMPLEMENTED(); |
| 1117 } |
1040 } | 1118 } |
1041 | 1119 |
1042 | 1120 |
1043 void Assembler::int3() { | 1121 void Assembler::int3() { |
1044 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1122 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
1045 EmitUint8(0xCC); | 1123 EmitUint8(0xCC); |
1046 } | 1124 } |
1047 | 1125 |
1048 | 1126 |
1049 void Assembler::hlt() { | 1127 void Assembler::hlt() { |
(...skipping 21 matching lines...) Expand all Loading... |
1071 EmitUint8(0x70 + condition); | 1149 EmitUint8(0x70 + condition); |
1072 EmitNearLabelLink(label); | 1150 EmitNearLabelLink(label); |
1073 } else { | 1151 } else { |
1074 EmitUint8(0x0F); | 1152 EmitUint8(0x0F); |
1075 EmitUint8(0x80 + condition); | 1153 EmitUint8(0x80 + condition); |
1076 EmitLabelLink(label); | 1154 EmitLabelLink(label); |
1077 } | 1155 } |
1078 } | 1156 } |
1079 | 1157 |
1080 | 1158 |
| 1159 void Assembler::j(Condition condition, const ExternalLabel* label) { |
| 1160 Label no_jump; |
| 1161 j(static_cast<Condition>(condition ^ 1), &no_jump); // Negate condition. |
| 1162 jmp(label); |
| 1163 Bind(&no_jump); |
| 1164 } |
| 1165 |
| 1166 |
1081 void Assembler::jmp(Register reg) { | 1167 void Assembler::jmp(Register reg) { |
1082 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1168 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
1083 Operand operand(reg); | 1169 Operand operand(reg); |
1084 EmitOperandREX(4, operand, REX_NONE); | 1170 EmitOperandREX(4, operand, REX_NONE); |
1085 EmitUint8(0xFF); | 1171 EmitUint8(0xFF); |
1086 EmitOperand(4, operand); | 1172 EmitOperand(4, operand); |
1087 } | 1173 } |
1088 | 1174 |
1089 | 1175 |
1090 void Assembler::jmp(Label* label, bool near) { | 1176 void Assembler::jmp(Label* label, bool near) { |
(...skipping 14 matching lines...) Expand all Loading... |
1105 EmitUint8(0xEB); | 1191 EmitUint8(0xEB); |
1106 EmitNearLabelLink(label); | 1192 EmitNearLabelLink(label); |
1107 } else { | 1193 } else { |
1108 EmitUint8(0xE9); | 1194 EmitUint8(0xE9); |
1109 EmitLabelLink(label); | 1195 EmitLabelLink(label); |
1110 } | 1196 } |
1111 } | 1197 } |
1112 | 1198 |
1113 | 1199 |
1114 void Assembler::jmp(const ExternalLabel* label) { | 1200 void Assembler::jmp(const ExternalLabel* label) { |
1115 movq(TMP, Immediate(label->address())); | 1201 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
1116 jmp(TMP); | 1202 intptr_t call_start = buffer_.GetPosition(); |
| 1203 |
| 1204 // Encode movq(TMP, Immediate(label->address())), but always as imm64. |
| 1205 EmitRegisterREX(TMP, REX_W); |
| 1206 EmitUint8(0xB8 | (TMP & 7)); |
| 1207 EmitInt64(label->address()); |
| 1208 |
| 1209 // Encode jmp(TMP). |
| 1210 Operand operand(TMP); |
| 1211 EmitOperandREX(4, operand, REX_NONE); |
| 1212 EmitUint8(0xFF); |
| 1213 EmitOperand(4, operand); |
| 1214 |
| 1215 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); |
1117 } | 1216 } |
1118 | 1217 |
1119 | 1218 |
1120 void Assembler::lock() { | 1219 void Assembler::lock() { |
1121 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1220 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
1122 EmitUint8(0xF0); | 1221 EmitUint8(0xF0); |
1123 } | 1222 } |
1124 | 1223 |
1125 | 1224 |
1126 void Assembler::cmpxchgl(const Address& address, Register reg) { | 1225 void Assembler::cmpxchgl(const Address& address, Register reg) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1187 if (object.IsSmi()) { | 1286 if (object.IsSmi()) { |
1188 cmpq(reg, Immediate(reinterpret_cast<int64_t>(object.raw()))); | 1287 cmpq(reg, Immediate(reinterpret_cast<int64_t>(object.raw()))); |
1189 } else { | 1288 } else { |
1190 ASSERT(reg != TMP); | 1289 ASSERT(reg != TMP); |
1191 LoadObject(TMP, object); | 1290 LoadObject(TMP, object); |
1192 cmpq(reg, TMP); | 1291 cmpq(reg, TMP); |
1193 } | 1292 } |
1194 } | 1293 } |
1195 | 1294 |
1196 | 1295 |
| 1296 void Assembler::StoreIntoObject(Register object, |
| 1297 const FieldAddress& dest, |
| 1298 Register value) { |
| 1299 // TODO(iposva): Add write barrier. |
| 1300 movq(dest, value); |
| 1301 } |
| 1302 |
| 1303 |
1197 void Assembler::Stop(const char* message) { | 1304 void Assembler::Stop(const char* message) { |
1198 // Emit the lower half and the higher half of the message address as immediate | 1305 // Emit the lower half and the higher half of the message address as immediate |
1199 // operands in the test rax instructions, followed by the int3 instruction. | 1306 // operands in the test rax instructions, followed by the int3 instruction. |
1200 // Execution can be resumed with the 'cont' command in gdb. | 1307 // Execution can be resumed with the 'cont' command in gdb. |
1201 int64_t message_address = reinterpret_cast<int64_t>(message); | 1308 int64_t message_address = reinterpret_cast<int64_t>(message); |
1202 testl(RAX, Immediate(Utils::Low32Bits(message_address))); | 1309 testl(RAX, Immediate(Utils::Low32Bits(message_address))); |
1203 testl(RAX, Immediate(Utils::High32Bits(message_address))); | 1310 testl(RAX, Immediate(Utils::High32Bits(message_address))); |
1204 int3(); | 1311 int3(); |
1205 } | 1312 } |
1206 | 1313 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1247 entry.CallFromDart(this); | 1354 entry.CallFromDart(this); |
1248 } | 1355 } |
1249 | 1356 |
1250 | 1357 |
1251 void Assembler::CallRuntimeFromStub(const RuntimeEntry& entry) { | 1358 void Assembler::CallRuntimeFromStub(const RuntimeEntry& entry) { |
1252 entry.CallFromStub(this); | 1359 entry.CallFromStub(this); |
1253 } | 1360 } |
1254 | 1361 |
1255 | 1362 |
1256 void Assembler::Align(int alignment, int offset) { | 1363 void Assembler::Align(int alignment, int offset) { |
1257 UNIMPLEMENTED(); | 1364 ASSERT(Utils::IsPowerOfTwo(alignment)); |
| 1365 int pos = offset + buffer_.GetPosition(); |
| 1366 int mod = pos & (alignment - 1); |
| 1367 if (mod == 0) { |
| 1368 return; |
| 1369 } |
| 1370 int bytes_needed = alignment - mod; |
| 1371 while (bytes_needed > MAX_NOP_SIZE) { |
| 1372 nop(MAX_NOP_SIZE); |
| 1373 bytes_needed -= MAX_NOP_SIZE; |
| 1374 } |
| 1375 if (bytes_needed) { |
| 1376 nop(bytes_needed); |
| 1377 } |
| 1378 ASSERT(((offset + buffer_.GetPosition()) & (alignment-1)) == 0); |
1258 } | 1379 } |
1259 | 1380 |
1260 | 1381 |
1261 void Assembler::EmitOperand(int rm, const Operand& operand) { | 1382 void Assembler::EmitOperand(int rm, const Operand& operand) { |
1262 ASSERT(rm >= 0 && rm < 8); | 1383 ASSERT(rm >= 0 && rm < 8); |
1263 const int length = operand.length_; | 1384 const int length = operand.length_; |
1264 ASSERT(length > 0); | 1385 ASSERT(length > 0); |
1265 // Emit the ModRM byte updated with the given RM value. | 1386 // Emit the ModRM byte updated with the given RM value. |
1266 ASSERT((operand.encoding_[0] & 0x38) == 0); | 1387 ASSERT((operand.encoding_[0] & 0x38) == 0); |
1267 EmitUint8(operand.encoding_[0] + (rm << 3)); | 1388 EmitUint8(operand.encoding_[0] + (rm << 3)); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1370 } else { | 1491 } else { |
1371 EmitRegisterREX(operand, REX_NONE); | 1492 EmitRegisterREX(operand, REX_NONE); |
1372 } | 1493 } |
1373 EmitUint8(0xD3); | 1494 EmitUint8(0xD3); |
1374 EmitOperand(rm, Operand(operand)); | 1495 EmitOperand(rm, Operand(operand)); |
1375 } | 1496 } |
1376 | 1497 |
1377 } // namespace dart | 1498 } // namespace dart |
1378 | 1499 |
1379 #endif // defined TARGET_ARCH_X64 | 1500 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |