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

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

Issue 149608: Copy of issue 155346: Change test status for x64, make test.py pass --arch to Scons. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 5 months 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 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 16 matching lines...) Expand all
27 27
28 #include <assert.h> 28 #include <assert.h>
29 #include <stdio.h> 29 #include <stdio.h>
30 #include <stdarg.h> 30 #include <stdarg.h>
31 31
32 #include "v8.h" 32 #include "v8.h"
33 #include "disasm.h" 33 #include "disasm.h"
34 34
35 namespace disasm { 35 namespace disasm {
36 36
37 enum OperandOrder { 37 enum OperandType {
38 UNSET_OP_ORDER = 0, REG_OPER_OP_ORDER, OPER_REG_OP_ORDER 38 UNSET_OP_ORDER = 0,
39 // Operand size decides between 16, 32 and 64 bit operands.
40 REG_OPER_OP_ORDER = 1, // Register destination, operand source.
41 OPER_REG_OP_ORDER = 2, // Operand destination, register source.
42 // Fixed 8-bit operands.
43 BYTE_SIZE_OPERAND_FLAG = 4,
44 BYTE_REG_OPER_OP_ORDER = REG_OPER_OP_ORDER | BYTE_SIZE_OPERAND_FLAG,
45 BYTE_OPER_REG_OP_ORDER = OPER_REG_OP_ORDER | BYTE_SIZE_OPERAND_FLAG
39 }; 46 };
40 47
41 //------------------------------------------------------------------ 48 //------------------------------------------------------------------
42 // Tables 49 // Tables
43 //------------------------------------------------------------------ 50 //------------------------------------------------------------------
44 struct ByteMnemonic { 51 struct ByteMnemonic {
45 int b; // -1 terminates, otherwise must be in range (0..255) 52 int b; // -1 terminates, otherwise must be in range (0..255)
46 OperandOrder op_order_; 53 OperandType op_order_;
47 const char* mnem; 54 const char* mnem;
48 }; 55 };
49 56
50 57
51 static ByteMnemonic two_operands_instr[] = { 58 static ByteMnemonic two_operands_instr[] = {
52 { 0x03, REG_OPER_OP_ORDER, "add" }, 59 { 0x00, BYTE_OPER_REG_OP_ORDER, "add" },
53 { 0x21, OPER_REG_OP_ORDER, "and" }, 60 { 0x01, OPER_REG_OP_ORDER, "add" },
54 { 0x23, REG_OPER_OP_ORDER, "and" }, 61 { 0x02, BYTE_REG_OPER_OP_ORDER, "add" },
55 { 0x3B, REG_OPER_OP_ORDER, "cmp" }, 62 { 0x03, REG_OPER_OP_ORDER, "add" },
56 { 0x8D, REG_OPER_OP_ORDER, "lea" }, 63 { 0x08, BYTE_OPER_REG_OP_ORDER, "or" },
57 { 0x09, OPER_REG_OP_ORDER, "or" }, 64 { 0x09, OPER_REG_OP_ORDER, "or" },
58 { 0x0B, REG_OPER_OP_ORDER, "or" }, 65 { 0x0A, BYTE_REG_OPER_OP_ORDER, "or" },
59 { 0x1B, REG_OPER_OP_ORDER, "sbb" }, 66 { 0x0B, REG_OPER_OP_ORDER, "or" },
60 { 0x29, OPER_REG_OP_ORDER, "sub" }, 67 { 0x10, BYTE_OPER_REG_OP_ORDER, "adc" },
61 { 0x2B, REG_OPER_OP_ORDER, "sub" }, 68 { 0x11, OPER_REG_OP_ORDER, "adc" },
62 { 0x85, REG_OPER_OP_ORDER, "test" }, 69 { 0x12, BYTE_REG_OPER_OP_ORDER, "adc" },
63 { 0x31, OPER_REG_OP_ORDER, "xor" }, 70 { 0x13, REG_OPER_OP_ORDER, "adc" },
64 { 0x33, REG_OPER_OP_ORDER, "xor" }, 71 { 0x18, BYTE_OPER_REG_OP_ORDER, "sbb" },
65 { 0x87, REG_OPER_OP_ORDER, "xchg" }, 72 { 0x19, OPER_REG_OP_ORDER, "sbb" },
66 { 0x8A, REG_OPER_OP_ORDER, "movb" }, 73 { 0x1A, BYTE_REG_OPER_OP_ORDER, "sbb" },
67 { 0x8B, REG_OPER_OP_ORDER, "mov" }, 74 { 0x1B, REG_OPER_OP_ORDER, "sbb" },
75 { 0x20, BYTE_OPER_REG_OP_ORDER, "and" },
76 { 0x21, OPER_REG_OP_ORDER, "and" },
77 { 0x22, BYTE_REG_OPER_OP_ORDER, "and" },
78 { 0x23, REG_OPER_OP_ORDER, "and" },
79 { 0x28, BYTE_OPER_REG_OP_ORDER, "sub" },
80 { 0x29, OPER_REG_OP_ORDER, "sub" },
81 { 0x2A, BYTE_REG_OPER_OP_ORDER, "sub" },
82 { 0x2B, REG_OPER_OP_ORDER, "sub" },
83 { 0x30, BYTE_OPER_REG_OP_ORDER, "xor" },
84 { 0x31, OPER_REG_OP_ORDER, "xor" },
85 { 0x32, BYTE_REG_OPER_OP_ORDER, "xor" },
86 { 0x33, REG_OPER_OP_ORDER, "xor" },
87 { 0x38, BYTE_OPER_REG_OP_ORDER, "cmp" },
88 { 0x39, OPER_REG_OP_ORDER, "cmp" },
89 { 0x3A, BYTE_REG_OPER_OP_ORDER, "cmp" },
90 { 0x3B, REG_OPER_OP_ORDER, "cmp" },
91 { 0x8D, REG_OPER_OP_ORDER, "lea" },
92 { 0x84, BYTE_REG_OPER_OP_ORDER, "test" },
93 { 0x85, REG_OPER_OP_ORDER, "test" },
94 { 0x86, BYTE_REG_OPER_OP_ORDER, "xchg" },
95 { 0x87, REG_OPER_OP_ORDER, "xchg" },
96 { 0x88, BYTE_OPER_REG_OP_ORDER, "mov" },
97 { 0x89, OPER_REG_OP_ORDER, "mov" },
98 { 0x8A, BYTE_REG_OPER_OP_ORDER, "mov" },
99 { 0x8B, REG_OPER_OP_ORDER, "mov" },
68 { -1, UNSET_OP_ORDER, "" } 100 { -1, UNSET_OP_ORDER, "" }
69 }; 101 };
70 102
71 103
72 static ByteMnemonic zero_operands_instr[] = { 104 static ByteMnemonic zero_operands_instr[] = {
73 { 0xC3, UNSET_OP_ORDER, "ret" }, 105 { 0xC3, UNSET_OP_ORDER, "ret" },
74 { 0xC9, UNSET_OP_ORDER, "leave" }, 106 { 0xC9, UNSET_OP_ORDER, "leave" },
75 { 0x90, UNSET_OP_ORDER, "nop" }, 107 { 0x90, UNSET_OP_ORDER, "nop" },
76 { 0xF4, UNSET_OP_ORDER, "hlt" }, 108 { 0xF4, UNSET_OP_ORDER, "hlt" },
77 { 0xCC, UNSET_OP_ORDER, "int3" }, 109 { 0xCC, UNSET_OP_ORDER, "int3" },
(...skipping 12 matching lines...) Expand all
90 { 0xE8, UNSET_OP_ORDER, "call" }, 122 { 0xE8, UNSET_OP_ORDER, "call" },
91 { 0xE9, UNSET_OP_ORDER, "jmp" }, 123 { 0xE9, UNSET_OP_ORDER, "jmp" },
92 { -1, UNSET_OP_ORDER, "" } 124 { -1, UNSET_OP_ORDER, "" }
93 }; 125 };
94 126
95 127
96 static ByteMnemonic short_immediate_instr[] = { 128 static ByteMnemonic short_immediate_instr[] = {
97 { 0x05, UNSET_OP_ORDER, "add" }, 129 { 0x05, UNSET_OP_ORDER, "add" },
98 { 0x0D, UNSET_OP_ORDER, "or" }, 130 { 0x0D, UNSET_OP_ORDER, "or" },
99 { 0x15, UNSET_OP_ORDER, "adc" }, 131 { 0x15, UNSET_OP_ORDER, "adc" },
132 { 0x1D, UNSET_OP_ORDER, "sbb" },
100 { 0x25, UNSET_OP_ORDER, "and" }, 133 { 0x25, UNSET_OP_ORDER, "and" },
101 { 0x2D, UNSET_OP_ORDER, "sub" }, 134 { 0x2D, UNSET_OP_ORDER, "sub" },
102 { 0x35, UNSET_OP_ORDER, "xor" }, 135 { 0x35, UNSET_OP_ORDER, "xor" },
103 { 0x3D, UNSET_OP_ORDER, "cmp" }, 136 { 0x3D, UNSET_OP_ORDER, "cmp" },
104 { -1, UNSET_OP_ORDER, "" } 137 { -1, UNSET_OP_ORDER, "" }
105 }; 138 };
106 139
107 140
108 static const char* conditional_code_suffix[] = { 141 static const char* conditional_code_suffix[] = {
109 "o", "no", "c", "nc", "z", "nz", "a", "na", 142 "o", "no", "c", "nc", "z", "nz", "a", "na",
(...skipping 10 matching lines...) Expand all
120 PUSHPOP_INSTR, // Has implicit 64-bit operand size. 153 PUSHPOP_INSTR, // Has implicit 64-bit operand size.
121 MOVE_REG_INSTR, 154 MOVE_REG_INSTR,
122 CALL_JUMP_INSTR, 155 CALL_JUMP_INSTR,
123 SHORT_IMMEDIATE_INSTR 156 SHORT_IMMEDIATE_INSTR
124 }; 157 };
125 158
126 159
127 struct InstructionDesc { 160 struct InstructionDesc {
128 const char* mnem; 161 const char* mnem;
129 InstructionType type; 162 InstructionType type;
130 OperandOrder op_order_; 163 OperandType op_order_;
164 bool byte_size_operation; // Fixed 8-bit operation.
131 }; 165 };
132 166
133 167
134 class InstructionTable { 168 class InstructionTable {
135 public: 169 public:
136 InstructionTable(); 170 InstructionTable();
137 const InstructionDesc& Get(byte x) const { 171 const InstructionDesc& Get(byte x) const {
138 return instructions_[x]; 172 return instructions_[x];
139 } 173 }
140 174
141 private: 175 private:
142 InstructionDesc instructions_[256]; 176 InstructionDesc instructions_[256];
143 void Clear(); 177 void Clear();
144 void Init(); 178 void Init();
145 void CopyTable(ByteMnemonic bm[], InstructionType type); 179 void CopyTable(ByteMnemonic bm[], InstructionType type);
146 void SetTableRange(InstructionType type, byte start, byte end, 180 void SetTableRange(InstructionType type, byte start, byte end, bool byte_size,
147 const char* mnem); 181 const char* mnem);
148 void AddJumpConditionalShort(); 182 void AddJumpConditionalShort();
149 }; 183 };
150 184
151 185
152 InstructionTable::InstructionTable() { 186 InstructionTable::InstructionTable() {
153 Clear(); 187 Clear();
154 Init(); 188 Init();
155 } 189 }
156 190
157 191
158 void InstructionTable::Clear() { 192 void InstructionTable::Clear() {
159 for (int i = 0; i < 256; i++) { 193 for (int i = 0; i < 256; i++) {
160 instructions_[i].mnem = ""; 194 instructions_[i].mnem = "(bad)";
161 instructions_[i].type = NO_INSTR; 195 instructions_[i].type = NO_INSTR;
162 instructions_[i].op_order_ = UNSET_OP_ORDER; 196 instructions_[i].op_order_ = UNSET_OP_ORDER;
197 instructions_[i].byte_size_operation = false;
163 } 198 }
164 } 199 }
165 200
166 201
167 void InstructionTable::Init() { 202 void InstructionTable::Init() {
168 CopyTable(two_operands_instr, TWO_OPERANDS_INSTR); 203 CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
169 CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR); 204 CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
170 CopyTable(call_jump_instr, CALL_JUMP_INSTR); 205 CopyTable(call_jump_instr, CALL_JUMP_INSTR);
171 CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR); 206 CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
172 AddJumpConditionalShort(); 207 AddJumpConditionalShort();
173 SetTableRange(PUSHPOP_INSTR, 0x50, 0x57, "push"); 208 SetTableRange(PUSHPOP_INSTR, 0x50, 0x57, false, "push");
174 SetTableRange(PUSHPOP_INSTR, 0x58, 0x5F, "pop"); 209 SetTableRange(PUSHPOP_INSTR, 0x58, 0x5F, false, "pop");
175 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov"); 210 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, false, "mov");
176 } 211 }
177 212
178 213
179 void InstructionTable::CopyTable(ByteMnemonic bm[], InstructionType type) { 214 void InstructionTable::CopyTable(ByteMnemonic bm[], InstructionType type) {
180 for (int i = 0; bm[i].b >= 0; i++) { 215 for (int i = 0; bm[i].b >= 0; i++) {
181 InstructionDesc* id = &instructions_[bm[i].b]; 216 InstructionDesc* id = &instructions_[bm[i].b];
182 id->mnem = bm[i].mnem; 217 id->mnem = bm[i].mnem;
183 id->op_order_ = bm[i].op_order_; 218 OperandType op_order = bm[i].op_order_;
184 assert(id->type == NO_INSTR); // Information already entered 219 id->op_order_ =
220 static_cast<OperandType>(op_order & ~BYTE_SIZE_OPERAND_FLAG);
221 assert(id->type == NO_INSTR); // Information not already entered
185 id->type = type; 222 id->type = type;
223 id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0);
186 } 224 }
187 } 225 }
188 226
189 227
190 void InstructionTable::SetTableRange(InstructionType type, byte start, 228 void InstructionTable::SetTableRange(InstructionType type,
191 byte end, const char* mnem) { 229 byte start,
230 byte end,
231 bool byte_size,
232 const char* mnem) {
192 for (byte b = start; b <= end; b++) { 233 for (byte b = start; b <= end; b++) {
193 InstructionDesc* id = &instructions_[b]; 234 InstructionDesc* id = &instructions_[b];
194 assert(id->type == NO_INSTR); // Information already entered 235 assert(id->type == NO_INSTR); // Information already entered
195 id->mnem = mnem; 236 id->mnem = mnem;
196 id->type = type; 237 id->type = type;
238 id->byte_size_operation = byte_size;
197 } 239 }
198 } 240 }
199 241
200 242
201 void InstructionTable::AddJumpConditionalShort() { 243 void InstructionTable::AddJumpConditionalShort() {
202 for (byte b = 0x70; b <= 0x7F; b++) { 244 for (byte b = 0x70; b <= 0x7F; b++) {
203 InstructionDesc* id = &instructions_[b]; 245 InstructionDesc* id = &instructions_[b];
204 assert(id->type == NO_INSTR); // Information already entered 246 assert(id->type == NO_INSTR); // Information already entered
205 id->mnem = NULL; // Computed depending on condition code. 247 id->mnem = NULL; // Computed depending on condition code.
206 id->type = JUMP_CONDITIONAL_SHORT_INSTR; 248 id->type = JUMP_CONDITIONAL_SHORT_INSTR;
(...skipping 14 matching lines...) Expand all
221 class DisassemblerX64 { 263 class DisassemblerX64 {
222 public: 264 public:
223 DisassemblerX64(const NameConverter& converter, 265 DisassemblerX64(const NameConverter& converter,
224 UnimplementedOpcodeAction unimplemented_action = 266 UnimplementedOpcodeAction unimplemented_action =
225 ABORT_ON_UNIMPLEMENTED_OPCODE) 267 ABORT_ON_UNIMPLEMENTED_OPCODE)
226 : converter_(converter), 268 : converter_(converter),
227 tmp_buffer_pos_(0), 269 tmp_buffer_pos_(0),
228 abort_on_unimplemented_( 270 abort_on_unimplemented_(
229 unimplemented_action == ABORT_ON_UNIMPLEMENTED_OPCODE), 271 unimplemented_action == ABORT_ON_UNIMPLEMENTED_OPCODE),
230 rex_(0), 272 rex_(0),
231 operand_size_(0) { 273 operand_size_(0),
274 byte_size_operand_(false) {
232 tmp_buffer_[0] = '\0'; 275 tmp_buffer_[0] = '\0';
233 } 276 }
234 277
235 virtual ~DisassemblerX64() { 278 virtual ~DisassemblerX64() {
236 } 279 }
237 280
238 // Writes one disassembled instruction into 'buffer' (0-terminated). 281 // Writes one disassembled instruction into 'buffer' (0-terminated).
239 // Returns the length of the disassembled machine instruction in bytes. 282 // Returns the length of the disassembled machine instruction in bytes.
240 int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); 283 int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
241 284
242 private: 285 private:
286 enum OperandSize {
287 BYTE_SIZE = 0,
288 WORD_SIZE = 1,
289 DOUBLEWORD_SIZE = 2,
290 QUADWORD_SIZE = 3
291 };
243 292
244 const NameConverter& converter_; 293 const NameConverter& converter_;
245 v8::internal::EmbeddedVector<char, 128> tmp_buffer_; 294 v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
246 unsigned int tmp_buffer_pos_; 295 unsigned int tmp_buffer_pos_;
247 bool abort_on_unimplemented_; 296 bool abort_on_unimplemented_;
248 // Prefixes parsed 297 // Prefixes parsed
249 byte rex_; 298 byte rex_;
250 byte operand_size_; 299 byte operand_size_;
300 // Byte size operand override.
301 bool byte_size_operand_;
251 302
252 void setOperandSizePrefix(byte prefix) { 303 void setOperandSizePrefix(byte prefix) {
253 ASSERT_EQ(0x66, prefix); 304 ASSERT_EQ(0x66, prefix);
254 operand_size_ = prefix; 305 operand_size_ = prefix;
255 } 306 }
256 307
257 void setRex(byte rex) { 308 void setRex(byte rex) {
258 ASSERT_EQ(0x40, rex & 0xF0); 309 ASSERT_EQ(0x40, rex & 0xF0);
259 rex_ = rex; 310 rex_ = rex;
260 } 311 }
261 312
262 bool rex() { return rex_ != 0; } 313 bool rex() { return rex_ != 0; }
263 314
264 bool rex_b() { return (rex_ & 0x01) != 0; } 315 bool rex_b() { return (rex_ & 0x01) != 0; }
265 316
266 // Actual number of base register given the low bits and the rex.b state. 317 // Actual number of base register given the low bits and the rex.b state.
267 int base_reg(int low_bits) { return low_bits | ((rex_ & 0x01) << 3); } 318 int base_reg(int low_bits) { return low_bits | ((rex_ & 0x01) << 3); }
268 319
269 bool rex_x() { return (rex_ & 0x02) != 0; } 320 bool rex_x() { return (rex_ & 0x02) != 0; }
270 321
271 bool rex_r() { return (rex_ & 0x04) != 0; } 322 bool rex_r() { return (rex_ & 0x04) != 0; }
272 323
273 bool rex_w() { return (rex_ & 0x08) != 0; } 324 bool rex_w() { return (rex_ & 0x08) != 0; }
274 325
275 int operand_size() { 326 OperandSize operand_size() {
276 return rex_w() ? 64 : (operand_size_ != 0) ? 16 : 32; 327 if (byte_size_operand_) return BYTE_SIZE;
328 if (rex_w()) return QUADWORD_SIZE;
329 if (operand_size_ != 0) return WORD_SIZE;
330 return DOUBLEWORD_SIZE;
277 } 331 }
278 332
279 char operand_size_code() { 333 char operand_size_code() {
280 return rex_w() ? 'q' : (operand_size_ != 0) ? 'w' : 'l'; 334 return "bwlq"[operand_size()];
281 } 335 }
282 336
283 const char* NameOfCPURegister(int reg) const { 337 const char* NameOfCPURegister(int reg) const {
284 return converter_.NameOfCPURegister(reg); 338 return converter_.NameOfCPURegister(reg);
285 } 339 }
286 340
287 const char* NameOfByteCPURegister(int reg) const { 341 const char* NameOfByteCPURegister(int reg) const {
288 return converter_.NameOfByteCPURegister(reg); 342 return converter_.NameOfByteCPURegister(reg);
289 } 343 }
290 344
(...skipping 14 matching lines...) Expand all
305 *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0); 359 *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0);
306 *rm = (data & 7) | (rex_b() ? 8 : 0); 360 *rm = (data & 7) | (rex_b() ? 8 : 0);
307 } 361 }
308 362
309 void get_sib(byte data, 363 void get_sib(byte data,
310 int* scale, 364 int* scale,
311 int* index, 365 int* index,
312 int* base) { 366 int* base) {
313 *scale = (data >> 6) & 3; 367 *scale = (data >> 6) & 3;
314 *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0); 368 *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0);
315 *base = data & 7 | (rex_b() ? 8 : 0); 369 *base = (data & 7) | (rex_b() ? 8 : 0);
316 } 370 }
317 371
318 typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const; 372 typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const;
319 373
320 int PrintRightOperandHelper(byte* modrmp, 374 int PrintRightOperandHelper(byte* modrmp,
321 RegisterNameMapping register_name); 375 RegisterNameMapping register_name);
322 int PrintRightOperand(byte* modrmp); 376 int PrintRightOperand(byte* modrmp);
323 int PrintRightByteOperand(byte* modrmp); 377 int PrintRightByteOperand(byte* modrmp);
324 int PrintOperands(const char* mnem, 378 int PrintOperands(const char* mnem,
325 OperandOrder op_order, 379 OperandType op_order,
326 byte* data); 380 byte* data);
381 int PrintImmediate(byte* data, OperandSize size);
327 int PrintImmediateOp(byte* data); 382 int PrintImmediateOp(byte* data);
328 int F7Instruction(byte* data); 383 int F7Instruction(byte* data);
329 int D1D3C1Instruction(byte* data); 384 int ShiftInstruction(byte* data);
330 int JumpShort(byte* data); 385 int JumpShort(byte* data);
331 int JumpConditional(byte* data); 386 int JumpConditional(byte* data);
332 int JumpConditionalShort(byte* data); 387 int JumpConditionalShort(byte* data);
333 int SetCC(byte* data); 388 int SetCC(byte* data);
334 int FPUInstruction(byte* data); 389 int FPUInstruction(byte* data);
335 void AppendToBuffer(const char* format, ...); 390 void AppendToBuffer(const char* format, ...);
336 391
337 void UnimplementedInstruction() { 392 void UnimplementedInstruction() {
338 if (abort_on_unimplemented_) { 393 if (abort_on_unimplemented_) {
339 UNIMPLEMENTED(); 394 UNIMPLEMENTED();
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 AppendToBuffer("%s", (this->*register_name)(rm)); 499 AppendToBuffer("%s", (this->*register_name)(rm));
445 return 1; 500 return 1;
446 default: 501 default:
447 UnimplementedInstruction(); 502 UnimplementedInstruction();
448 return 1; 503 return 1;
449 } 504 }
450 UNREACHABLE(); 505 UNREACHABLE();
451 } 506 }
452 507
453 508
509 int DisassemblerX64::PrintImmediate(byte* data, OperandSize size) {
510 int64_t value;
511 int count;
512 switch (size) {
513 case BYTE_SIZE:
514 value = *data;
515 count = 1;
516 break;
517 case WORD_SIZE:
518 value = *reinterpret_cast<int16_t*>(data);
519 count = 2;
520 break;
521 case DOUBLEWORD_SIZE:
522 value = *reinterpret_cast<uint32_t*>(data);
523 count = 4;
524 break;
525 case QUADWORD_SIZE:
526 value = *reinterpret_cast<int32_t*>(data);
527 count = 4;
528 break;
529 default:
530 UNREACHABLE();
531 value = 0; // Initialize variables on all paths to satisfy the compiler.
532 count = 0;
533 }
534 AppendToBuffer(V8_PTR_PREFIX"x", value);
535 return count;
536 }
537
538
454 int DisassemblerX64::PrintRightOperand(byte* modrmp) { 539 int DisassemblerX64::PrintRightOperand(byte* modrmp) {
455 return PrintRightOperandHelper(modrmp, 540 return PrintRightOperandHelper(modrmp,
456 &DisassemblerX64::NameOfCPURegister); 541 &DisassemblerX64::NameOfCPURegister);
457 } 542 }
458 543
459 544
460 int DisassemblerX64::PrintRightByteOperand(byte* modrmp) { 545 int DisassemblerX64::PrintRightByteOperand(byte* modrmp) {
461 return PrintRightOperandHelper(modrmp, 546 return PrintRightOperandHelper(modrmp,
462 &DisassemblerX64::NameOfByteCPURegister); 547 &DisassemblerX64::NameOfByteCPURegister);
463 } 548 }
464 549
465 550
466 // Returns number of bytes used including the current *data. 551 // Returns number of bytes used including the current *data.
467 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'. 552 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
468 int DisassemblerX64::PrintOperands(const char* mnem, 553 int DisassemblerX64::PrintOperands(const char* mnem,
469 OperandOrder op_order, 554 OperandType op_order,
470 byte* data) { 555 byte* data) {
471 byte modrm = *data; 556 byte modrm = *data;
472 int mod, regop, rm; 557 int mod, regop, rm;
473 get_modrm(modrm, &mod, &regop, &rm); 558 get_modrm(modrm, &mod, &regop, &rm);
474 int advance = 0; 559 int advance = 0;
560 const char* register_name =
561 byte_size_operand_ ? NameOfByteCPURegister(regop)
562 : NameOfCPURegister(regop);
475 switch (op_order) { 563 switch (op_order) {
476 case REG_OPER_OP_ORDER: { 564 case REG_OPER_OP_ORDER: {
477 AppendToBuffer("%s%c %s,", 565 AppendToBuffer("%s%c %s,",
478 mnem, 566 mnem,
479 operand_size_code(), 567 operand_size_code(),
480 NameOfCPURegister(regop)); 568 register_name);
481 advance = PrintRightOperand(data); 569 advance = byte_size_operand_ ? PrintRightByteOperand(data)
570 : PrintRightOperand(data);
482 break; 571 break;
483 } 572 }
484 case OPER_REG_OP_ORDER: { 573 case OPER_REG_OP_ORDER: {
485 AppendToBuffer("%s%c ", mnem, operand_size_code()); 574 AppendToBuffer("%s%c ", mnem, operand_size_code());
486 advance = PrintRightOperand(data); 575 advance = byte_size_operand_ ? PrintRightByteOperand(data)
487 AppendToBuffer(",%s", NameOfCPURegister(regop)); 576 : PrintRightOperand(data);
577 AppendToBuffer(",%s", register_name);
488 break; 578 break;
489 } 579 }
490 default: 580 default:
491 UNREACHABLE(); 581 UNREACHABLE();
492 break; 582 break;
493 } 583 }
494 return advance; 584 return advance;
495 } 585 }
496 586
497 587
498 // Returns number of bytes used by machine instruction, including *data byte. 588 // Returns number of bytes used by machine instruction, including *data byte.
499 // Writes immediate instructions to 'tmp_buffer_'. 589 // Writes immediate instructions to 'tmp_buffer_'.
500 int DisassemblerX64::PrintImmediateOp(byte* data) { 590 int DisassemblerX64::PrintImmediateOp(byte* data) {
501 bool sign_extension_bit = (*data & 0x02) != 0; 591 bool byte_size_immediate = (*data & 0x02) != 0;
502 byte modrm = *(data + 1); 592 byte modrm = *(data + 1);
503 int mod, regop, rm; 593 int mod, regop, rm;
504 get_modrm(modrm, &mod, &regop, &rm); 594 get_modrm(modrm, &mod, &regop, &rm);
505 const char* mnem = "Imm???"; 595 const char* mnem = "Imm???";
506 switch (regop) { 596 switch (regop) {
507 case 0: 597 case 0:
508 mnem = "add"; 598 mnem = "add";
509 break; 599 break;
510 case 1: 600 case 1:
511 mnem = "or"; 601 mnem = "or";
512 break; 602 break;
513 case 2: 603 case 2:
514 mnem = "adc"; 604 mnem = "adc";
515 break; 605 break;
516 case 4: 606 case 4:
517 mnem = "and"; 607 mnem = "and";
518 break; 608 break;
519 case 5: 609 case 5:
520 mnem = "sub"; 610 mnem = "sub";
521 break; 611 break;
522 case 6: 612 case 6:
523 mnem = "xor"; 613 mnem = "xor";
524 break; 614 break;
525 case 7: 615 case 7:
526 mnem = "cmp"; 616 mnem = "cmp";
527 break; 617 break;
528 default: 618 default:
529 UnimplementedInstruction(); 619 UnimplementedInstruction();
530 } 620 }
531 AppendToBuffer("%s ", mnem); 621 AppendToBuffer("%s%c ", mnem, operand_size_code());
532 int count = PrintRightOperand(data + 1); 622 int count = PrintRightOperand(data + 1);
533 if (sign_extension_bit) { 623 AppendToBuffer(",0x");
534 AppendToBuffer(",0x%x", *(data + 1 + count)); 624 OperandSize immediate_size = byte_size_immediate ? BYTE_SIZE : operand_size();
535 return 1 + count + 1 /*int8*/; 625 count += PrintImmediate(data + 1 + count, immediate_size);
536 } else { 626 return 1 + count;
537 AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count));
538 return 1 + count + 4 /*int32_t*/;
539 }
540 } 627 }
541 628
542 629
543 // Returns number of bytes used, including *data. 630 // Returns number of bytes used, including *data.
544 int DisassemblerX64::F7Instruction(byte* data) { 631 int DisassemblerX64::F7Instruction(byte* data) {
545 assert(*data == 0xF7); 632 assert(*data == 0xF7);
546 byte modrm = *(data + 1); 633 byte modrm = *(data + 1);
547 int mod, regop, rm; 634 int mod, regop, rm;
548 get_modrm(modrm, &mod, &regop, &rm); 635 get_modrm(modrm, &mod, &regop, &rm);
549 if (mod == 3 && regop != 0) { 636 if (mod == 3 && regop != 0) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 int32_t imm = *reinterpret_cast<int32_t*>(data + 1 + count); 669 int32_t imm = *reinterpret_cast<int32_t*>(data + 1 + count);
583 AppendToBuffer(",0x%x", imm); 670 AppendToBuffer(",0x%x", imm);
584 return 1 + count + 4 /*int32_t*/; 671 return 1 + count + 4 /*int32_t*/;
585 } else { 672 } else {
586 UnimplementedInstruction(); 673 UnimplementedInstruction();
587 return 2; 674 return 2;
588 } 675 }
589 } 676 }
590 677
591 678
592 int DisassemblerX64::D1D3C1Instruction(byte* data) { 679 int DisassemblerX64::ShiftInstruction(byte* data) {
593 byte op = *data; 680 byte op = *data & (~1);
594 assert(op == 0xD1 || op == 0xD3 || op == 0xC1); 681 if (op != 0xD0 && op != 0xD2 && op != 0xC0) {
682 UnimplementedInstruction();
683 return 1;
684 }
595 byte modrm = *(data + 1); 685 byte modrm = *(data + 1);
596 int mod, regop, rm; 686 int mod, regop, rm;
597 get_modrm(modrm, &mod, &regop, &rm); 687 get_modrm(modrm, &mod, &regop, &rm);
598 ASSERT(regop < 8); 688 ASSERT(regop < 8);
599 int imm8 = -1; 689 int imm8 = -1;
600 int num_bytes = 2; 690 int num_bytes = 2;
601 if (mod == 3) { 691 if (mod != 3) {
602 const char* mnem = NULL; 692 UnimplementedInstruction();
603 if (op == 0xD1) { 693 return num_bytes;
604 imm8 = 1; 694 }
605 switch (regop) { 695 const char* mnem = NULL;
606 case 2: 696 switch (regop) {
607 mnem = "rcl"; 697 case 0:
608 break; 698 mnem = "rol";
609 case 7: 699 break;
610 mnem = "sar"; 700 case 1:
611 break; 701 mnem = "ror";
612 case 4: 702 break;
613 mnem = "shl"; 703 case 2:
614 break; 704 mnem = "rcl";
615 default: 705 break;
616 UnimplementedInstruction(); 706 case 3:
617 } 707 mnem = "rcr";
618 } else if (op == 0xC1) { 708 break;
619 imm8 = *(data + 2); 709 case 4:
620 num_bytes = 3; 710 mnem = "shl";
621 switch (regop) { 711 break;
622 case 2: 712 case 5:
623 mnem = "rcl"; 713 mnem = "shr";
624 break; 714 break;
625 case 4: 715 case 7:
626 mnem = "shl"; 716 mnem = "sar";
627 break; 717 break;
628 case 5: 718 default:
629 mnem = "shr"; 719 UnimplementedInstruction();
630 break; 720 return num_bytes;
631 case 7: 721 }
632 mnem = "sar"; 722 assert(mnem != NULL);
633 break; 723 if (op == 0xD0) {
634 default: 724 imm8 = 1;
635 UnimplementedInstruction(); 725 } else if (op == 0xC0) {
636 } 726 imm8 = *(data + 2);
637 } else if (op == 0xD3) { 727 num_bytes = 3;
638 switch (regop) { 728 }
639 case 4: 729 AppendToBuffer("%s%c %s,",
640 mnem = "shl"; 730 mnem,
641 break; 731 operand_size_code(),
642 case 5: 732 byte_size_operand_ ? NameOfByteCPURegister(rm)
643 mnem = "shr"; 733 : NameOfCPURegister(rm));
644 break; 734 if (op == 0xD2) {
645 case 7: 735 AppendToBuffer("cl");
646 mnem = "sar";
647 break;
648 default:
649 UnimplementedInstruction();
650 }
651 }
652 assert(mnem != NULL);
653 AppendToBuffer("%s%c %s,",
654 mnem,
655 operand_size_code(),
656 NameOfCPURegister(rm));
657 if (imm8 > 0) {
658 AppendToBuffer("%d", imm8);
659 } else {
660 AppendToBuffer("cl");
661 }
662 } else { 736 } else {
663 UnimplementedInstruction(); 737 AppendToBuffer("%d", imm8);
664 } 738 }
665 return num_bytes; 739 return num_bytes;
666 } 740 }
667 741
668 742
669 // Returns number of bytes used, including *data. 743 // Returns number of bytes used, including *data.
670 int DisassemblerX64::JumpShort(byte* data) { 744 int DisassemblerX64::JumpShort(byte* data) {
671 assert(*data == 0xEB); 745 assert(*data == 0xEB);
672 byte b = *(data + 1); 746 byte b = *(data + 1);
673 byte* dest = data + static_cast<int8_t>(b) + 2; 747 byte* dest = data + static_cast<int8_t>(b) + 2;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
709 } 783 }
710 784
711 785
712 // Returns number of bytes used, including *data. 786 // Returns number of bytes used, including *data.
713 int DisassemblerX64::FPUInstruction(byte* data) { 787 int DisassemblerX64::FPUInstruction(byte* data) {
714 byte b1 = *data; 788 byte b1 = *data;
715 byte b2 = *(data + 1); 789 byte b2 = *(data + 1);
716 if (b1 == 0xD9) { 790 if (b1 == 0xD9) {
717 const char* mnem = NULL; 791 const char* mnem = NULL;
718 switch (b2) { 792 switch (b2) {
719 case 0xE8: 793 case 0xE0:
720 mnem = "fld1"; 794 mnem = "fchs";
721 break;
722 case 0xEE:
723 mnem = "fldz";
724 break; 795 break;
725 case 0xE1: 796 case 0xE1:
726 mnem = "fabs"; 797 mnem = "fabs";
727 break; 798 break;
728 case 0xE0: 799 case 0xE4:
729 mnem = "fchs"; 800 mnem = "ftst";
730 break;
731 case 0xF8:
732 mnem = "fprem";
733 break; 801 break;
734 case 0xF5: 802 case 0xF5:
735 mnem = "fprem1"; 803 mnem = "fprem1";
736 break; 804 break;
737 case 0xF7: 805 case 0xF7:
738 mnem = "fincstp"; 806 mnem = "fincstp";
739 break; 807 break;
740 case 0xE4: 808 case 0xE8:
741 mnem = "ftst"; 809 mnem = "fld1";
810 break;
811 case 0xEE:
812 mnem = "fldz";
813 break;
814 case 0xF8:
815 mnem = "fprem";
742 break; 816 break;
743 } 817 }
744 if (mnem != NULL) { 818 if (mnem != NULL) {
745 AppendToBuffer("%s", mnem); 819 AppendToBuffer("%s", mnem);
746 return 2; 820 return 2;
747 } else if ((b2 & 0xF8) == 0xC8) { 821 } else if ((b2 & 0xF8) == 0xC8) {
748 AppendToBuffer("fxch st%d", b2 & 0x7); 822 AppendToBuffer("fxch st%d", b2 & 0x7);
749 return 2; 823 return 2;
750 } else { 824 } else {
751 int mod, regop, rm; 825 int mod, regop, rm;
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
899 tmp_buffer_pos_ = 0; // starting to write as position 0 973 tmp_buffer_pos_ = 0; // starting to write as position 0
900 byte* data = instr; 974 byte* data = instr;
901 bool processed = true; // Will be set to false if the current instruction 975 bool processed = true; // Will be set to false if the current instruction
902 // is not in 'instructions' table. 976 // is not in 'instructions' table.
903 byte current; 977 byte current;
904 978
905 // Scan for prefixes. 979 // Scan for prefixes.
906 while (true) { 980 while (true) {
907 current = *data; 981 current = *data;
908 if (current == 0x66) { 982 if (current == 0x66) {
909 setOperandSizePrefix(current); 983 // If the sequence is 66 0f, it's not a prefix, but a SSE escape.
984 if (*(data + 1) == 0x0F) break;
910 data++; 985 data++;
911 } else if ((current & 0xF0) == 0x40) { 986 } else if ((current & 0xF0) == 0x40) {
912 setRex(current); 987 setRex(current);
913 if (rex_w()) AppendToBuffer("REX.W "); 988 if (rex_w()) AppendToBuffer("REX.W ");
914 data++; 989 data++;
915 } else { 990 } else {
916 break; 991 break;
917 } 992 }
918 } 993 }
919 994
920 const InstructionDesc& idesc = instruction_table.Get(current); 995 const InstructionDesc& idesc = instruction_table.Get(current);
996 byte_size_operand_ = idesc.byte_size_operation;
921 switch (idesc.type) { 997 switch (idesc.type) {
922 case ZERO_OPERANDS_INSTR: 998 case ZERO_OPERANDS_INSTR:
923 AppendToBuffer(idesc.mnem); 999 AppendToBuffer(idesc.mnem);
924 data++; 1000 data++;
925 break; 1001 break;
926 1002
927 case TWO_OPERANDS_INSTR: 1003 case TWO_OPERANDS_INSTR:
928 data++; 1004 data++;
929 data += PrintOperands(idesc.mnem, idesc.op_order_, data); 1005 data += PrintOperands(idesc.mnem, idesc.op_order_, data);
930 break; 1006 break;
(...skipping 11 matching lines...) Expand all
942 break; 1018 break;
943 case PUSHPOP_INSTR: 1019 case PUSHPOP_INSTR:
944 AppendToBuffer("%s %s", 1020 AppendToBuffer("%s %s",
945 idesc.mnem, 1021 idesc.mnem,
946 NameOfCPURegister(base_reg(current & 0x07))); 1022 NameOfCPURegister(base_reg(current & 0x07)));
947 data++; 1023 data++;
948 break; 1024 break;
949 case MOVE_REG_INSTR: { 1025 case MOVE_REG_INSTR: {
950 byte* addr = NULL; 1026 byte* addr = NULL;
951 switch (operand_size()) { 1027 switch (operand_size()) {
952 case 16: 1028 case WORD_SIZE:
953 addr = reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1)); 1029 addr = reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1));
954 data += 3; 1030 data += 3;
955 break; 1031 break;
956 case 32: 1032 case DOUBLEWORD_SIZE:
957 addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1)); 1033 addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
958 data += 5; 1034 data += 5;
959 break; 1035 break;
960 case 64: 1036 case QUADWORD_SIZE:
961 addr = reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1)); 1037 addr = reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1));
962 data += 9; 1038 data += 9;
963 break; 1039 break;
964 default: 1040 default:
965 UNREACHABLE(); 1041 UNREACHABLE();
966 } 1042 }
967 AppendToBuffer("mov%c %s,%s", 1043 AppendToBuffer("mov%c %s,%s",
968 operand_size_code(), 1044 operand_size_code(),
969 NameOfCPURegister(base_reg(current & 0x07)), 1045 NameOfCPURegister(base_reg(current & 0x07)),
970 NameOfAddress(addr)); 1046 NameOfAddress(addr));
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1005 1081
1006 case 0x69: // fall through 1082 case 0x69: // fall through
1007 case 0x6B: { 1083 case 0x6B: {
1008 int mod, regop, rm; 1084 int mod, regop, rm;
1009 get_modrm(*(data + 1), &mod, &regop, &rm); 1085 get_modrm(*(data + 1), &mod, &regop, &rm);
1010 int32_t imm = *data == 0x6B ? *(data + 2) 1086 int32_t imm = *data == 0x6B ? *(data + 2)
1011 : *reinterpret_cast<int32_t*>(data + 2); 1087 : *reinterpret_cast<int32_t*>(data + 2);
1012 AppendToBuffer("imul %s,%s,0x%x", NameOfCPURegister(regop), 1088 AppendToBuffer("imul %s,%s,0x%x", NameOfCPURegister(regop),
1013 NameOfCPURegister(rm), imm); 1089 NameOfCPURegister(rm), imm);
1014 data += 2 + (*data == 0x6B ? 1 : 4); 1090 data += 2 + (*data == 0x6B ? 1 : 4);
1091 break;
1015 } 1092 }
1016 break;
1017 1093
1018 case 0xF6: { 1094 case 0xF6: {
1019 int mod, regop, rm; 1095 int mod, regop, rm;
1020 get_modrm(*(data + 1), &mod, &regop, &rm); 1096 get_modrm(*(data + 1), &mod, &regop, &rm);
1021 if (mod == 3 && regop == 0) { 1097 if (mod == 3 && regop == 0) {
1022 AppendToBuffer("testb %s,%d", NameOfCPURegister(rm), *(data + 2)); 1098 AppendToBuffer("testb %s,%d", NameOfCPURegister(rm), *(data + 2));
1023 } else { 1099 } else {
1024 UnimplementedInstruction(); 1100 UnimplementedInstruction();
1025 } 1101 }
1026 data += 3; 1102 data += 3;
1103 break;
1027 } 1104 }
1028 break;
1029 1105
1030 case 0x81: // fall through 1106 case 0x81: // fall through
1031 case 0x83: // 0x81 with sign extension bit set 1107 case 0x83: // 0x81 with sign extension bit set
1032 data += PrintImmediateOp(data); 1108 data += PrintImmediateOp(data);
1033 break; 1109 break;
1034 1110
1035 case 0x0F: { 1111 case 0x0F: {
1036 byte f0byte = *(data + 1); 1112 byte f0byte = *(data + 1);
1037 const char* f0mnem = F0Mnem(f0byte); 1113 const char* f0mnem = F0Mnem(f0byte);
1038 if (f0byte == 0x1F) { 1114 if (f0byte == 0x1F) {
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
1163 break; 1239 break;
1164 1240
1165 case 0x90: 1241 case 0x90:
1166 case 0x91: 1242 case 0x91:
1167 case 0x92: 1243 case 0x92:
1168 case 0x93: 1244 case 0x93:
1169 case 0x94: 1245 case 0x94:
1170 case 0x95: 1246 case 0x95:
1171 case 0x96: 1247 case 0x96:
1172 case 0x97: { 1248 case 0x97: {
1173 int reg = current & 0x7 | (rex_b() ? 8 : 0); 1249 int reg = (current & 0x7) | (rex_b() ? 8 : 0);
1174 if (reg == 0) { 1250 if (reg == 0) {
1175 AppendToBuffer("nop"); // Common name for xchg rax,rax. 1251 AppendToBuffer("nop"); // Common name for xchg rax,rax.
1176 } else { 1252 } else {
1177 AppendToBuffer("xchg%c rax, %s", 1253 AppendToBuffer("xchg%c rax, %s",
1178 operand_size_code(), 1254 operand_size_code(),
1179 NameOfByteCPURegister(reg)); 1255 NameOfCPURegister(reg));
1180 } 1256 }
1181 } 1257 }
1182 1258
1183 1259
1184 case 0xFE: { 1260 case 0xFE: {
1185 data++; 1261 data++;
1186 int mod, regop, rm; 1262 int mod, regop, rm;
1187 get_modrm(*data, &mod, &regop, &rm); 1263 get_modrm(*data, &mod, &regop, &rm);
1188 if (mod == 3 && regop == 1) { 1264 if (mod == 3 && regop == 1) {
1189 AppendToBuffer("decb %s", NameOfCPURegister(rm)); 1265 AppendToBuffer("decb %s", NameOfCPURegister(rm));
(...skipping 12 matching lines...) Expand all
1202 case 0x6A: 1278 case 0x6A:
1203 AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1)); 1279 AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
1204 data += 2; 1280 data += 2;
1205 break; 1281 break;
1206 1282
1207 case 0xA8: 1283 case 0xA8:
1208 AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1)); 1284 AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1));
1209 data += 2; 1285 data += 2;
1210 break; 1286 break;
1211 1287
1212 case 0xA9: 1288 case 0xA9: {
1213 AppendToBuffer("test%c rax,0x%x", // CHECKME! 1289 int64_t value;
1290 switch (operand_size()) {
1291 case WORD_SIZE:
1292 value = *reinterpret_cast<uint16_t*>(data + 1);
1293 data += 3;
1294 break;
1295 case DOUBLEWORD_SIZE:
1296 value = *reinterpret_cast<uint32_t*>(data + 1);
1297 data += 5;
1298 break;
1299 case QUADWORD_SIZE:
1300 value = *reinterpret_cast<int32_t*>(data + 1);
1301 data += 5;
1302 break;
1303 default:
1304 UNREACHABLE();
1305 }
1306 break;
1307 AppendToBuffer("test%c rax,0x%"V8_PTR_PREFIX"ux",
1214 operand_size_code(), 1308 operand_size_code(),
1215 *reinterpret_cast<int32_t*>(data + 1)); 1309 value);
1216 data += 5; 1310 }
1217 break;
1218
1219 case 0xD1: // fall through 1311 case 0xD1: // fall through
1220 case 0xD3: // fall through 1312 case 0xD3: // fall through
1221 case 0xC1: 1313 case 0xC1:
1222 data += D1D3C1Instruction(data); 1314 data += ShiftInstruction(data);
1315 break;
1316 case 0xD0: // fall through
1317 case 0xD2: // fall through
1318 case 0xC0:
1319 byte_size_operand_ = true;
1320 data += ShiftInstruction(data);
1223 break; 1321 break;
1224 1322
1225 case 0xD9: // fall through 1323 case 0xD9: // fall through
1226 case 0xDA: // fall through 1324 case 0xDA: // fall through
1227 case 0xDB: // fall through 1325 case 0xDB: // fall through
1228 case 0xDC: // fall through 1326 case 0xDC: // fall through
1229 case 0xDD: // fall through 1327 case 0xDD: // fall through
1230 case 0xDE: // fall through 1328 case 0xDE: // fall through
1231 case 0xDF: 1329 case 0xDF:
1232 data += FPUInstruction(data); 1330 data += FPUInstruction(data);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1282 NameOfXMMRegister(rm)); 1380 NameOfXMMRegister(rm));
1283 data++; 1381 data++;
1284 } 1382 }
1285 } 1383 }
1286 } else { 1384 } else {
1287 UnimplementedInstruction(); 1385 UnimplementedInstruction();
1288 } 1386 }
1289 break; 1387 break;
1290 1388
1291 case 0xF3: 1389 case 0xF3:
1292 if (*(data + 1) == 0x0F && *(data + 2) == 0x2C) { 1390 if (*(data + 1) == 0x0F) {
1293 data += 3; 1391 if (*(data + 2) == 0x2C) {
1294 data += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, data); 1392 data += 3;
1393 data += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, data);
1394 } else {
1395 UnimplementedInstruction();
1396 data += 1;
1397 }
1295 } else { 1398 } else {
1296 UnimplementedInstruction(); 1399 UnimplementedInstruction();
1400 data += 1;
1297 } 1401 }
1298 break; 1402 break;
1299 1403
1300 case 0xF7: 1404 case 0xF7:
1301 data += F7Instruction(data); 1405 data += F7Instruction(data);
1302 break; 1406 break;
1303 1407
1304 default: 1408 default:
1305 UnimplementedInstruction(); 1409 UnimplementedInstruction();
1410 data += 1;
1306 } 1411 }
1307 } // !processed 1412 } // !processed
1308 1413
1309 if (tmp_buffer_pos_ < sizeof tmp_buffer_) { 1414 if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
1310 tmp_buffer_[tmp_buffer_pos_] = '\0'; 1415 tmp_buffer_[tmp_buffer_pos_] = '\0';
1311 } 1416 }
1312 1417
1313 int instr_len = data - instr; 1418 int instr_len = data - instr;
1314 ASSERT(instr_len > 0); // Ensure progress. 1419 ASSERT(instr_len > 0); // Ensure progress.
1315 1420
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1423 fprintf(f, "%02x", *bp); 1528 fprintf(f, "%02x", *bp);
1424 } 1529 }
1425 for (int i = 6 - (pc - prev_pc); i >= 0; i--) { 1530 for (int i = 6 - (pc - prev_pc); i >= 0; i--) {
1426 fprintf(f, " "); 1531 fprintf(f, " ");
1427 } 1532 }
1428 fprintf(f, " %s\n", buffer.start()); 1533 fprintf(f, " %s\n", buffer.start());
1429 } 1534 }
1430 } 1535 }
1431 1536
1432 } // namespace disasm 1537 } // namespace disasm
OLDNEW
« no previous file with comments | « src/x64/assembler-x64.h ('k') | test/cctest/cctest.status » ('j') | test/cctest/cctest.status » ('J')

Powered by Google App Engine
This is Rietveld 408576698