OLD | NEW |
1 // Copyright 2007-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2007-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 static ByteMnemonic two_operands_instr[] = { | 54 static ByteMnemonic two_operands_instr[] = { |
55 {0x03, "add", REG_OPER_OP_ORDER}, | 55 {0x03, "add", REG_OPER_OP_ORDER}, |
56 {0x21, "and", OPER_REG_OP_ORDER}, | 56 {0x21, "and", OPER_REG_OP_ORDER}, |
57 {0x23, "and", REG_OPER_OP_ORDER}, | 57 {0x23, "and", REG_OPER_OP_ORDER}, |
58 {0x3B, "cmp", REG_OPER_OP_ORDER}, | 58 {0x3B, "cmp", REG_OPER_OP_ORDER}, |
59 {0x8D, "lea", REG_OPER_OP_ORDER}, | 59 {0x8D, "lea", REG_OPER_OP_ORDER}, |
60 {0x09, "or", OPER_REG_OP_ORDER}, | 60 {0x09, "or", OPER_REG_OP_ORDER}, |
61 {0x0B, "or", REG_OPER_OP_ORDER}, | 61 {0x0B, "or", REG_OPER_OP_ORDER}, |
62 {0x1B, "sbb", REG_OPER_OP_ORDER}, | 62 {0x1B, "sbb", REG_OPER_OP_ORDER}, |
63 {0x29, "sub", OPER_REG_OP_ORDER}, | 63 {0x29, "sub", OPER_REG_OP_ORDER}, |
| 64 {0x2A, "subb", REG_OPER_OP_ORDER}, |
64 {0x2B, "sub", REG_OPER_OP_ORDER}, | 65 {0x2B, "sub", REG_OPER_OP_ORDER}, |
65 {0x85, "test", REG_OPER_OP_ORDER}, | 66 {0x85, "test", REG_OPER_OP_ORDER}, |
66 {0x31, "xor", OPER_REG_OP_ORDER}, | 67 {0x31, "xor", OPER_REG_OP_ORDER}, |
67 {0x33, "xor", REG_OPER_OP_ORDER}, | 68 {0x33, "xor", REG_OPER_OP_ORDER}, |
68 {0x87, "xchg", REG_OPER_OP_ORDER}, | 69 {0x87, "xchg", REG_OPER_OP_ORDER}, |
69 {0x8A, "mov_b", REG_OPER_OP_ORDER}, | 70 {0x8A, "mov_b", REG_OPER_OP_ORDER}, |
70 {0x8B, "mov", REG_OPER_OP_ORDER}, | 71 {0x8B, "mov", REG_OPER_OP_ORDER}, |
71 {-1, "", UNSET_OP_ORDER} | 72 {-1, "", UNSET_OP_ORDER} |
72 }; | 73 }; |
73 | 74 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 | 110 |
110 | 111 |
111 static const char* jump_conditional_mnem[] = { | 112 static const char* jump_conditional_mnem[] = { |
112 /*0*/ "jo", "jno", "jc", "jnc", | 113 /*0*/ "jo", "jno", "jc", "jnc", |
113 /*4*/ "jz", "jnz", "jna", "ja", | 114 /*4*/ "jz", "jnz", "jna", "ja", |
114 /*8*/ "js", "jns", "jpe", "jpo", | 115 /*8*/ "js", "jns", "jpe", "jpo", |
115 /*12*/ "jl", "jnl", "jng", "jg" | 116 /*12*/ "jl", "jnl", "jng", "jg" |
116 }; | 117 }; |
117 | 118 |
118 | 119 |
| 120 static const char* loop_mnem[] = { |
| 121 "loopne", "loope", "loop" |
| 122 }; |
| 123 |
| 124 |
119 static const char* set_conditional_mnem[] = { | 125 static const char* set_conditional_mnem[] = { |
120 /*0*/ "seto", "setno", "setc", "setnc", | 126 /*0*/ "seto", "setno", "setc", "setnc", |
121 /*4*/ "setz", "setnz", "setna", "seta", | 127 /*4*/ "setz", "setnz", "setna", "seta", |
122 /*8*/ "sets", "setns", "setpe", "setpo", | 128 /*8*/ "sets", "setns", "setpe", "setpo", |
123 /*12*/ "setl", "setnl", "setng", "setg" | 129 /*12*/ "setl", "setnl", "setng", "setg" |
124 }; | 130 }; |
125 | 131 |
126 | 132 |
127 static const char* conditional_move_mnem[] = { | 133 static const char* conditional_move_mnem[] = { |
128 /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc", | 134 /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc", |
129 /*4*/ "cmovz", "cmovnz", "cmovna", "cmova", | 135 /*4*/ "cmovz", "cmovnz", "cmovna", "cmova", |
130 /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo", | 136 /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo", |
131 /*12*/ "cmovl", "cmovnl", "cmovng", "cmovg" | 137 /*12*/ "cmovl", "cmovnl", "cmovng", "cmovg" |
132 }; | 138 }; |
133 | 139 |
134 | 140 |
135 enum InstructionType { | 141 enum InstructionType { |
136 NO_INSTR, | 142 NO_INSTR, |
137 ZERO_OPERANDS_INSTR, | 143 ZERO_OPERANDS_INSTR, |
138 TWO_OPERANDS_INSTR, | 144 TWO_OPERANDS_INSTR, |
139 JUMP_CONDITIONAL_SHORT_INSTR, | 145 JUMP_CONDITIONAL_SHORT_INSTR, |
| 146 LOOP_INSTR, |
140 REGISTER_INSTR, | 147 REGISTER_INSTR, |
141 MOVE_REG_INSTR, | 148 MOVE_REG_INSTR, |
142 CALL_JUMP_INSTR, | 149 CALL_JUMP_INSTR, |
143 SHORT_IMMEDIATE_INSTR | 150 SHORT_IMMEDIATE_INSTR |
144 }; | 151 }; |
145 | 152 |
146 | 153 |
147 struct InstructionDesc { | 154 struct InstructionDesc { |
148 const char* mnem; | 155 const char* mnem; |
149 InstructionType type; | 156 InstructionType type; |
150 OperandOrder op_order_; | 157 OperandOrder op_order_; |
151 }; | 158 }; |
152 | 159 |
153 | 160 |
154 class InstructionTable { | 161 class InstructionTable { |
155 public: | 162 public: |
156 InstructionTable(); | 163 InstructionTable(); |
157 const InstructionDesc& Get(byte x) const { return instructions_[x]; } | 164 const InstructionDesc& Get(byte x) const { return instructions_[x]; } |
158 | 165 |
159 private: | 166 private: |
160 InstructionDesc instructions_[256]; | 167 InstructionDesc instructions_[256]; |
161 void Clear(); | 168 void Clear(); |
162 void Init(); | 169 void Init(); |
163 void CopyTable(ByteMnemonic bm[], InstructionType type); | 170 void CopyTable(ByteMnemonic bm[], InstructionType type); |
164 void SetTableRange(InstructionType type, | 171 void SetTableRange(InstructionType type, |
165 byte start, | 172 byte start, |
166 byte end, | 173 byte end, |
167 const char* mnem); | 174 const char* mnem); |
168 void AddJumpConditionalShort(); | 175 void AddJumpConditionalShort(); |
| 176 void AddLoop(); |
169 }; | 177 }; |
170 | 178 |
171 | 179 |
172 InstructionTable::InstructionTable() { | 180 InstructionTable::InstructionTable() { |
173 Clear(); | 181 Clear(); |
174 Init(); | 182 Init(); |
175 } | 183 } |
176 | 184 |
177 | 185 |
178 void InstructionTable::Clear() { | 186 void InstructionTable::Clear() { |
179 for (int i = 0; i < 256; i++) { | 187 for (int i = 0; i < 256; i++) { |
180 instructions_[i].mnem = ""; | 188 instructions_[i].mnem = ""; |
181 instructions_[i].type = NO_INSTR; | 189 instructions_[i].type = NO_INSTR; |
182 instructions_[i].op_order_ = UNSET_OP_ORDER; | 190 instructions_[i].op_order_ = UNSET_OP_ORDER; |
183 } | 191 } |
184 } | 192 } |
185 | 193 |
186 | 194 |
187 void InstructionTable::Init() { | 195 void InstructionTable::Init() { |
188 CopyTable(two_operands_instr, TWO_OPERANDS_INSTR); | 196 CopyTable(two_operands_instr, TWO_OPERANDS_INSTR); |
189 CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR); | 197 CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR); |
190 CopyTable(call_jump_instr, CALL_JUMP_INSTR); | 198 CopyTable(call_jump_instr, CALL_JUMP_INSTR); |
191 CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR); | 199 CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR); |
192 AddJumpConditionalShort(); | 200 AddJumpConditionalShort(); |
| 201 AddLoop(); |
193 SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc"); | 202 SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc"); |
194 SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec"); | 203 SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec"); |
195 SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push"); | 204 SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push"); |
196 SetTableRange(REGISTER_INSTR, 0x58, 0x5F, "pop"); | 205 SetTableRange(REGISTER_INSTR, 0x58, 0x5F, "pop"); |
197 SetTableRange(REGISTER_INSTR, 0x91, 0x97, "xchg eax,"); // 0x90 is nop. | 206 SetTableRange(REGISTER_INSTR, 0x91, 0x97, "xchg eax,"); // 0x90 is nop. |
198 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov"); | 207 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov"); |
199 } | 208 } |
200 | 209 |
201 | 210 |
202 void InstructionTable::CopyTable(ByteMnemonic bm[], InstructionType type) { | 211 void InstructionTable::CopyTable(ByteMnemonic bm[], InstructionType type) { |
(...skipping 23 matching lines...) Expand all Loading... |
226 void InstructionTable::AddJumpConditionalShort() { | 235 void InstructionTable::AddJumpConditionalShort() { |
227 for (byte b = 0x70; b <= 0x7F; b++) { | 236 for (byte b = 0x70; b <= 0x7F; b++) { |
228 InstructionDesc* id = &instructions_[b]; | 237 InstructionDesc* id = &instructions_[b]; |
229 ASSERT_EQ(NO_INSTR, id->type); // Information not already entered. | 238 ASSERT_EQ(NO_INSTR, id->type); // Information not already entered. |
230 id->mnem = jump_conditional_mnem[b & 0x0F]; | 239 id->mnem = jump_conditional_mnem[b & 0x0F]; |
231 id->type = JUMP_CONDITIONAL_SHORT_INSTR; | 240 id->type = JUMP_CONDITIONAL_SHORT_INSTR; |
232 } | 241 } |
233 } | 242 } |
234 | 243 |
235 | 244 |
| 245 void InstructionTable::AddLoop() { |
| 246 for (byte b = 0xE0; b <= 0xE2; b++) { |
| 247 InstructionDesc* id = &instructions_[b]; |
| 248 ASSERT_EQ(NO_INSTR, id->type); // Information not already entered. |
| 249 id->mnem = loop_mnem[b & 0x03]; |
| 250 id->type = LOOP_INSTR; |
| 251 } |
| 252 } |
| 253 |
| 254 |
236 static InstructionTable instruction_table; | 255 static InstructionTable instruction_table; |
237 | 256 |
238 | 257 |
239 // The IA32 disassembler implementation. | 258 // The IA32 disassembler implementation. |
240 class DisassemblerIA32 { | 259 class DisassemblerIA32 { |
241 public: | 260 public: |
242 DisassemblerIA32(const NameConverter& converter, | 261 DisassemblerIA32(const NameConverter& converter, |
243 bool abort_on_unimplemented = true) | 262 bool abort_on_unimplemented = true) |
244 : converter_(converter), | 263 : converter_(converter), |
245 tmp_buffer_pos_(0), | 264 tmp_buffer_pos_(0), |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
322 int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name); | 341 int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name); |
323 int PrintRightOperand(byte* modrmp); | 342 int PrintRightOperand(byte* modrmp); |
324 int PrintRightByteOperand(byte* modrmp); | 343 int PrintRightByteOperand(byte* modrmp); |
325 int PrintOperands(const char* mnem, OperandOrder op_order, byte* data); | 344 int PrintOperands(const char* mnem, OperandOrder op_order, byte* data); |
326 int PrintImmediateOp(byte* data); | 345 int PrintImmediateOp(byte* data); |
327 int F7Instruction(byte* data); | 346 int F7Instruction(byte* data); |
328 int D1D3C1Instruction(byte* data); | 347 int D1D3C1Instruction(byte* data); |
329 int JumpShort(byte* data); | 348 int JumpShort(byte* data); |
330 int JumpConditional(byte* data, const char* comment); | 349 int JumpConditional(byte* data, const char* comment); |
331 int JumpConditionalShort(byte* data, const char* comment); | 350 int JumpConditionalShort(byte* data, const char* comment); |
| 351 int Loop(byte* data); |
332 int SetCC(byte* data); | 352 int SetCC(byte* data); |
333 int CMov(byte* data); | 353 int CMov(byte* data); |
334 int FPUInstruction(byte* data); | 354 int FPUInstruction(byte* data); |
335 int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start); | 355 int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start); |
336 int RegisterFPUInstruction(int escape_opcode, byte modrm_byte); | 356 int RegisterFPUInstruction(int escape_opcode, byte modrm_byte); |
337 void AppendToBuffer(const char* format, ...); | 357 void AppendToBuffer(const char* format, ...); |
338 | 358 |
339 | 359 |
340 void UnimplementedInstruction() { | 360 void UnimplementedInstruction() { |
341 if (abort_on_unimplemented_) { | 361 if (abort_on_unimplemented_) { |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
610 const char* mnem = jump_conditional_mnem[cond]; | 630 const char* mnem = jump_conditional_mnem[cond]; |
611 AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); | 631 AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); |
612 if (comment != NULL) { | 632 if (comment != NULL) { |
613 AppendToBuffer(", %s", comment); | 633 AppendToBuffer(", %s", comment); |
614 } | 634 } |
615 return 2; | 635 return 2; |
616 } | 636 } |
617 | 637 |
618 | 638 |
619 // Returns number of bytes used, including *data. | 639 // Returns number of bytes used, including *data. |
| 640 int DisassemblerIA32::Loop(byte* data) { |
| 641 byte cond = *data & 0x03; |
| 642 byte b = *(data+1); |
| 643 byte* dest = data + static_cast<int8_t>(b) + 2; |
| 644 const char* mnem = loop_mnem[cond]; |
| 645 AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); |
| 646 return 2; |
| 647 } |
| 648 |
| 649 |
| 650 // Returns number of bytes used, including *data. |
620 int DisassemblerIA32::SetCC(byte* data) { | 651 int DisassemblerIA32::SetCC(byte* data) { |
621 ASSERT_EQ(0x0F, *data); | 652 ASSERT_EQ(0x0F, *data); |
622 byte cond = *(data+1) & 0x0F; | 653 byte cond = *(data+1) & 0x0F; |
623 const char* mnem = set_conditional_mnem[cond]; | 654 const char* mnem = set_conditional_mnem[cond]; |
624 AppendToBuffer("%s ", mnem); | 655 AppendToBuffer("%s ", mnem); |
625 PrintRightByteOperand(data+2); | 656 PrintRightByteOperand(data+2); |
626 return 3; // Includes 0x0F. | 657 return 3; // Includes 0x0F. |
627 } | 658 } |
628 | 659 |
629 | 660 |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
847 | 878 |
848 case TWO_OPERANDS_INSTR: | 879 case TWO_OPERANDS_INSTR: |
849 data++; | 880 data++; |
850 data += PrintOperands(idesc.mnem, idesc.op_order_, data); | 881 data += PrintOperands(idesc.mnem, idesc.op_order_, data); |
851 break; | 882 break; |
852 | 883 |
853 case JUMP_CONDITIONAL_SHORT_INSTR: | 884 case JUMP_CONDITIONAL_SHORT_INSTR: |
854 data += JumpConditionalShort(data, branch_hint); | 885 data += JumpConditionalShort(data, branch_hint); |
855 break; | 886 break; |
856 | 887 |
| 888 case LOOP_INSTR: |
| 889 data += Loop(data); |
| 890 break; |
| 891 |
857 case REGISTER_INSTR: | 892 case REGISTER_INSTR: |
858 AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07)); | 893 AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07)); |
859 data++; | 894 data++; |
860 break; | 895 break; |
861 | 896 |
862 case MOVE_REG_INSTR: { | 897 case MOVE_REG_INSTR: { |
863 byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1)); | 898 byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1)); |
864 AppendToBuffer("mov %s,%s", | 899 AppendToBuffer("mov %s,%s", |
865 NameOfCPURegister(*data & 0x07), | 900 NameOfCPURegister(*data & 0x07), |
866 NameOfAddress(addr)); | 901 NameOfAddress(addr)); |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1297 } | 1332 } |
1298 for (int i = 6 - (pc - prev_pc); i >= 0; i--) { | 1333 for (int i = 6 - (pc - prev_pc); i >= 0; i--) { |
1299 fprintf(f, " "); | 1334 fprintf(f, " "); |
1300 } | 1335 } |
1301 fprintf(f, " %s\n", buffer.start()); | 1336 fprintf(f, " %s\n", buffer.start()); |
1302 } | 1337 } |
1303 } | 1338 } |
1304 | 1339 |
1305 | 1340 |
1306 } // namespace disasm | 1341 } // namespace disasm |
OLD | NEW |