Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(367)

Side by Side Diff: src/x64/disasm-x64.cc

Issue 757503002: [x64] Introduce FMA3 instructions on scalar data elements. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: remove avx_os_support Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | test/cctest/test-assembler-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <assert.h> 5 #include <assert.h>
6 #include <stdarg.h> 6 #include <stdarg.h>
7 #include <stdio.h> 7 #include <stdio.h>
8 8
9 #include "src/v8.h" 9 #include "src/v8.h"
10 10
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 MOVE_REG_INSTR, 141 MOVE_REG_INSTR,
142 CALL_JUMP_INSTR, 142 CALL_JUMP_INSTR,
143 SHORT_IMMEDIATE_INSTR 143 SHORT_IMMEDIATE_INSTR
144 }; 144 };
145 145
146 146
147 enum Prefixes { 147 enum Prefixes {
148 ESCAPE_PREFIX = 0x0F, 148 ESCAPE_PREFIX = 0x0F,
149 OPERAND_SIZE_OVERRIDE_PREFIX = 0x66, 149 OPERAND_SIZE_OVERRIDE_PREFIX = 0x66,
150 ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67, 150 ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67,
151 VEX3_PREFIX = 0xC4,
152 VEX2_PREFIX = 0xC5,
151 REPNE_PREFIX = 0xF2, 153 REPNE_PREFIX = 0xF2,
152 REP_PREFIX = 0xF3, 154 REP_PREFIX = 0xF3,
153 REPEQ_PREFIX = REP_PREFIX 155 REPEQ_PREFIX = REP_PREFIX
154 }; 156 };
155 157
156 158
157 struct InstructionDesc { 159 struct InstructionDesc {
158 const char* mnem; 160 const char* mnem;
159 InstructionType type; 161 InstructionType type;
160 OperandType op_order_; 162 OperandType op_order_;
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 285
284 // A new DisassemblerX64 object is created to disassemble each instruction. 286 // A new DisassemblerX64 object is created to disassemble each instruction.
285 // The object can only disassemble a single instruction. 287 // The object can only disassemble a single instruction.
286 class DisassemblerX64 { 288 class DisassemblerX64 {
287 public: 289 public:
288 DisassemblerX64(const NameConverter& converter, 290 DisassemblerX64(const NameConverter& converter,
289 UnimplementedOpcodeAction unimplemented_action = 291 UnimplementedOpcodeAction unimplemented_action =
290 ABORT_ON_UNIMPLEMENTED_OPCODE) 292 ABORT_ON_UNIMPLEMENTED_OPCODE)
291 : converter_(converter), 293 : converter_(converter),
292 tmp_buffer_pos_(0), 294 tmp_buffer_pos_(0),
293 abort_on_unimplemented_( 295 abort_on_unimplemented_(unimplemented_action ==
294 unimplemented_action == ABORT_ON_UNIMPLEMENTED_OPCODE), 296 ABORT_ON_UNIMPLEMENTED_OPCODE),
295 rex_(0), 297 rex_(0),
296 operand_size_(0), 298 operand_size_(0),
297 group_1_prefix_(0), 299 group_1_prefix_(0),
300 vex_byte0_(0),
301 vex_byte1_(0),
302 vex_byte2_(0),
298 byte_size_operand_(false), 303 byte_size_operand_(false),
299 instruction_table_(instruction_table.Pointer()) { 304 instruction_table_(instruction_table.Pointer()) {
300 tmp_buffer_[0] = '\0'; 305 tmp_buffer_[0] = '\0';
301 } 306 }
302 307
303 virtual ~DisassemblerX64() { 308 virtual ~DisassemblerX64() {
304 } 309 }
305 310
306 // Writes one disassembled instruction into 'buffer' (0-terminated). 311 // Writes one disassembled instruction into 'buffer' (0-terminated).
307 // Returns the length of the disassembled machine instruction in bytes. 312 // Returns the length of the disassembled machine instruction in bytes.
308 int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); 313 int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
309 314
310 private: 315 private:
311 enum OperandSize { 316 enum OperandSize {
312 OPERAND_BYTE_SIZE = 0, 317 OPERAND_BYTE_SIZE = 0,
313 OPERAND_WORD_SIZE = 1, 318 OPERAND_WORD_SIZE = 1,
314 OPERAND_DOUBLEWORD_SIZE = 2, 319 OPERAND_DOUBLEWORD_SIZE = 2,
315 OPERAND_QUADWORD_SIZE = 3 320 OPERAND_QUADWORD_SIZE = 3
316 }; 321 };
317 322
318 const NameConverter& converter_; 323 const NameConverter& converter_;
319 v8::internal::EmbeddedVector<char, 128> tmp_buffer_; 324 v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
320 unsigned int tmp_buffer_pos_; 325 unsigned int tmp_buffer_pos_;
321 bool abort_on_unimplemented_; 326 bool abort_on_unimplemented_;
322 // Prefixes parsed 327 // Prefixes parsed
323 byte rex_; 328 byte rex_;
324 byte operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0. 329 byte operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0.
325 byte group_1_prefix_; // 0xF2, 0xF3, or (if no group 1 prefix is present) 0. 330 byte group_1_prefix_; // 0xF2, 0xF3, or (if no group 1 prefix is present) 0.
331 byte vex_byte0_; // 0xc4 or 0xc5
332 byte vex_byte1_;
333 byte vex_byte2_; // only for 3 bytes vex prefix
326 // Byte size operand override. 334 // Byte size operand override.
327 bool byte_size_operand_; 335 bool byte_size_operand_;
328 const InstructionTable* const instruction_table_; 336 const InstructionTable* const instruction_table_;
329 337
330 void setRex(byte rex) { 338 void setRex(byte rex) {
331 DCHECK_EQ(0x40, rex & 0xF0); 339 DCHECK_EQ(0x40, rex & 0xF0);
332 rex_ = rex; 340 rex_ = rex;
333 } 341 }
334 342
335 bool rex() { return rex_ != 0; } 343 bool rex() { return rex_ != 0; }
336 344
337 bool rex_b() { return (rex_ & 0x01) != 0; } 345 bool rex_b() { return (rex_ & 0x01) != 0; }
338 346
339 // Actual number of base register given the low bits and the rex.b state. 347 // Actual number of base register given the low bits and the rex.b state.
340 int base_reg(int low_bits) { return low_bits | ((rex_ & 0x01) << 3); } 348 int base_reg(int low_bits) { return low_bits | ((rex_ & 0x01) << 3); }
341 349
342 bool rex_x() { return (rex_ & 0x02) != 0; } 350 bool rex_x() { return (rex_ & 0x02) != 0; }
343 351
344 bool rex_r() { return (rex_ & 0x04) != 0; } 352 bool rex_r() { return (rex_ & 0x04) != 0; }
345 353
346 bool rex_w() { return (rex_ & 0x08) != 0; } 354 bool rex_w() { return (rex_ & 0x08) != 0; }
347 355
356 bool vex_128() {
357 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
358 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
359 return (checked & 4) != 1;
360 }
361
362 bool vex_66() {
363 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
364 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
365 return (checked & 3) == 1;
366 }
367
368 bool vex_f3() {
369 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
370 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
371 return (checked & 3) == 2;
372 }
373
374 bool vex_f2() {
375 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
376 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
377 return (checked & 3) == 3;
378 }
379
380 bool vex_0f() {
381 if (vex_byte0_ == VEX2_PREFIX) return true;
382 return (vex_byte1_ & 3) == 1;
383 }
384
385 bool vex_0f38() {
386 DCHECK(vex_byte0_ == VEX3_PREFIX);
387 return (vex_byte1_ & 3) == 2;
388 }
389
390 bool vex_0f3a() {
391 DCHECK(vex_byte0_ == VEX3_PREFIX);
392 return (vex_byte1_ & 3) == 3;
393 }
394
395 int vex_vreg() {
396 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
397 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
398 return ~(checked >> 3) & 0xf;
399 }
400
348 OperandSize operand_size() { 401 OperandSize operand_size() {
349 if (byte_size_operand_) return OPERAND_BYTE_SIZE; 402 if (byte_size_operand_) return OPERAND_BYTE_SIZE;
350 if (rex_w()) return OPERAND_QUADWORD_SIZE; 403 if (rex_w()) return OPERAND_QUADWORD_SIZE;
351 if (operand_size_ != 0) return OPERAND_WORD_SIZE; 404 if (operand_size_ != 0) return OPERAND_WORD_SIZE;
352 return OPERAND_DOUBLEWORD_SIZE; 405 return OPERAND_DOUBLEWORD_SIZE;
353 } 406 }
354 407
355 char operand_size_code() { 408 char operand_size_code() {
356 return "bwlq"[operand_size()]; 409 return "bwlq"[operand_size()];
357 } 410 }
358 411
412 char float_size_code() { return "sd"[rex_w()]; }
413
359 const char* NameOfCPURegister(int reg) const { 414 const char* NameOfCPURegister(int reg) const {
360 return converter_.NameOfCPURegister(reg); 415 return converter_.NameOfCPURegister(reg);
361 } 416 }
362 417
363 const char* NameOfByteCPURegister(int reg) const { 418 const char* NameOfByteCPURegister(int reg) const {
364 return converter_.NameOfByteCPURegister(reg); 419 return converter_.NameOfByteCPURegister(reg);
365 } 420 }
366 421
367 const char* NameOfXMMRegister(int reg) const { 422 const char* NameOfXMMRegister(int reg) const {
368 return converter_.NameOfXMMRegister(reg); 423 return converter_.NameOfXMMRegister(reg);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 int TwoByteOpcodeInstruction(byte* data); 462 int TwoByteOpcodeInstruction(byte* data);
408 int F6F7Instruction(byte* data); 463 int F6F7Instruction(byte* data);
409 int ShiftInstruction(byte* data); 464 int ShiftInstruction(byte* data);
410 int JumpShort(byte* data); 465 int JumpShort(byte* data);
411 int JumpConditional(byte* data); 466 int JumpConditional(byte* data);
412 int JumpConditionalShort(byte* data); 467 int JumpConditionalShort(byte* data);
413 int SetCC(byte* data); 468 int SetCC(byte* data);
414 int FPUInstruction(byte* data); 469 int FPUInstruction(byte* data);
415 int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start); 470 int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
416 int RegisterFPUInstruction(int escape_opcode, byte modrm_byte); 471 int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
472 int AVXInstruction(byte* data);
417 void AppendToBuffer(const char* format, ...); 473 void AppendToBuffer(const char* format, ...);
418 474
419 void UnimplementedInstruction() { 475 void UnimplementedInstruction() {
420 if (abort_on_unimplemented_) { 476 if (abort_on_unimplemented_) {
421 CHECK(false); 477 CHECK(false);
422 } else { 478 } else {
423 AppendToBuffer("'Unimplemented Instruction'"); 479 AppendToBuffer("'Unimplemented Instruction'");
424 } 480 }
425 } 481 }
426 }; 482 };
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 int DisassemblerX64::SetCC(byte* data) { 860 int DisassemblerX64::SetCC(byte* data) {
805 DCHECK_EQ(0x0F, *data); 861 DCHECK_EQ(0x0F, *data);
806 byte cond = *(data + 1) & 0x0F; 862 byte cond = *(data + 1) & 0x0F;
807 const char* mnem = conditional_code_suffix[cond]; 863 const char* mnem = conditional_code_suffix[cond];
808 AppendToBuffer("set%s%c ", mnem, operand_size_code()); 864 AppendToBuffer("set%s%c ", mnem, operand_size_code());
809 PrintRightByteOperand(data + 2); 865 PrintRightByteOperand(data + 2);
810 return 3; // includes 0x0F 866 return 3; // includes 0x0F
811 } 867 }
812 868
813 869
870 int DisassemblerX64::AVXInstruction(byte* data) {
871 byte opcode = *data;
872 byte* current = data + 1;
873 if (vex_byte0_ == VEX3_PREFIX) {
874 if (vex_128()) {
875 if (vex_66() && vex_0f38()) {
876 int mod, regop, rm, vvvv = vex_vreg();
877 get_modrm(*current, &mod, &regop, &rm);
878 switch (opcode) {
879 case 0x99:
880 AppendToBuffer("vfmadd132s%c %s,%s,", float_size_code(),
881 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
882 current += PrintRightXMMOperand(current);
883 break;
884 case 0xa9:
885 AppendToBuffer("vfmadd213s%c %s,%s,", float_size_code(),
886 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
887 current += PrintRightXMMOperand(current);
888 break;
889 case 0xb9:
890 AppendToBuffer("vfmadd231s%c %s,%s,", float_size_code(),
891 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
892 current += PrintRightXMMOperand(current);
893 break;
894 case 0x9b:
895 AppendToBuffer("vfmsub132s%c %s,%s,", float_size_code(),
896 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
897 current += PrintRightXMMOperand(current);
898 break;
899 case 0xab:
900 AppendToBuffer("vfmsub213s%c %s,%s,", float_size_code(),
901 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
902 current += PrintRightXMMOperand(current);
903 break;
904 case 0xbb:
905 AppendToBuffer("vfmsub231s%c %s,%s,", float_size_code(),
906 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
907 current += PrintRightXMMOperand(current);
908 break;
909 case 0x9d:
910 AppendToBuffer("vfnmadd132s%c %s,%s,", float_size_code(),
911 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
912 current += PrintRightXMMOperand(current);
913 break;
914 case 0xad:
915 AppendToBuffer("vfnmadd213s%c %s,%s,", float_size_code(),
916 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
917 current += PrintRightXMMOperand(current);
918 break;
919 case 0xbd:
920 AppendToBuffer("vfnmadd231s%c %s,%s,", float_size_code(),
921 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
922 current += PrintRightXMMOperand(current);
923 break;
924 case 0x9f:
925 AppendToBuffer("vfnmsub132s%c %s,%s,", float_size_code(),
926 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
927 current += PrintRightXMMOperand(current);
928 break;
929 case 0xaf:
930 AppendToBuffer("vfnmsub213s%c %s,%s,", float_size_code(),
931 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
932 current += PrintRightXMMOperand(current);
933 break;
934 case 0xbf:
935 AppendToBuffer("vfnmsub231s%c %s,%s,", float_size_code(),
936 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
937 current += PrintRightXMMOperand(current);
938 break;
939 default:
940 UnimplementedInstruction();
941 }
942 }
943 } else {
944 UnimplementedInstruction();
945 }
946 } else if (vex_byte0_ == VEX2_PREFIX) {
947 UnimplementedInstruction();
948 } else {
949 UNREACHABLE();
950 }
951
952 return static_cast<int>(current - data);
953 }
954
955
814 // Returns number of bytes used, including *data. 956 // Returns number of bytes used, including *data.
815 int DisassemblerX64::FPUInstruction(byte* data) { 957 int DisassemblerX64::FPUInstruction(byte* data) {
816 byte escape_opcode = *data; 958 byte escape_opcode = *data;
817 DCHECK_EQ(0xD8, escape_opcode & 0xF8); 959 DCHECK_EQ(0xD8, escape_opcode & 0xF8);
818 byte modrm_byte = *(data+1); 960 byte modrm_byte = *(data+1);
819 961
820 if (modrm_byte >= 0xC0) { 962 if (modrm_byte >= 0xC0) {
821 return RegisterFPUInstruction(escape_opcode, modrm_byte); 963 return RegisterFPUInstruction(escape_opcode, modrm_byte);
822 } else { 964 } else {
823 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1); 965 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
1182 AppendToBuffer("%ss %s,", mnemonic, NameOfXMMRegister(regop)); 1324 AppendToBuffer("%ss %s,", mnemonic, NameOfXMMRegister(regop));
1183 current += PrintRightOperand(current); 1325 current += PrintRightOperand(current);
1184 } else if (opcode == 0x2C) { 1326 } else if (opcode == 0x2C) {
1185 // CVTTSS2SI: 1327 // CVTTSS2SI:
1186 // Convert with truncation scalar single-precision FP to dword integer. 1328 // Convert with truncation scalar single-precision FP to dword integer.
1187 int mod, regop, rm; 1329 int mod, regop, rm;
1188 get_modrm(*current, &mod, &regop, &rm); 1330 get_modrm(*current, &mod, &regop, &rm);
1189 AppendToBuffer("cvttss2si%c %s,", 1331 AppendToBuffer("cvttss2si%c %s,",
1190 operand_size_code(), NameOfCPURegister(regop)); 1332 operand_size_code(), NameOfCPURegister(regop));
1191 current += PrintRightXMMOperand(current); 1333 current += PrintRightXMMOperand(current);
1334 } else if (opcode == 0x58) {
1335 int mod, regop, rm;
1336 get_modrm(*current, &mod, &regop, &rm);
1337 AppendToBuffer("addss %s,", NameOfXMMRegister(regop));
1338 current += PrintRightXMMOperand(current);
1339 } else if (opcode == 0x59) {
1340 int mod, regop, rm;
1341 get_modrm(*current, &mod, &regop, &rm);
1342 AppendToBuffer("mulss %s,", NameOfXMMRegister(regop));
1343 current += PrintRightXMMOperand(current);
1192 } else if (opcode == 0x5A) { 1344 } else if (opcode == 0x5A) {
1193 // CVTSS2SD: 1345 // CVTSS2SD:
1194 // Convert scalar single-precision FP to scalar double-precision FP. 1346 // Convert scalar single-precision FP to scalar double-precision FP.
1195 int mod, regop, rm; 1347 int mod, regop, rm;
1196 get_modrm(*current, &mod, &regop, &rm); 1348 get_modrm(*current, &mod, &regop, &rm);
1197 AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop)); 1349 AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
1198 current += PrintRightXMMOperand(current); 1350 current += PrintRightXMMOperand(current);
1351 } else if (opcode == 0x5c) {
1352 int mod, regop, rm;
1353 get_modrm(*current, &mod, &regop, &rm);
1354 AppendToBuffer("subss %s,", NameOfXMMRegister(regop));
1355 current += PrintRightXMMOperand(current);
1356 } else if (opcode == 0x5e) {
1357 int mod, regop, rm;
1358 get_modrm(*current, &mod, &regop, &rm);
1359 AppendToBuffer("divss %s,", NameOfXMMRegister(regop));
1360 current += PrintRightXMMOperand(current);
1199 } else if (opcode == 0x7E) { 1361 } else if (opcode == 0x7E) {
1200 int mod, regop, rm; 1362 int mod, regop, rm;
1201 get_modrm(*current, &mod, &regop, &rm); 1363 get_modrm(*current, &mod, &regop, &rm);
1202 AppendToBuffer("movq %s,", NameOfXMMRegister(regop)); 1364 AppendToBuffer("movq %s,", NameOfXMMRegister(regop));
1203 current += PrintRightXMMOperand(current); 1365 current += PrintRightXMMOperand(current);
1204 } else { 1366 } else {
1205 UnimplementedInstruction(); 1367 UnimplementedInstruction();
1206 } 1368 }
1207 } else if (opcode == 0x1F) { 1369 } else if (opcode == 0x1F) {
1208 // NOP 1370 // NOP
(...skipping 18 matching lines...) Expand all
1227 current += PrintRightXMMOperand(current); 1389 current += PrintRightXMMOperand(current);
1228 1390
1229 } else if (opcode == 0x29) { 1391 } else if (opcode == 0x29) {
1230 // movaps xmm/m128, xmm 1392 // movaps xmm/m128, xmm
1231 int mod, regop, rm; 1393 int mod, regop, rm;
1232 get_modrm(*current, &mod, &regop, &rm); 1394 get_modrm(*current, &mod, &regop, &rm);
1233 AppendToBuffer("movaps "); 1395 AppendToBuffer("movaps ");
1234 current += PrintRightXMMOperand(current); 1396 current += PrintRightXMMOperand(current);
1235 AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1397 AppendToBuffer(",%s", NameOfXMMRegister(regop));
1236 1398
1399 } else if (opcode == 0x2e) {
1400 int mod, regop, rm;
1401 get_modrm(*current, &mod, &regop, &rm);
1402 AppendToBuffer("ucomiss %s,", NameOfXMMRegister(regop));
1403 current += PrintRightXMMOperand(current);
1237 } else if (opcode == 0xA2) { 1404 } else if (opcode == 0xA2) {
1238 // CPUID 1405 // CPUID
1239 AppendToBuffer("%s", mnemonic); 1406 AppendToBuffer("%s", mnemonic);
1240 1407
1241 } else if ((opcode & 0xF0) == 0x40) { 1408 } else if ((opcode & 0xF0) == 0x40) {
1242 // CMOVcc: conditional move. 1409 // CMOVcc: conditional move.
1243 int condition = opcode & 0x0F; 1410 int condition = opcode & 0x0F;
1244 const InstructionDesc& idesc = cmov_instructions[condition]; 1411 const InstructionDesc& idesc = cmov_instructions[condition];
1245 byte_size_operand_ = idesc.byte_size_operation; 1412 byte_size_operand_ = idesc.byte_size_operation;
1246 current += PrintOperands(idesc.mnem, idesc.op_order_, current); 1413 current += PrintOperands(idesc.mnem, idesc.op_order_, current);
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
1380 // Scan for prefixes. 1547 // Scan for prefixes.
1381 while (true) { 1548 while (true) {
1382 current = *data; 1549 current = *data;
1383 if (current == OPERAND_SIZE_OVERRIDE_PREFIX) { // Group 3 prefix. 1550 if (current == OPERAND_SIZE_OVERRIDE_PREFIX) { // Group 3 prefix.
1384 operand_size_ = current; 1551 operand_size_ = current;
1385 } else if ((current & 0xF0) == 0x40) { // REX prefix. 1552 } else if ((current & 0xF0) == 0x40) { // REX prefix.
1386 setRex(current); 1553 setRex(current);
1387 if (rex_w()) AppendToBuffer("REX.W "); 1554 if (rex_w()) AppendToBuffer("REX.W ");
1388 } else if ((current & 0xFE) == 0xF2) { // Group 1 prefix (0xF2 or 0xF3). 1555 } else if ((current & 0xFE) == 0xF2) { // Group 1 prefix (0xF2 or 0xF3).
1389 group_1_prefix_ = current; 1556 group_1_prefix_ = current;
1557 } else if (current == VEX3_PREFIX) {
1558 vex_byte0_ = current;
1559 vex_byte1_ = *(data + 1);
1560 vex_byte2_ = *(data + 2);
1561 setRex(0x40 | (~(vex_byte1_ >> 5) & 7) | ((vex_byte2_ >> 4) & 8));
1562 data += 2;
1563 } else if (current == VEX2_PREFIX) {
1564 vex_byte0_ = current;
1565 vex_byte1_ = *(data + 1);
1566 setRex(0x40 | (~(vex_byte1_ >> 5) & 4));
1567 data++;
1390 } else { // Not a prefix - an opcode. 1568 } else { // Not a prefix - an opcode.
1391 break; 1569 break;
1392 } 1570 }
1393 data++; 1571 data++;
1394 } 1572 }
1395 1573
1396 const InstructionDesc& idesc = instruction_table_->Get(current); 1574 // Decode AVX instructions.
1397 byte_size_operand_ = idesc.byte_size_operation; 1575 if (vex_byte0_ != 0) {
1398 switch (idesc.type) { 1576 processed = true;
1399 case ZERO_OPERANDS_INSTR: 1577 data += AVXInstruction(data);
1400 if (current >= 0xA4 && current <= 0xA7) { 1578 } else {
1401 // String move or compare operations. 1579 const InstructionDesc& idesc = instruction_table_->Get(current);
1402 if (group_1_prefix_ == REP_PREFIX) { 1580 byte_size_operand_ = idesc.byte_size_operation;
1403 // REP. 1581 switch (idesc.type) {
1404 AppendToBuffer("rep "); 1582 case ZERO_OPERANDS_INSTR:
1583 if (current >= 0xA4 && current <= 0xA7) {
1584 // String move or compare operations.
1585 if (group_1_prefix_ == REP_PREFIX) {
1586 // REP.
1587 AppendToBuffer("rep ");
1588 }
1589 if (rex_w()) AppendToBuffer("REX.W ");
1590 AppendToBuffer("%s%c", idesc.mnem, operand_size_code());
1591 } else {
1592 AppendToBuffer("%s", idesc.mnem, operand_size_code());
1405 } 1593 }
1406 if (rex_w()) AppendToBuffer("REX.W "); 1594 data++;
1407 AppendToBuffer("%s%c", idesc.mnem, operand_size_code()); 1595 break;
1408 } else { 1596
1409 AppendToBuffer("%s", idesc.mnem, operand_size_code()); 1597 case TWO_OPERANDS_INSTR:
1598 data++;
1599 data += PrintOperands(idesc.mnem, idesc.op_order_, data);
1600 break;
1601
1602 case JUMP_CONDITIONAL_SHORT_INSTR:
1603 data += JumpConditionalShort(data);
1604 break;
1605
1606 case REGISTER_INSTR:
1607 AppendToBuffer("%s%c %s", idesc.mnem, operand_size_code(),
1608 NameOfCPURegister(base_reg(current & 0x07)));
1609 data++;
1610 break;
1611 case PUSHPOP_INSTR:
1612 AppendToBuffer("%s %s", idesc.mnem,
1613 NameOfCPURegister(base_reg(current & 0x07)));
1614 data++;
1615 break;
1616 case MOVE_REG_INSTR: {
1617 byte* addr = NULL;
1618 switch (operand_size()) {
1619 case OPERAND_WORD_SIZE:
1620 addr =
1621 reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1));
1622 data += 3;
1623 break;
1624 case OPERAND_DOUBLEWORD_SIZE:
1625 addr =
1626 reinterpret_cast<byte*>(*reinterpret_cast<uint32_t*>(data + 1));
1627 data += 5;
1628 break;
1629 case OPERAND_QUADWORD_SIZE:
1630 addr =
1631 reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1));
1632 data += 9;
1633 break;
1634 default:
1635 UNREACHABLE();
1636 }
1637 AppendToBuffer("mov%c %s,%s", operand_size_code(),
1638 NameOfCPURegister(base_reg(current & 0x07)),
1639 NameOfAddress(addr));
1640 break;
1410 } 1641 }
1411 data++;
1412 break;
1413 1642
1414 case TWO_OPERANDS_INSTR: 1643 case CALL_JUMP_INSTR: {
1415 data++; 1644 byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
1416 data += PrintOperands(idesc.mnem, idesc.op_order_, data); 1645 AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
1417 break; 1646 data += 5;
1647 break;
1648 }
1418 1649
1419 case JUMP_CONDITIONAL_SHORT_INSTR: 1650 case SHORT_IMMEDIATE_INSTR: {
1420 data += JumpConditionalShort(data); 1651 byte* addr =
1421 break; 1652 reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
1653 AppendToBuffer("%s rax,%s", idesc.mnem, NameOfAddress(addr));
1654 data += 5;
1655 break;
1656 }
1422 1657
1423 case REGISTER_INSTR: 1658 case NO_INSTR:
1424 AppendToBuffer("%s%c %s", 1659 processed = false;
1425 idesc.mnem, 1660 break;
1426 operand_size_code(), 1661
1427 NameOfCPURegister(base_reg(current & 0x07))); 1662 default:
1428 data++; 1663 UNIMPLEMENTED(); // This type is not implemented.
1429 break;
1430 case PUSHPOP_INSTR:
1431 AppendToBuffer("%s %s",
1432 idesc.mnem,
1433 NameOfCPURegister(base_reg(current & 0x07)));
1434 data++;
1435 break;
1436 case MOVE_REG_INSTR: {
1437 byte* addr = NULL;
1438 switch (operand_size()) {
1439 case OPERAND_WORD_SIZE:
1440 addr = reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1));
1441 data += 3;
1442 break;
1443 case OPERAND_DOUBLEWORD_SIZE:
1444 addr =
1445 reinterpret_cast<byte*>(*reinterpret_cast<uint32_t*>(data + 1));
1446 data += 5;
1447 break;
1448 case OPERAND_QUADWORD_SIZE:
1449 addr = reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1));
1450 data += 9;
1451 break;
1452 default:
1453 UNREACHABLE();
1454 }
1455 AppendToBuffer("mov%c %s,%s",
1456 operand_size_code(),
1457 NameOfCPURegister(base_reg(current & 0x07)),
1458 NameOfAddress(addr));
1459 break;
1460 } 1664 }
1461
1462 case CALL_JUMP_INSTR: {
1463 byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
1464 AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
1465 data += 5;
1466 break;
1467 }
1468
1469 case SHORT_IMMEDIATE_INSTR: {
1470 byte* addr =
1471 reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
1472 AppendToBuffer("%s rax,%s", idesc.mnem, NameOfAddress(addr));
1473 data += 5;
1474 break;
1475 }
1476
1477 case NO_INSTR:
1478 processed = false;
1479 break;
1480
1481 default:
1482 UNIMPLEMENTED(); // This type is not implemented.
1483 } 1665 }
1484 1666
1485 // The first byte didn't match any of the simple opcodes, so we 1667 // The first byte didn't match any of the simple opcodes, so we
1486 // need to do special processing on it. 1668 // need to do special processing on it.
1487 if (!processed) { 1669 if (!processed) {
1488 switch (*data) { 1670 switch (*data) {
1489 case 0xC2: 1671 case 0xC2:
1490 AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data + 1)); 1672 AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data + 1));
1491 data += 3; 1673 data += 3;
1492 break; 1674 break;
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
1910 for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) { 2092 for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) {
1911 fprintf(f, " "); 2093 fprintf(f, " ");
1912 } 2094 }
1913 fprintf(f, " %s\n", buffer.start()); 2095 fprintf(f, " %s\n", buffer.start());
1914 } 2096 }
1915 } 2097 }
1916 2098
1917 } // namespace disasm 2099 } // namespace disasm
1918 2100
1919 #endif // V8_TARGET_ARCH_X64 2101 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | test/cctest/test-assembler-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698