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

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

Issue 770183002: [ia32] Introduce vex prefix version of float64 arithmetic binop (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: 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/ia32/assembler-ia32.cc ('k') | test/cctest/test-disasm-ia32.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 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 } 239 }
240 } 240 }
241 241
242 242
243 // The IA32 disassembler implementation. 243 // The IA32 disassembler implementation.
244 class DisassemblerIA32 { 244 class DisassemblerIA32 {
245 public: 245 public:
246 DisassemblerIA32(const NameConverter& converter, 246 DisassemblerIA32(const NameConverter& converter,
247 bool abort_on_unimplemented = true) 247 bool abort_on_unimplemented = true)
248 : converter_(converter), 248 : converter_(converter),
249 vex_byte0_(0),
250 vex_byte1_(0),
251 vex_byte2_(0),
249 instruction_table_(InstructionTable::get_instance()), 252 instruction_table_(InstructionTable::get_instance()),
250 tmp_buffer_pos_(0), 253 tmp_buffer_pos_(0),
251 abort_on_unimplemented_(abort_on_unimplemented) { 254 abort_on_unimplemented_(abort_on_unimplemented) {
252 tmp_buffer_[0] = '\0'; 255 tmp_buffer_[0] = '\0';
253 } 256 }
254 257
255 virtual ~DisassemblerIA32() {} 258 virtual ~DisassemblerIA32() {}
256 259
257 // Writes one disassembled instruction into 'buffer' (0-terminated). 260 // Writes one disassembled instruction into 'buffer' (0-terminated).
258 // Returns the length of the disassembled machine instruction in bytes. 261 // Returns the length of the disassembled machine instruction in bytes.
259 int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); 262 int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
260 263
261 private: 264 private:
262 const NameConverter& converter_; 265 const NameConverter& converter_;
266 byte vex_byte0_; // 0xc4 or 0xc5
267 byte vex_byte1_;
268 byte vex_byte2_; // only for 3 bytes vex prefix
263 InstructionTable* instruction_table_; 269 InstructionTable* instruction_table_;
264 v8::internal::EmbeddedVector<char, 128> tmp_buffer_; 270 v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
265 unsigned int tmp_buffer_pos_; 271 unsigned int tmp_buffer_pos_;
266 bool abort_on_unimplemented_; 272 bool abort_on_unimplemented_;
267 273
268 enum { 274 enum {
269 eax = 0, 275 eax = 0,
270 ecx = 1, 276 ecx = 1,
271 edx = 2, 277 edx = 2,
272 ebx = 3, 278 ebx = 3,
273 esp = 4, 279 esp = 4,
274 ebp = 5, 280 ebp = 5,
275 esi = 6, 281 esi = 6,
276 edi = 7 282 edi = 7
277 }; 283 };
278 284
279 285
280 enum ShiftOpcodeExtension { 286 enum ShiftOpcodeExtension {
281 kROL = 0, 287 kROL = 0,
282 kROR = 1, 288 kROR = 1,
283 kRCL = 2, 289 kRCL = 2,
284 kRCR = 3, 290 kRCR = 3,
285 kSHL = 4, 291 kSHL = 4,
286 KSHR = 5, 292 KSHR = 5,
287 kSAR = 7 293 kSAR = 7
288 }; 294 };
289 295
296 bool vex_128() {
297 DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
298 byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
299 return (checked & 4) != 1;
300 }
301
302 bool vex_66() {
303 DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
304 byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
305 return (checked & 3) == 1;
306 }
307
308 bool vex_f3() {
309 DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
310 byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
311 return (checked & 3) == 2;
312 }
313
314 bool vex_f2() {
315 DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
316 byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
317 return (checked & 3) == 3;
318 }
319
320 bool vex_w() {
321 if (vex_byte0_ == 0xc5) return false;
322 return (vex_byte2_ & 0x80) == 1;
323 }
324
325 bool vex_0f() {
326 if (vex_byte0_ == 0xc5) return true;
327 return (vex_byte1_ & 3) == 1;
328 }
329
330 bool vex_0f38() {
331 if (vex_byte0_ == 0xc5) return false;
332 return (vex_byte1_ & 3) == 2;
333 }
334
335 bool vex_0f3a() {
336 if (vex_byte0_ == 0xc5) return false;
337 return (vex_byte1_ & 3) == 3;
338 }
339
340 int vex_vreg() {
341 DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
342 byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
343 return ~(checked >> 3) & 0xf;
344 }
345
346 char float_size_code() { return "sd"[vex_w()]; }
290 347
291 const char* NameOfCPURegister(int reg) const { 348 const char* NameOfCPURegister(int reg) const {
292 return converter_.NameOfCPURegister(reg); 349 return converter_.NameOfCPURegister(reg);
293 } 350 }
294 351
295 352
296 const char* NameOfByteCPURegister(int reg) const { 353 const char* NameOfByteCPURegister(int reg) const {
297 return converter_.NameOfByteCPURegister(reg); 354 return converter_.NameOfByteCPURegister(reg);
298 } 355 }
299 356
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 int F7Instruction(byte* data); 390 int F7Instruction(byte* data);
334 int D1D3C1Instruction(byte* data); 391 int D1D3C1Instruction(byte* data);
335 int JumpShort(byte* data); 392 int JumpShort(byte* data);
336 int JumpConditional(byte* data, const char* comment); 393 int JumpConditional(byte* data, const char* comment);
337 int JumpConditionalShort(byte* data, const char* comment); 394 int JumpConditionalShort(byte* data, const char* comment);
338 int SetCC(byte* data); 395 int SetCC(byte* data);
339 int CMov(byte* data); 396 int CMov(byte* data);
340 int FPUInstruction(byte* data); 397 int FPUInstruction(byte* data);
341 int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start); 398 int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
342 int RegisterFPUInstruction(int escape_opcode, byte modrm_byte); 399 int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
400 int AVXInstruction(byte* data);
343 void AppendToBuffer(const char* format, ...); 401 void AppendToBuffer(const char* format, ...);
344 402
345 403
346 void UnimplementedInstruction() { 404 void UnimplementedInstruction() {
347 if (abort_on_unimplemented_) { 405 if (abort_on_unimplemented_) {
348 UNIMPLEMENTED(); 406 UNIMPLEMENTED();
349 } else { 407 } else {
350 AppendToBuffer("'Unimplemented Instruction'"); 408 AppendToBuffer("'Unimplemented Instruction'");
351 } 409 }
352 } 410 }
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
672 // Returns number of bytes used, including *data. 730 // Returns number of bytes used, including *data.
673 int DisassemblerIA32::CMov(byte* data) { 731 int DisassemblerIA32::CMov(byte* data) {
674 DCHECK_EQ(0x0F, *data); 732 DCHECK_EQ(0x0F, *data);
675 byte cond = *(data + 1) & 0x0F; 733 byte cond = *(data + 1) & 0x0F;
676 const char* mnem = conditional_move_mnem[cond]; 734 const char* mnem = conditional_move_mnem[cond];
677 int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2); 735 int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2);
678 return 2 + op_size; // includes 0x0F 736 return 2 + op_size; // includes 0x0F
679 } 737 }
680 738
681 739
740 int DisassemblerIA32::AVXInstruction(byte* data) {
741 byte opcode = *data;
742 byte* current = data + 1;
743 if (vex_f2() && vex_0f()) {
744 int mod, regop, rm, vvvv = vex_vreg();
745 get_modrm(*current, &mod, &regop, &rm);
746 switch (opcode) {
747 case 0x58:
748 AppendToBuffer("vaddsd %s,%s,", NameOfXMMRegister(regop),
749 NameOfXMMRegister(vvvv));
750 current += PrintRightXMMOperand(current);
751 break;
752 case 0x59:
753 AppendToBuffer("vmulsd %s,%s,", NameOfXMMRegister(regop),
754 NameOfXMMRegister(vvvv));
755 current += PrintRightXMMOperand(current);
756 break;
757 case 0x5c:
758 AppendToBuffer("vsubsd %s,%s,", NameOfXMMRegister(regop),
759 NameOfXMMRegister(vvvv));
760 current += PrintRightXMMOperand(current);
761 break;
762 case 0x5e:
763 AppendToBuffer("vdivsd %s,%s,", NameOfXMMRegister(regop),
764 NameOfXMMRegister(vvvv));
765 current += PrintRightXMMOperand(current);
766 break;
767 default:
768 UnimplementedInstruction();
769 }
770 } else {
771 UnimplementedInstruction();
772 }
773
774 return static_cast<int>(current - data);
775 }
776
777
682 // Returns number of bytes used, including *data. 778 // Returns number of bytes used, including *data.
683 int DisassemblerIA32::FPUInstruction(byte* data) { 779 int DisassemblerIA32::FPUInstruction(byte* data) {
684 byte escape_opcode = *data; 780 byte escape_opcode = *data;
685 DCHECK_EQ(0xD8, escape_opcode & 0xF8); 781 DCHECK_EQ(0xD8, escape_opcode & 0xF8);
686 byte modrm_byte = *(data+1); 782 byte modrm_byte = *(data+1);
687 783
688 if (modrm_byte >= 0xC0) { 784 if (modrm_byte >= 0xC0) {
689 return RegisterFPUInstruction(escape_opcode, modrm_byte); 785 return RegisterFPUInstruction(escape_opcode, modrm_byte);
690 } else { 786 } else {
691 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1); 787 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
896 byte* data = instr; 992 byte* data = instr;
897 // Check for hints. 993 // Check for hints.
898 const char* branch_hint = NULL; 994 const char* branch_hint = NULL;
899 // We use these two prefixes only with branch prediction 995 // We use these two prefixes only with branch prediction
900 if (*data == 0x3E /*ds*/) { 996 if (*data == 0x3E /*ds*/) {
901 branch_hint = "predicted taken"; 997 branch_hint = "predicted taken";
902 data++; 998 data++;
903 } else if (*data == 0x2E /*cs*/) { 999 } else if (*data == 0x2E /*cs*/) {
904 branch_hint = "predicted not taken"; 1000 branch_hint = "predicted not taken";
905 data++; 1001 data++;
1002 } else if (*data == 0xC4 && *(data + 1) >= 0xc0) {
1003 vex_byte0_ = *data;
1004 vex_byte1_ = *(data + 1);
1005 vex_byte2_ = *(data + 2);
1006 data += 3;
1007 } else if (*data == 0xC5 && *(data + 1) >= 0xc0) {
1008 vex_byte0_ = *data;
1009 vex_byte1_ = *(data + 1);
1010 data += 2;
906 } 1011 }
1012
907 bool processed = true; // Will be set to false if the current instruction 1013 bool processed = true; // Will be set to false if the current instruction
908 // is not in 'instructions' table. 1014 // is not in 'instructions' table.
909 const InstructionDesc& idesc = instruction_table_->Get(*data); 1015 // Decode AVX instructions.
910 switch (idesc.type) { 1016 if (vex_byte0_ != 0) {
911 case ZERO_OPERANDS_INSTR: 1017 data += AVXInstruction(data);
912 AppendToBuffer(idesc.mnem); 1018 } else {
913 data++; 1019 const InstructionDesc& idesc = instruction_table_->Get(*data);
914 break; 1020 switch (idesc.type) {
1021 case ZERO_OPERANDS_INSTR:
1022 AppendToBuffer(idesc.mnem);
1023 data++;
1024 break;
915 1025
916 case TWO_OPERANDS_INSTR: 1026 case TWO_OPERANDS_INSTR:
917 data++; 1027 data++;
918 data += PrintOperands(idesc.mnem, idesc.op_order_, data); 1028 data += PrintOperands(idesc.mnem, idesc.op_order_, data);
919 break; 1029 break;
920 1030
921 case JUMP_CONDITIONAL_SHORT_INSTR: 1031 case JUMP_CONDITIONAL_SHORT_INSTR:
922 data += JumpConditionalShort(data, branch_hint); 1032 data += JumpConditionalShort(data, branch_hint);
923 break; 1033 break;
924 1034
925 case REGISTER_INSTR: 1035 case REGISTER_INSTR:
926 AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07)); 1036 AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07));
927 data++; 1037 data++;
928 break; 1038 break;
929 1039
930 case MOVE_REG_INSTR: { 1040 case MOVE_REG_INSTR: {
931 byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1)); 1041 byte* addr =
932 AppendToBuffer("mov %s,%s", 1042 reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
933 NameOfCPURegister(*data & 0x07), 1043 AppendToBuffer("mov %s,%s", NameOfCPURegister(*data & 0x07),
934 NameOfAddress(addr)); 1044 NameOfAddress(addr));
935 data += 5; 1045 data += 5;
936 break; 1046 break;
1047 }
1048
1049 case CALL_JUMP_INSTR: {
1050 byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
1051 AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
1052 data += 5;
1053 break;
1054 }
1055
1056 case SHORT_IMMEDIATE_INSTR: {
1057 byte* addr =
1058 reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
1059 AppendToBuffer("%s eax,%s", idesc.mnem, NameOfAddress(addr));
1060 data += 5;
1061 break;
1062 }
1063
1064 case BYTE_IMMEDIATE_INSTR: {
1065 AppendToBuffer("%s al,0x%x", idesc.mnem, data[1]);
1066 data += 2;
1067 break;
1068 }
1069
1070 case NO_INSTR:
1071 processed = false;
1072 break;
1073
1074 default:
1075 UNIMPLEMENTED(); // This type is not implemented.
937 } 1076 }
938
939 case CALL_JUMP_INSTR: {
940 byte* addr = data + *reinterpret_cast<int32_t*>(data+1) + 5;
941 AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
942 data += 5;
943 break;
944 }
945
946 case SHORT_IMMEDIATE_INSTR: {
947 byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1));
948 AppendToBuffer("%s eax,%s", idesc.mnem, NameOfAddress(addr));
949 data += 5;
950 break;
951 }
952
953 case BYTE_IMMEDIATE_INSTR: {
954 AppendToBuffer("%s al,0x%x", idesc.mnem, data[1]);
955 data += 2;
956 break;
957 }
958
959 case NO_INSTR:
960 processed = false;
961 break;
962
963 default:
964 UNIMPLEMENTED(); // This type is not implemented.
965 } 1077 }
966 //---------------------------- 1078 //----------------------------
967 if (!processed) { 1079 if (!processed) {
968 switch (*data) { 1080 switch (*data) {
969 case 0xC2: 1081 case 0xC2:
970 AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data+1)); 1082 AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data+1));
971 data += 3; 1083 data += 3;
972 break; 1084 break;
973 1085
974 case 0x6B: { 1086 case 0x6B: {
(...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after
1779 fprintf(f, " "); 1891 fprintf(f, " ");
1780 } 1892 }
1781 fprintf(f, " %s\n", buffer.start()); 1893 fprintf(f, " %s\n", buffer.start());
1782 } 1894 }
1783 } 1895 }
1784 1896
1785 1897
1786 } // namespace disasm 1898 } // namespace disasm
1787 1899
1788 #endif // V8_TARGET_ARCH_IA32 1900 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/assembler-ia32.cc ('k') | test/cctest/test-disasm-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698