OLD | NEW |
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 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 | 209 |
210 | 210 |
211 void InstructionTable::CopyTable(const ByteMnemonic bm[], | 211 void InstructionTable::CopyTable(const ByteMnemonic bm[], |
212 InstructionType type) { | 212 InstructionType type) { |
213 for (int i = 0; bm[i].b >= 0; i++) { | 213 for (int i = 0; bm[i].b >= 0; i++) { |
214 InstructionDesc* id = &instructions_[bm[i].b]; | 214 InstructionDesc* id = &instructions_[bm[i].b]; |
215 id->mnem = bm[i].mnem; | 215 id->mnem = bm[i].mnem; |
216 OperandType op_order = bm[i].op_order_; | 216 OperandType op_order = bm[i].op_order_; |
217 id->op_order_ = | 217 id->op_order_ = |
218 static_cast<OperandType>(op_order & ~BYTE_SIZE_OPERAND_FLAG); | 218 static_cast<OperandType>(op_order & ~BYTE_SIZE_OPERAND_FLAG); |
219 ASSERT_EQ(NO_INSTR, id->type); // Information not already entered | 219 DCHECK_EQ(NO_INSTR, id->type); // Information not already entered |
220 id->type = type; | 220 id->type = type; |
221 id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0); | 221 id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0); |
222 } | 222 } |
223 } | 223 } |
224 | 224 |
225 | 225 |
226 void InstructionTable::SetTableRange(InstructionType type, | 226 void InstructionTable::SetTableRange(InstructionType type, |
227 byte start, | 227 byte start, |
228 byte end, | 228 byte end, |
229 bool byte_size, | 229 bool byte_size, |
230 const char* mnem) { | 230 const char* mnem) { |
231 for (byte b = start; b <= end; b++) { | 231 for (byte b = start; b <= end; b++) { |
232 InstructionDesc* id = &instructions_[b]; | 232 InstructionDesc* id = &instructions_[b]; |
233 ASSERT_EQ(NO_INSTR, id->type); // Information not already entered | 233 DCHECK_EQ(NO_INSTR, id->type); // Information not already entered |
234 id->mnem = mnem; | 234 id->mnem = mnem; |
235 id->type = type; | 235 id->type = type; |
236 id->byte_size_operation = byte_size; | 236 id->byte_size_operation = byte_size; |
237 } | 237 } |
238 } | 238 } |
239 | 239 |
240 | 240 |
241 void InstructionTable::AddJumpConditionalShort() { | 241 void InstructionTable::AddJumpConditionalShort() { |
242 for (byte b = 0x70; b <= 0x7F; b++) { | 242 for (byte b = 0x70; b <= 0x7F; b++) { |
243 InstructionDesc* id = &instructions_[b]; | 243 InstructionDesc* id = &instructions_[b]; |
244 ASSERT_EQ(NO_INSTR, id->type); // Information not already entered | 244 DCHECK_EQ(NO_INSTR, id->type); // Information not already entered |
245 id->mnem = NULL; // Computed depending on condition code. | 245 id->mnem = NULL; // Computed depending on condition code. |
246 id->type = JUMP_CONDITIONAL_SHORT_INSTR; | 246 id->type = JUMP_CONDITIONAL_SHORT_INSTR; |
247 } | 247 } |
248 } | 248 } |
249 | 249 |
250 | 250 |
251 static v8::base::LazyInstance<InstructionTable>::type instruction_table = | 251 static v8::base::LazyInstance<InstructionTable>::type instruction_table = |
252 LAZY_INSTANCE_INITIALIZER; | 252 LAZY_INSTANCE_INITIALIZER; |
253 | 253 |
254 | 254 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 bool abort_on_unimplemented_; | 321 bool abort_on_unimplemented_; |
322 // Prefixes parsed | 322 // Prefixes parsed |
323 byte rex_; | 323 byte rex_; |
324 byte operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0. | 324 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. | 325 byte group_1_prefix_; // 0xF2, 0xF3, or (if no group 1 prefix is present) 0. |
326 // Byte size operand override. | 326 // Byte size operand override. |
327 bool byte_size_operand_; | 327 bool byte_size_operand_; |
328 const InstructionTable* const instruction_table_; | 328 const InstructionTable* const instruction_table_; |
329 | 329 |
330 void setRex(byte rex) { | 330 void setRex(byte rex) { |
331 ASSERT_EQ(0x40, rex & 0xF0); | 331 DCHECK_EQ(0x40, rex & 0xF0); |
332 rex_ = rex; | 332 rex_ = rex; |
333 } | 333 } |
334 | 334 |
335 bool rex() { return rex_ != 0; } | 335 bool rex() { return rex_ != 0; } |
336 | 336 |
337 bool rex_b() { return (rex_ & 0x01) != 0; } | 337 bool rex_b() { return (rex_ & 0x01) != 0; } |
338 | 338 |
339 // Actual number of base register given the low bits and the rex.b state. | 339 // 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); } | 340 int base_reg(int low_bits) { return low_bits | ((rex_ & 0x01) << 3); } |
341 | 341 |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
654 AppendToBuffer(",0x"); | 654 AppendToBuffer(",0x"); |
655 OperandSize immediate_size = | 655 OperandSize immediate_size = |
656 byte_size_immediate ? OPERAND_BYTE_SIZE : operand_size(); | 656 byte_size_immediate ? OPERAND_BYTE_SIZE : operand_size(); |
657 count += PrintImmediate(data + 1 + count, immediate_size); | 657 count += PrintImmediate(data + 1 + count, immediate_size); |
658 return 1 + count; | 658 return 1 + count; |
659 } | 659 } |
660 | 660 |
661 | 661 |
662 // Returns number of bytes used, including *data. | 662 // Returns number of bytes used, including *data. |
663 int DisassemblerX64::F6F7Instruction(byte* data) { | 663 int DisassemblerX64::F6F7Instruction(byte* data) { |
664 ASSERT(*data == 0xF7 || *data == 0xF6); | 664 DCHECK(*data == 0xF7 || *data == 0xF6); |
665 byte modrm = *(data + 1); | 665 byte modrm = *(data + 1); |
666 int mod, regop, rm; | 666 int mod, regop, rm; |
667 get_modrm(modrm, &mod, ®op, &rm); | 667 get_modrm(modrm, &mod, ®op, &rm); |
668 if (mod == 3 && regop != 0) { | 668 if (mod == 3 && regop != 0) { |
669 const char* mnem = NULL; | 669 const char* mnem = NULL; |
670 switch (regop) { | 670 switch (regop) { |
671 case 2: | 671 case 2: |
672 mnem = "not"; | 672 mnem = "not"; |
673 break; | 673 break; |
674 case 3: | 674 case 3: |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
743 case 5: | 743 case 5: |
744 mnem = "shr"; | 744 mnem = "shr"; |
745 break; | 745 break; |
746 case 7: | 746 case 7: |
747 mnem = "sar"; | 747 mnem = "sar"; |
748 break; | 748 break; |
749 default: | 749 default: |
750 UnimplementedInstruction(); | 750 UnimplementedInstruction(); |
751 return num_bytes; | 751 return num_bytes; |
752 } | 752 } |
753 ASSERT_NE(NULL, mnem); | 753 DCHECK_NE(NULL, mnem); |
754 if (op == 0xD0) { | 754 if (op == 0xD0) { |
755 imm8 = 1; | 755 imm8 = 1; |
756 } else if (op == 0xC0) { | 756 } else if (op == 0xC0) { |
757 imm8 = *(data + 2); | 757 imm8 = *(data + 2); |
758 num_bytes = 3; | 758 num_bytes = 3; |
759 } | 759 } |
760 AppendToBuffer("%s%c %s,", | 760 AppendToBuffer("%s%c %s,", |
761 mnem, | 761 mnem, |
762 operand_size_code(), | 762 operand_size_code(), |
763 byte_size_operand_ ? NameOfByteCPURegister(rm) | 763 byte_size_operand_ ? NameOfByteCPURegister(rm) |
764 : NameOfCPURegister(rm)); | 764 : NameOfCPURegister(rm)); |
765 if (op == 0xD2) { | 765 if (op == 0xD2) { |
766 AppendToBuffer("cl"); | 766 AppendToBuffer("cl"); |
767 } else { | 767 } else { |
768 AppendToBuffer("%d", imm8); | 768 AppendToBuffer("%d", imm8); |
769 } | 769 } |
770 return num_bytes; | 770 return num_bytes; |
771 } | 771 } |
772 | 772 |
773 | 773 |
774 // Returns number of bytes used, including *data. | 774 // Returns number of bytes used, including *data. |
775 int DisassemblerX64::JumpShort(byte* data) { | 775 int DisassemblerX64::JumpShort(byte* data) { |
776 ASSERT_EQ(0xEB, *data); | 776 DCHECK_EQ(0xEB, *data); |
777 byte b = *(data + 1); | 777 byte b = *(data + 1); |
778 byte* dest = data + static_cast<int8_t>(b) + 2; | 778 byte* dest = data + static_cast<int8_t>(b) + 2; |
779 AppendToBuffer("jmp %s", NameOfAddress(dest)); | 779 AppendToBuffer("jmp %s", NameOfAddress(dest)); |
780 return 2; | 780 return 2; |
781 } | 781 } |
782 | 782 |
783 | 783 |
784 // Returns number of bytes used, including *data. | 784 // Returns number of bytes used, including *data. |
785 int DisassemblerX64::JumpConditional(byte* data) { | 785 int DisassemblerX64::JumpConditional(byte* data) { |
786 ASSERT_EQ(0x0F, *data); | 786 DCHECK_EQ(0x0F, *data); |
787 byte cond = *(data + 1) & 0x0F; | 787 byte cond = *(data + 1) & 0x0F; |
788 byte* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6; | 788 byte* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6; |
789 const char* mnem = conditional_code_suffix[cond]; | 789 const char* mnem = conditional_code_suffix[cond]; |
790 AppendToBuffer("j%s %s", mnem, NameOfAddress(dest)); | 790 AppendToBuffer("j%s %s", mnem, NameOfAddress(dest)); |
791 return 6; // includes 0x0F | 791 return 6; // includes 0x0F |
792 } | 792 } |
793 | 793 |
794 | 794 |
795 // Returns number of bytes used, including *data. | 795 // Returns number of bytes used, including *data. |
796 int DisassemblerX64::JumpConditionalShort(byte* data) { | 796 int DisassemblerX64::JumpConditionalShort(byte* data) { |
797 byte cond = *data & 0x0F; | 797 byte cond = *data & 0x0F; |
798 byte b = *(data + 1); | 798 byte b = *(data + 1); |
799 byte* dest = data + static_cast<int8_t>(b) + 2; | 799 byte* dest = data + static_cast<int8_t>(b) + 2; |
800 const char* mnem = conditional_code_suffix[cond]; | 800 const char* mnem = conditional_code_suffix[cond]; |
801 AppendToBuffer("j%s %s", mnem, NameOfAddress(dest)); | 801 AppendToBuffer("j%s %s", mnem, NameOfAddress(dest)); |
802 return 2; | 802 return 2; |
803 } | 803 } |
804 | 804 |
805 | 805 |
806 // Returns number of bytes used, including *data. | 806 // Returns number of bytes used, including *data. |
807 int DisassemblerX64::SetCC(byte* data) { | 807 int DisassemblerX64::SetCC(byte* data) { |
808 ASSERT_EQ(0x0F, *data); | 808 DCHECK_EQ(0x0F, *data); |
809 byte cond = *(data + 1) & 0x0F; | 809 byte cond = *(data + 1) & 0x0F; |
810 const char* mnem = conditional_code_suffix[cond]; | 810 const char* mnem = conditional_code_suffix[cond]; |
811 AppendToBuffer("set%s%c ", mnem, operand_size_code()); | 811 AppendToBuffer("set%s%c ", mnem, operand_size_code()); |
812 PrintRightByteOperand(data + 2); | 812 PrintRightByteOperand(data + 2); |
813 return 3; // includes 0x0F | 813 return 3; // includes 0x0F |
814 } | 814 } |
815 | 815 |
816 | 816 |
817 // Returns number of bytes used, including *data. | 817 // Returns number of bytes used, including *data. |
818 int DisassemblerX64::FPUInstruction(byte* data) { | 818 int DisassemblerX64::FPUInstruction(byte* data) { |
819 byte escape_opcode = *data; | 819 byte escape_opcode = *data; |
820 ASSERT_EQ(0xD8, escape_opcode & 0xF8); | 820 DCHECK_EQ(0xD8, escape_opcode & 0xF8); |
821 byte modrm_byte = *(data+1); | 821 byte modrm_byte = *(data+1); |
822 | 822 |
823 if (modrm_byte >= 0xC0) { | 823 if (modrm_byte >= 0xC0) { |
824 return RegisterFPUInstruction(escape_opcode, modrm_byte); | 824 return RegisterFPUInstruction(escape_opcode, modrm_byte); |
825 } else { | 825 } else { |
826 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1); | 826 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1); |
827 } | 827 } |
828 } | 828 } |
829 | 829 |
830 int DisassemblerX64::MemoryFPUInstruction(int escape_opcode, | 830 int DisassemblerX64::MemoryFPUInstruction(int escape_opcode, |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1064 AppendToBuffer(",%s", NameOfXMMRegister(regop)); | 1064 AppendToBuffer(",%s", NameOfXMMRegister(regop)); |
1065 } else if (opcode == 0xD6) { | 1065 } else if (opcode == 0xD6) { |
1066 AppendToBuffer("movq "); | 1066 AppendToBuffer("movq "); |
1067 current += PrintRightXMMOperand(current); | 1067 current += PrintRightXMMOperand(current); |
1068 AppendToBuffer(",%s", NameOfXMMRegister(regop)); | 1068 AppendToBuffer(",%s", NameOfXMMRegister(regop)); |
1069 } else if (opcode == 0x50) { | 1069 } else if (opcode == 0x50) { |
1070 AppendToBuffer("movmskpd %s,", NameOfCPURegister(regop)); | 1070 AppendToBuffer("movmskpd %s,", NameOfCPURegister(regop)); |
1071 current += PrintRightXMMOperand(current); | 1071 current += PrintRightXMMOperand(current); |
1072 } else if (opcode == 0x73) { | 1072 } else if (opcode == 0x73) { |
1073 current += 1; | 1073 current += 1; |
1074 ASSERT(regop == 6); | 1074 DCHECK(regop == 6); |
1075 AppendToBuffer("psllq,%s,%d", NameOfXMMRegister(rm), *current & 0x7f); | 1075 AppendToBuffer("psllq,%s,%d", NameOfXMMRegister(rm), *current & 0x7f); |
1076 current += 1; | 1076 current += 1; |
1077 } else { | 1077 } else { |
1078 const char* mnemonic = "?"; | 1078 const char* mnemonic = "?"; |
1079 if (opcode == 0x54) { | 1079 if (opcode == 0x54) { |
1080 mnemonic = "andpd"; | 1080 mnemonic = "andpd"; |
1081 } else if (opcode == 0x56) { | 1081 } else if (opcode == 0x56) { |
1082 mnemonic = "orpd"; | 1082 mnemonic = "orpd"; |
1083 } else if (opcode == 0x57) { | 1083 } else if (opcode == 0x57) { |
1084 mnemonic = "xorpd"; | 1084 mnemonic = "xorpd"; |
(...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1784 UnimplementedInstruction(); | 1784 UnimplementedInstruction(); |
1785 data += 1; | 1785 data += 1; |
1786 } | 1786 } |
1787 } // !processed | 1787 } // !processed |
1788 | 1788 |
1789 if (tmp_buffer_pos_ < sizeof tmp_buffer_) { | 1789 if (tmp_buffer_pos_ < sizeof tmp_buffer_) { |
1790 tmp_buffer_[tmp_buffer_pos_] = '\0'; | 1790 tmp_buffer_[tmp_buffer_pos_] = '\0'; |
1791 } | 1791 } |
1792 | 1792 |
1793 int instr_len = static_cast<int>(data - instr); | 1793 int instr_len = static_cast<int>(data - instr); |
1794 ASSERT(instr_len > 0); // Ensure progress. | 1794 DCHECK(instr_len > 0); // Ensure progress. |
1795 | 1795 |
1796 int outp = 0; | 1796 int outp = 0; |
1797 // Instruction bytes. | 1797 // Instruction bytes. |
1798 for (byte* bp = instr; bp < data; bp++) { | 1798 for (byte* bp = instr; bp < data; bp++) { |
1799 outp += v8::internal::SNPrintF(out_buffer + outp, "%02x", *bp); | 1799 outp += v8::internal::SNPrintF(out_buffer + outp, "%02x", *bp); |
1800 } | 1800 } |
1801 for (int i = 6 - instr_len; i >= 0; i--) { | 1801 for (int i = 6 - instr_len; i >= 0; i--) { |
1802 outp += v8::internal::SNPrintF(out_buffer + outp, " "); | 1802 outp += v8::internal::SNPrintF(out_buffer + outp, " "); |
1803 } | 1803 } |
1804 | 1804 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1906 for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) { | 1906 for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) { |
1907 fprintf(f, " "); | 1907 fprintf(f, " "); |
1908 } | 1908 } |
1909 fprintf(f, " %s\n", buffer.start()); | 1909 fprintf(f, " %s\n", buffer.start()); |
1910 } | 1910 } |
1911 } | 1911 } |
1912 | 1912 |
1913 } // namespace disasm | 1913 } // namespace disasm |
1914 | 1914 |
1915 #endif // V8_TARGET_ARCH_X64 | 1915 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |