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

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

Issue 155346: X64: Fixed test .status format, and made test.py forward arch to scons. (Closed)
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
« no previous file with comments | « src/x64/assembler-x64.h ('k') | test/cctest/cctest.status » ('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 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) {
William Hesse 2009/07/14 09:09:22 I would call the argument immediate_size, since th
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 }
532 AppendToBuffer(V8_PTR_PREFIX"x", value);
533 return count;
534 }
535
536
454 int DisassemblerX64::PrintRightOperand(byte* modrmp) { 537 int DisassemblerX64::PrintRightOperand(byte* modrmp) {
455 return PrintRightOperandHelper(modrmp, 538 return PrintRightOperandHelper(modrmp,
456 &DisassemblerX64::NameOfCPURegister); 539 &DisassemblerX64::NameOfCPURegister);
457 } 540 }
458 541
459 542
460 int DisassemblerX64::PrintRightByteOperand(byte* modrmp) { 543 int DisassemblerX64::PrintRightByteOperand(byte* modrmp) {
461 return PrintRightOperandHelper(modrmp, 544 return PrintRightOperandHelper(modrmp,
462 &DisassemblerX64::NameOfByteCPURegister); 545 &DisassemblerX64::NameOfByteCPURegister);
463 } 546 }
464 547
465 548
466 // Returns number of bytes used including the current *data. 549 // Returns number of bytes used including the current *data.
467 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'. 550 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
468 int DisassemblerX64::PrintOperands(const char* mnem, 551 int DisassemblerX64::PrintOperands(const char* mnem,
469 OperandOrder op_order, 552 OperandType op_order,
470 byte* data) { 553 byte* data) {
471 byte modrm = *data; 554 byte modrm = *data;
472 int mod, regop, rm; 555 int mod, regop, rm;
473 get_modrm(modrm, &mod, &regop, &rm); 556 get_modrm(modrm, &mod, &regop, &rm);
474 int advance = 0; 557 int advance = 0;
558 const char* register_name =
559 byte_size_operand_ ? NameOfByteCPURegister(regop)
560 : NameOfCPURegister(regop);
475 switch (op_order) { 561 switch (op_order) {
476 case REG_OPER_OP_ORDER: { 562 case REG_OPER_OP_ORDER: {
477 AppendToBuffer("%s%c %s,", 563 AppendToBuffer("%s%c %s,",
478 mnem, 564 mnem,
479 operand_size_code(), 565 operand_size_code(),
480 NameOfCPURegister(regop)); 566 register_name);
481 advance = PrintRightOperand(data); 567 advance = byte_size_operand_ ? PrintRightByteOperand(data)
568 : PrintRightOperand(data);
482 break; 569 break;
483 } 570 }
484 case OPER_REG_OP_ORDER: { 571 case OPER_REG_OP_ORDER: {
485 AppendToBuffer("%s%c ", mnem, operand_size_code()); 572 AppendToBuffer("%s%c ", mnem, operand_size_code());
486 advance = PrintRightOperand(data); 573 advance = byte_size_operand_ ? PrintRightByteOperand(data)
487 AppendToBuffer(",%s", NameOfCPURegister(regop)); 574 : PrintRightOperand(data);
575 AppendToBuffer(",%s", register_name);
488 break; 576 break;
489 } 577 }
490 default: 578 default:
491 UNREACHABLE(); 579 UNREACHABLE();
492 break; 580 break;
493 } 581 }
494 return advance; 582 return advance;
495 } 583 }
496 584
497 585
498 // Returns number of bytes used by machine instruction, including *data byte. 586 // Returns number of bytes used by machine instruction, including *data byte.
499 // Writes immediate instructions to 'tmp_buffer_'. 587 // Writes immediate instructions to 'tmp_buffer_'.
500 int DisassemblerX64::PrintImmediateOp(byte* data) { 588 int DisassemblerX64::PrintImmediateOp(byte* data) {
501 bool sign_extension_bit = (*data & 0x02) != 0; 589 bool byte_size_immediate = (*data & 0x02) != 0;
502 byte modrm = *(data + 1); 590 byte modrm = *(data + 1);
503 int mod, regop, rm; 591 int mod, regop, rm;
504 get_modrm(modrm, &mod, &regop, &rm); 592 get_modrm(modrm, &mod, &regop, &rm);
505 const char* mnem = "Imm???"; 593 const char* mnem = "Imm???";
506 switch (regop) { 594 switch (regop) {
507 case 0: 595 case 0:
508 mnem = "add"; 596 mnem = "add";
509 break; 597 break;
510 case 1: 598 case 1:
511 mnem = "or"; 599 mnem = "or";
512 break; 600 break;
513 case 2: 601 case 2:
514 mnem = "adc"; 602 mnem = "adc";
515 break; 603 break;
516 case 4: 604 case 4:
517 mnem = "and"; 605 mnem = "and";
518 break; 606 break;
519 case 5: 607 case 5:
520 mnem = "sub"; 608 mnem = "sub";
521 break; 609 break;
522 case 6: 610 case 6:
523 mnem = "xor"; 611 mnem = "xor";
524 break; 612 break;
525 case 7: 613 case 7:
526 mnem = "cmp"; 614 mnem = "cmp";
527 break; 615 break;
528 default: 616 default:
529 UnimplementedInstruction(); 617 UnimplementedInstruction();
530 } 618 }
531 AppendToBuffer("%s ", mnem); 619 AppendToBuffer("%s%c ", mnem, operand_size_code());
532 int count = PrintRightOperand(data + 1); 620 int count = PrintRightOperand(data + 1);
533 if (sign_extension_bit) { 621 AppendToBuffer(",0x");
534 AppendToBuffer(",0x%x", *(data + 1 + count)); 622 OperandSize op_size = byte_size_immediate ? BYTE_SIZE : operand_size();
William Hesse 2009/07/14 09:09:22 immediate_size, not op_size.
535 return 1 + count + 1 /*int8*/; 623 count += PrintImmediate(data + 1 + count, op_size);
536 } else { 624 return 1 + count;
537 AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count));
538 return 1 + count + 4 /*int32_t*/;
539 }
540 } 625 }
541 626
542 627
543 // Returns number of bytes used, including *data. 628 // Returns number of bytes used, including *data.
544 int DisassemblerX64::F7Instruction(byte* data) { 629 int DisassemblerX64::F7Instruction(byte* data) {
545 assert(*data == 0xF7); 630 assert(*data == 0xF7);
546 byte modrm = *(data + 1); 631 byte modrm = *(data + 1);
547 int mod, regop, rm; 632 int mod, regop, rm;
548 get_modrm(modrm, &mod, &regop, &rm); 633 get_modrm(modrm, &mod, &regop, &rm);
549 if (mod == 3 && regop != 0) { 634 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); 667 int32_t imm = *reinterpret_cast<int32_t*>(data + 1 + count);
583 AppendToBuffer(",0x%x", imm); 668 AppendToBuffer(",0x%x", imm);
584 return 1 + count + 4 /*int32_t*/; 669 return 1 + count + 4 /*int32_t*/;
585 } else { 670 } else {
586 UnimplementedInstruction(); 671 UnimplementedInstruction();
587 return 2; 672 return 2;
588 } 673 }
589 } 674 }
590 675
591 676
592 int DisassemblerX64::D1D3C1Instruction(byte* data) { 677 int DisassemblerX64::ShiftInstruction(byte* data) {
593 byte op = *data; 678 byte op = *data & (~1);
594 assert(op == 0xD1 || op == 0xD3 || op == 0xC1); 679 if (op != 0xD0 && op == 0xD0 && op == 0xC0) {
680 UnimplementedInstruction();
681 return 1;
682 }
595 byte modrm = *(data + 1); 683 byte modrm = *(data + 1);
596 int mod, regop, rm; 684 int mod, regop, rm;
597 get_modrm(modrm, &mod, &regop, &rm); 685 get_modrm(modrm, &mod, &regop, &rm);
598 ASSERT(regop < 8); 686 ASSERT(regop < 8);
599 int imm8 = -1; 687 int imm8 = -1;
600 int num_bytes = 2; 688 int num_bytes = 2;
601 if (mod == 3) { 689 if (mod != 3) {
602 const char* mnem = NULL; 690 UnimplementedInstruction();
603 if (op == 0xD1) { 691 return num_bytes;
604 imm8 = 1; 692 }
605 switch (regop) { 693 const char* mnem = NULL;
606 case 2: 694 switch (regop) {
607 mnem = "rcl"; 695 case 0:
608 break; 696 mnem = "rol";
609 case 7: 697 break;
610 mnem = "sar"; 698 case 1:
611 break; 699 mnem = "ror";
612 case 4: 700 break;
613 mnem = "shl"; 701 case 2:
614 break; 702 mnem = "rcl";
615 default: 703 break;
616 UnimplementedInstruction(); 704 case 3:
617 } 705 mnem = "rcr";
618 } else if (op == 0xC1) { 706 break;
619 imm8 = *(data + 2); 707 case 4:
620 num_bytes = 3; 708 mnem = "shl";
621 switch (regop) { 709 break;
622 case 2: 710 case 5:
623 mnem = "rcl"; 711 mnem = "shr";
624 break; 712 break;
625 case 4: 713 case 7:
626 mnem = "shl"; 714 mnem = "sar";
627 break; 715 break;
628 case 5: 716 default:
629 mnem = "shr"; 717 UnimplementedInstruction();
630 break; 718 return num_bytes;
631 case 7: 719 }
632 mnem = "sar"; 720 assert(mnem != NULL);
633 break; 721 if (op == 0xD0) {
634 default: 722 imm8 = 1;
635 UnimplementedInstruction(); 723 } else if (op == 0xC0) {
636 } 724 imm8 = *(data + 2);
637 } else if (op == 0xD3) { 725 num_bytes = 3;
638 switch (regop) { 726 }
639 case 4: 727 AppendToBuffer("%s%c %s,",
640 mnem = "shl"; 728 mnem,
641 break; 729 operand_size_code(),
642 case 5: 730 byte_size_operand_ ? NameOfByteCPURegister(rm)
643 mnem = "shr"; 731 : NameOfCPURegister(rm));
644 break; 732 if (imm8 > 0) {
William Hesse 2009/07/14 09:09:22 This seems wrong. Why aren't we testing the opcod
645 case 7: 733 AppendToBuffer("%d", imm8);
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 { 734 } else {
663 UnimplementedInstruction(); 735 AppendToBuffer("cl");
664 } 736 }
665 return num_bytes; 737 return num_bytes;
666 } 738 }
667 739
668 740
669 // Returns number of bytes used, including *data. 741 // Returns number of bytes used, including *data.
670 int DisassemblerX64::JumpShort(byte* data) { 742 int DisassemblerX64::JumpShort(byte* data) {
671 assert(*data == 0xEB); 743 assert(*data == 0xEB);
672 byte b = *(data + 1); 744 byte b = *(data + 1);
673 byte* dest = data + static_cast<int8_t>(b) + 2; 745 byte* dest = data + static_cast<int8_t>(b) + 2;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
709 } 781 }
710 782
711 783
712 // Returns number of bytes used, including *data. 784 // Returns number of bytes used, including *data.
713 int DisassemblerX64::FPUInstruction(byte* data) { 785 int DisassemblerX64::FPUInstruction(byte* data) {
714 byte b1 = *data; 786 byte b1 = *data;
715 byte b2 = *(data + 1); 787 byte b2 = *(data + 1);
716 if (b1 == 0xD9) { 788 if (b1 == 0xD9) {
717 const char* mnem = NULL; 789 const char* mnem = NULL;
718 switch (b2) { 790 switch (b2) {
719 case 0xE8: 791 case 0xE0:
720 mnem = "fld1"; 792 mnem = "fchs";
721 break;
722 case 0xEE:
723 mnem = "fldz";
724 break; 793 break;
725 case 0xE1: 794 case 0xE1:
726 mnem = "fabs"; 795 mnem = "fabs";
727 break; 796 break;
728 case 0xE0: 797 case 0xE4:
729 mnem = "fchs"; 798 mnem = "ftst";
730 break;
731 case 0xF8:
732 mnem = "fprem";
733 break; 799 break;
734 case 0xF5: 800 case 0xF5:
735 mnem = "fprem1"; 801 mnem = "fprem1";
736 break; 802 break;
737 case 0xF7: 803 case 0xF7:
738 mnem = "fincstp"; 804 mnem = "fincstp";
739 break; 805 break;
740 case 0xE4: 806 case 0xE8:
741 mnem = "ftst"; 807 mnem = "fld1";
808 break;
809 case 0xEE:
810 mnem = "fldz";
811 break;
812 case 0xF8:
813 mnem = "fprem";
742 break; 814 break;
743 } 815 }
744 if (mnem != NULL) { 816 if (mnem != NULL) {
745 AppendToBuffer("%s", mnem); 817 AppendToBuffer("%s", mnem);
746 return 2; 818 return 2;
747 } else if ((b2 & 0xF8) == 0xC8) { 819 } else if ((b2 & 0xF8) == 0xC8) {
748 AppendToBuffer("fxch st%d", b2 & 0x7); 820 AppendToBuffer("fxch st%d", b2 & 0x7);
749 return 2; 821 return 2;
750 } else { 822 } else {
751 int mod, regop, rm; 823 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 971 tmp_buffer_pos_ = 0; // starting to write as position 0
900 byte* data = instr; 972 byte* data = instr;
901 bool processed = true; // Will be set to false if the current instruction 973 bool processed = true; // Will be set to false if the current instruction
902 // is not in 'instructions' table. 974 // is not in 'instructions' table.
903 byte current; 975 byte current;
904 976
905 // Scan for prefixes. 977 // Scan for prefixes.
906 while (true) { 978 while (true) {
907 current = *data; 979 current = *data;
908 if (current == 0x66) { 980 if (current == 0x66) {
909 setOperandSizePrefix(current); 981 // If the sequence is 66 0f, it's not a prefix, but a SSE escape.
982 if (*(data + 1) == 0x0F) break;
910 data++; 983 data++;
911 } else if ((current & 0xF0) == 0x40) { 984 } else if ((current & 0xF0) == 0x40) {
912 setRex(current); 985 setRex(current);
913 if (rex_w()) AppendToBuffer("REX.W "); 986 if (rex_w()) AppendToBuffer("REX.W ");
914 data++; 987 data++;
915 } else { 988 } else {
916 break; 989 break;
917 } 990 }
918 } 991 }
919 992
920 const InstructionDesc& idesc = instruction_table.Get(current); 993 const InstructionDesc& idesc = instruction_table.Get(current);
994 byte_size_operand_ = idesc.byte_size_operation;
921 switch (idesc.type) { 995 switch (idesc.type) {
922 case ZERO_OPERANDS_INSTR: 996 case ZERO_OPERANDS_INSTR:
923 AppendToBuffer(idesc.mnem); 997 AppendToBuffer(idesc.mnem);
924 data++; 998 data++;
925 break; 999 break;
926 1000
927 case TWO_OPERANDS_INSTR: 1001 case TWO_OPERANDS_INSTR:
928 data++; 1002 data++;
929 data += PrintOperands(idesc.mnem, idesc.op_order_, data); 1003 data += PrintOperands(idesc.mnem, idesc.op_order_, data);
930 break; 1004 break;
(...skipping 11 matching lines...) Expand all
942 break; 1016 break;
943 case PUSHPOP_INSTR: 1017 case PUSHPOP_INSTR:
944 AppendToBuffer("%s %s", 1018 AppendToBuffer("%s %s",
945 idesc.mnem, 1019 idesc.mnem,
946 NameOfCPURegister(base_reg(current & 0x07))); 1020 NameOfCPURegister(base_reg(current & 0x07)));
947 data++; 1021 data++;
948 break; 1022 break;
949 case MOVE_REG_INSTR: { 1023 case MOVE_REG_INSTR: {
950 byte* addr = NULL; 1024 byte* addr = NULL;
951 switch (operand_size()) { 1025 switch (operand_size()) {
952 case 16: 1026 case WORD_SIZE:
953 addr = reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1)); 1027 addr = reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1));
954 data += 3; 1028 data += 3;
955 break; 1029 break;
956 case 32: 1030 case DOUBLEWORD_SIZE:
957 addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1)); 1031 addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
958 data += 5; 1032 data += 5;
959 break; 1033 break;
960 case 64: 1034 case QUADWORD_SIZE:
961 addr = reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1)); 1035 addr = reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1));
962 data += 9; 1036 data += 9;
963 break; 1037 break;
964 default: 1038 default:
965 UNREACHABLE(); 1039 UNREACHABLE();
966 } 1040 }
967 AppendToBuffer("mov%c %s,%s", 1041 AppendToBuffer("mov%c %s,%s",
968 operand_size_code(), 1042 operand_size_code(),
969 NameOfCPURegister(base_reg(current & 0x07)), 1043 NameOfCPURegister(base_reg(current & 0x07)),
970 NameOfAddress(addr)); 1044 NameOfAddress(addr));
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1005 1079
1006 case 0x69: // fall through 1080 case 0x69: // fall through
1007 case 0x6B: { 1081 case 0x6B: {
1008 int mod, regop, rm; 1082 int mod, regop, rm;
1009 get_modrm(*(data + 1), &mod, &regop, &rm); 1083 get_modrm(*(data + 1), &mod, &regop, &rm);
1010 int32_t imm = *data == 0x6B ? *(data + 2) 1084 int32_t imm = *data == 0x6B ? *(data + 2)
1011 : *reinterpret_cast<int32_t*>(data + 2); 1085 : *reinterpret_cast<int32_t*>(data + 2);
1012 AppendToBuffer("imul %s,%s,0x%x", NameOfCPURegister(regop), 1086 AppendToBuffer("imul %s,%s,0x%x", NameOfCPURegister(regop),
1013 NameOfCPURegister(rm), imm); 1087 NameOfCPURegister(rm), imm);
1014 data += 2 + (*data == 0x6B ? 1 : 4); 1088 data += 2 + (*data == 0x6B ? 1 : 4);
1089 break;
1015 } 1090 }
1016 break;
1017 1091
1018 case 0xF6: { 1092 case 0xF6: {
1019 int mod, regop, rm; 1093 int mod, regop, rm;
1020 get_modrm(*(data + 1), &mod, &regop, &rm); 1094 get_modrm(*(data + 1), &mod, &regop, &rm);
1021 if (mod == 3 && regop == 0) { 1095 if (mod == 3 && regop == 0) {
1022 AppendToBuffer("testb %s,%d", NameOfCPURegister(rm), *(data + 2)); 1096 AppendToBuffer("testb %s,%d", NameOfCPURegister(rm), *(data + 2));
1023 } else { 1097 } else {
1024 UnimplementedInstruction(); 1098 UnimplementedInstruction();
1025 } 1099 }
1026 data += 3; 1100 data += 3;
1101 break;
1027 } 1102 }
1028 break;
1029 1103
1030 case 0x81: // fall through 1104 case 0x81: // fall through
1031 case 0x83: // 0x81 with sign extension bit set 1105 case 0x83: // 0x81 with sign extension bit set
1032 data += PrintImmediateOp(data); 1106 data += PrintImmediateOp(data);
1033 break; 1107 break;
1034 1108
1035 case 0x0F: { 1109 case 0x0F: {
1036 byte f0byte = *(data + 1); 1110 byte f0byte = *(data + 1);
1037 const char* f0mnem = F0Mnem(f0byte); 1111 const char* f0mnem = F0Mnem(f0byte);
1038 if (f0byte == 0x1F) { 1112 if (f0byte == 0x1F) {
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
1163 break; 1237 break;
1164 1238
1165 case 0x90: 1239 case 0x90:
1166 case 0x91: 1240 case 0x91:
1167 case 0x92: 1241 case 0x92:
1168 case 0x93: 1242 case 0x93:
1169 case 0x94: 1243 case 0x94:
1170 case 0x95: 1244 case 0x95:
1171 case 0x96: 1245 case 0x96:
1172 case 0x97: { 1246 case 0x97: {
1173 int reg = current & 0x7 | (rex_b() ? 8 : 0); 1247 int reg = (current & 0x7) | (rex_b() ? 8 : 0);
1174 if (reg == 0) { 1248 if (reg == 0) {
1175 AppendToBuffer("nop"); // Common name for xchg rax,rax. 1249 AppendToBuffer("nop"); // Common name for xchg rax,rax.
1176 } else { 1250 } else {
1177 AppendToBuffer("xchg%c rax, %s", 1251 AppendToBuffer("xchg%c rax, %s",
1178 operand_size_code(), 1252 operand_size_code(),
1179 NameOfByteCPURegister(reg)); 1253 NameOfCPURegister(reg));
1180 } 1254 }
1181 } 1255 }
1182 1256
1183 1257
1184 case 0xFE: { 1258 case 0xFE: {
1185 data++; 1259 data++;
1186 int mod, regop, rm; 1260 int mod, regop, rm;
1187 get_modrm(*data, &mod, &regop, &rm); 1261 get_modrm(*data, &mod, &regop, &rm);
1188 if (mod == 3 && regop == 1) { 1262 if (mod == 3 && regop == 1) {
1189 AppendToBuffer("decb %s", NameOfCPURegister(rm)); 1263 AppendToBuffer("decb %s", NameOfCPURegister(rm));
(...skipping 12 matching lines...) Expand all
1202 case 0x6A: 1276 case 0x6A:
1203 AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1)); 1277 AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
1204 data += 2; 1278 data += 2;
1205 break; 1279 break;
1206 1280
1207 case 0xA8: 1281 case 0xA8:
1208 AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1)); 1282 AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1));
1209 data += 2; 1283 data += 2;
1210 break; 1284 break;
1211 1285
1212 case 0xA9: 1286 case 0xA9: {
1213 AppendToBuffer("test%c rax,0x%x", // CHECKME! 1287 int64_t value;
1288 switch (operand_size()) {
1289 case WORD_SIZE:
1290 value = *reinterpret_cast<uint16_t*>(data + 1);
1291 data += 3;
1292 break;
1293 case DOUBLEWORD_SIZE:
1294 value = *reinterpret_cast<uint32_t*>(data + 1);
1295 data += 5;
1296 break;
1297 case QUADWORD_SIZE:
1298 value = *reinterpret_cast<int32_t*>(data + 1);
1299 data += 5;
1300 break;
1301 default:
1302 UNREACHABLE();
1303 }
1304 break;
1305 AppendToBuffer("test%c rax,0x%"V8_PTR_PREFIX"ux",
1214 operand_size_code(), 1306 operand_size_code(),
1215 *reinterpret_cast<int32_t*>(data + 1)); 1307 value);
1216 data += 5; 1308 }
1217 break;
1218
1219 case 0xD1: // fall through 1309 case 0xD1: // fall through
1220 case 0xD3: // fall through 1310 case 0xD3: // fall through
1221 case 0xC1: 1311 case 0xC1:
1222 data += D1D3C1Instruction(data); 1312 data += ShiftInstruction(data);
1313 break;
1314 case 0xD0: // fall through
1315 case 0xD2: // fall through
1316 case 0xC0:
1317 byte_size_operand_ = true;
1318 data += ShiftInstruction(data);
1223 break; 1319 break;
1224 1320
1225 case 0xD9: // fall through 1321 case 0xD9: // fall through
1226 case 0xDA: // fall through 1322 case 0xDA: // fall through
1227 case 0xDB: // fall through 1323 case 0xDB: // fall through
1228 case 0xDC: // fall through 1324 case 0xDC: // fall through
1229 case 0xDD: // fall through 1325 case 0xDD: // fall through
1230 case 0xDE: // fall through 1326 case 0xDE: // fall through
1231 case 0xDF: 1327 case 0xDF:
1232 data += FPUInstruction(data); 1328 data += FPUInstruction(data);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1282 NameOfXMMRegister(rm)); 1378 NameOfXMMRegister(rm));
1283 data++; 1379 data++;
1284 } 1380 }
1285 } 1381 }
1286 } else { 1382 } else {
1287 UnimplementedInstruction(); 1383 UnimplementedInstruction();
1288 } 1384 }
1289 break; 1385 break;
1290 1386
1291 case 0xF3: 1387 case 0xF3:
1292 if (*(data + 1) == 0x0F && *(data + 2) == 0x2C) { 1388 if (*(data + 1) == 0x0F) {
1293 data += 3; 1389 if (*(data + 2) == 0x2C) {
1294 data += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, data); 1390 data += 3;
1391 data += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, data);
1392 } else {
1393 UnimplementedInstruction();
1394 data += 1;
1395 }
1295 } else { 1396 } else {
1296 UnimplementedInstruction(); 1397 UnimplementedInstruction();
1398 data += 1;
1297 } 1399 }
1298 break; 1400 break;
1299 1401
1300 case 0xF7: 1402 case 0xF7:
1301 data += F7Instruction(data); 1403 data += F7Instruction(data);
1302 break; 1404 break;
1303 1405
1304 default: 1406 default:
1305 UnimplementedInstruction(); 1407 UnimplementedInstruction();
1408 data += 1;
1306 } 1409 }
1307 } // !processed 1410 } // !processed
1308 1411
1309 if (tmp_buffer_pos_ < sizeof tmp_buffer_) { 1412 if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
1310 tmp_buffer_[tmp_buffer_pos_] = '\0'; 1413 tmp_buffer_[tmp_buffer_pos_] = '\0';
1311 } 1414 }
1312 1415
1313 int instr_len = data - instr; 1416 int instr_len = data - instr;
1314 ASSERT(instr_len > 0); // Ensure progress. 1417 ASSERT(instr_len > 0); // Ensure progress.
1315 1418
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1423 fprintf(f, "%02x", *bp); 1526 fprintf(f, "%02x", *bp);
1424 } 1527 }
1425 for (int i = 6 - (pc - prev_pc); i >= 0; i--) { 1528 for (int i = 6 - (pc - prev_pc); i >= 0; i--) {
1426 fprintf(f, " "); 1529 fprintf(f, " ");
1427 } 1530 }
1428 fprintf(f, " %s\n", buffer.start()); 1531 fprintf(f, " %s\n", buffer.start());
1429 } 1532 }
1430 } 1533 }
1431 1534
1432 } // namespace disasm 1535 } // namespace disasm
OLDNEW
« no previous file with comments | « src/x64/assembler-x64.h ('k') | test/cctest/cctest.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698