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

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

Issue 155771: X64: Add instructions to disassembler. Skip hanging test-api test. (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
« no previous file with comments | « no previous file | no next file » | 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 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 assert(id->type == NO_INSTR); // Information already entered 246 assert(id->type == NO_INSTR); // Information already entered
247 id->mnem = NULL; // Computed depending on condition code. 247 id->mnem = NULL; // Computed depending on condition code.
248 id->type = JUMP_CONDITIONAL_SHORT_INSTR; 248 id->type = JUMP_CONDITIONAL_SHORT_INSTR;
249 } 249 }
250 } 250 }
251 251
252 252
253 static InstructionTable instruction_table; 253 static InstructionTable instruction_table;
254 254
255 255
256 // The X64 disassembler implementation. 256 //------------------------------------------------------------------------------
257 // DisassemblerX64 implementation.
258
257 enum UnimplementedOpcodeAction { 259 enum UnimplementedOpcodeAction {
258 CONTINUE_ON_UNIMPLEMENTED_OPCODE, 260 CONTINUE_ON_UNIMPLEMENTED_OPCODE,
259 ABORT_ON_UNIMPLEMENTED_OPCODE 261 ABORT_ON_UNIMPLEMENTED_OPCODE
260 }; 262 };
261 263
262 264 // A new DisassemblerX64 object is created to disassemble each instruction.
265 // The object can only disassemble a single instruction.
263 class DisassemblerX64 { 266 class DisassemblerX64 {
264 public: 267 public:
265 DisassemblerX64(const NameConverter& converter, 268 DisassemblerX64(const NameConverter& converter,
266 UnimplementedOpcodeAction unimplemented_action = 269 UnimplementedOpcodeAction unimplemented_action =
267 ABORT_ON_UNIMPLEMENTED_OPCODE) 270 ABORT_ON_UNIMPLEMENTED_OPCODE)
268 : converter_(converter), 271 : converter_(converter),
269 tmp_buffer_pos_(0), 272 tmp_buffer_pos_(0),
270 abort_on_unimplemented_( 273 abort_on_unimplemented_(
271 unimplemented_action == ABORT_ON_UNIMPLEMENTED_OPCODE), 274 unimplemented_action == ABORT_ON_UNIMPLEMENTED_OPCODE),
272 rex_(0), 275 rex_(0),
273 operand_size_(0), 276 operand_size_(0),
277 group_1_prefix_(0),
274 byte_size_operand_(false) { 278 byte_size_operand_(false) {
275 tmp_buffer_[0] = '\0'; 279 tmp_buffer_[0] = '\0';
276 } 280 }
277 281
278 virtual ~DisassemblerX64() { 282 virtual ~DisassemblerX64() {
279 } 283 }
280 284
281 // Writes one disassembled instruction into 'buffer' (0-terminated). 285 // Writes one disassembled instruction into 'buffer' (0-terminated).
282 // Returns the length of the disassembled machine instruction in bytes. 286 // Returns the length of the disassembled machine instruction in bytes.
283 int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); 287 int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
284 288
285 private: 289 private:
286 enum OperandSize { 290 enum OperandSize {
287 BYTE_SIZE = 0, 291 BYTE_SIZE = 0,
288 WORD_SIZE = 1, 292 WORD_SIZE = 1,
289 DOUBLEWORD_SIZE = 2, 293 DOUBLEWORD_SIZE = 2,
290 QUADWORD_SIZE = 3 294 QUADWORD_SIZE = 3
291 }; 295 };
292 296
293 const NameConverter& converter_; 297 const NameConverter& converter_;
294 v8::internal::EmbeddedVector<char, 128> tmp_buffer_; 298 v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
295 unsigned int tmp_buffer_pos_; 299 unsigned int tmp_buffer_pos_;
296 bool abort_on_unimplemented_; 300 bool abort_on_unimplemented_;
297 // Prefixes parsed 301 // Prefixes parsed
298 byte rex_; 302 byte rex_;
299 byte operand_size_; 303 byte operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0.
304 byte group_1_prefix_; // 0xF2, 0xF3, or (if no group 1 prefix is present) 0.
300 // Byte size operand override. 305 // Byte size operand override.
301 bool byte_size_operand_; 306 bool byte_size_operand_;
302 307
303 void setOperandSizePrefix(byte prefix) {
304 ASSERT_EQ(0x66, prefix);
305 operand_size_ = prefix;
306 }
307
308 void setRex(byte rex) { 308 void setRex(byte rex) {
309 ASSERT_EQ(0x40, rex & 0xF0); 309 ASSERT_EQ(0x40, rex & 0xF0);
310 rex_ = rex; 310 rex_ = rex;
311 } 311 }
312 312
313 bool rex() { return rex_ != 0; } 313 bool rex() { return rex_ != 0; }
314 314
315 bool rex_b() { return (rex_ & 0x01) != 0; } 315 bool rex_b() { return (rex_ & 0x01) != 0; }
316 316
317 // 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.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 373
374 int PrintRightOperandHelper(byte* modrmp, 374 int PrintRightOperandHelper(byte* modrmp,
375 RegisterNameMapping register_name); 375 RegisterNameMapping register_name);
376 int PrintRightOperand(byte* modrmp); 376 int PrintRightOperand(byte* modrmp);
377 int PrintRightByteOperand(byte* modrmp); 377 int PrintRightByteOperand(byte* modrmp);
378 int PrintOperands(const char* mnem, 378 int PrintOperands(const char* mnem,
379 OperandType op_order, 379 OperandType op_order,
380 byte* data); 380 byte* data);
381 int PrintImmediate(byte* data, OperandSize size); 381 int PrintImmediate(byte* data, OperandSize size);
382 int PrintImmediateOp(byte* data); 382 int PrintImmediateOp(byte* data);
383 const char* TwoByteMnemonic(byte opcode);
384 int TwoByteOpcodeInstruction(byte* data);
383 int F7Instruction(byte* data); 385 int F7Instruction(byte* data);
384 int ShiftInstruction(byte* data); 386 int ShiftInstruction(byte* data);
385 int JumpShort(byte* data); 387 int JumpShort(byte* data);
386 int JumpConditional(byte* data); 388 int JumpConditional(byte* data);
387 int JumpConditionalShort(byte* data); 389 int JumpConditionalShort(byte* data);
388 int SetCC(byte* data); 390 int SetCC(byte* data);
389 int FPUInstruction(byte* data); 391 int FPUInstruction(byte* data);
390 void AppendToBuffer(const char* format, ...); 392 void AppendToBuffer(const char* format, ...);
391 393
392 void UnimplementedInstruction() { 394 void UnimplementedInstruction() {
393 if (abort_on_unimplemented_) { 395 if (abort_on_unimplemented_) {
394 UNIMPLEMENTED(); 396 CHECK(false);
395 } else { 397 } else {
396 AppendToBuffer("'Unimplemented Instruction'"); 398 AppendToBuffer("'Unimplemented Instruction'");
397 } 399 }
398 } 400 }
399 }; 401 };
400 402
401 403
402 void DisassemblerX64::AppendToBuffer(const char* format, ...) { 404 void DisassemblerX64::AppendToBuffer(const char* format, ...) {
403 v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_; 405 v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_;
404 va_list args; 406 va_list args;
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after
929 return 2; 931 return 2;
930 } else if (b1 == 0xDA && b2 == 0xE9) { 932 } else if (b1 == 0xDA && b2 == 0xE9) {
931 const char* mnem = "fucompp"; 933 const char* mnem = "fucompp";
932 AppendToBuffer("%s", mnem); 934 AppendToBuffer("%s", mnem);
933 return 2; 935 return 2;
934 } 936 }
935 AppendToBuffer("Unknown FP instruction"); 937 AppendToBuffer("Unknown FP instruction");
936 return 2; 938 return 2;
937 } 939 }
938 940
939 // Mnemonics for instructions 0xF0 byte. 941
942 // Handle all two-byte opcodes, which start with 0x0F.
943 // These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix.
944 // We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A.
945 int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
946 byte opcode = *(data + 1);
947 byte* current = data + 2;
948 // At return, "current" points to the start of the next instruction.
949 const char* mnemonic = TwoByteMnemonic(opcode);
950 if (opcode == 0x1F) {
951 // NOP
952 int mod, regop, rm;
953 get_modrm(*current, &mod, &regop, &rm);
954 current++;
955 if (regop == 4) { // SIB byte present.
956 current++;
957 }
958 if (mod == 1) { // Byte displacement.
959 current += 1;
960 } else if (mod == 2) { // 32-bit displacement.
961 current += 4;
962 } // else no immediate displacement.
963 AppendToBuffer("nop");
964
965 } else if (opcode == 0xA2 || opcode == 0x31) {
966 // RDTSC or CPUID
967 AppendToBuffer("%s", mnemonic);
968
969 } else if ((opcode & 0xF0) == 0x80) {
970 // Jcc: Conditional jump (branch).
971 current = data + JumpConditional(data);
972
973 } else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 ||
974 opcode == 0xB7 || opcode == 0xAF) {
975 // Size-extending moves, IMUL.
976 current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
977
978 } else if ((opcode & 0xF0) == 0x90) {
979 // SETcc: Set byte on condition. Needs pointer to beginning of instruction.
980 current = data + SetCC(data);
981
982 } else if (opcode == 0xAB || opcode == 0xA5 || opcode == 0xAD) {
983 // SHLD, SHRD (double-precision shift), BTS (bit set).
984 AppendToBuffer("%s ", mnemonic);
985 int mod, regop, rm;
986 get_modrm(*current, &mod, &regop, &rm);
987 current += PrintRightOperand(current);
988 if (opcode == 0xAB) {
989 AppendToBuffer(",%s", NameOfCPURegister(regop));
990 } else {
991 AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
992 }
993 } else if (group_1_prefix_ == 0xF2) {
994 // Beginning of instructions with prefix 0xF2.
995
996 if (opcode == 0x11 || opcode == 0x10) {
997 // MOVSD: Move scalar double-precision fp to/from/between XMM registers.
998 AppendToBuffer("movsd ");
999 int mod, regop, rm;
1000 get_modrm(*current, &mod, &regop, &rm);
1001 if (opcode == 0x11) {
1002 current += PrintRightOperand(current);
1003 AppendToBuffer(",%s", NameOfXMMRegister(regop));
1004 } else {
1005 AppendToBuffer("%s,", NameOfXMMRegister(regop));
1006 current += PrintRightOperand(current);
1007 }
1008 } else if (opcode == 0x2A) {
1009 // CVTSI2SD: integer to XMM double conversion.
1010 int mod, regop, rm;
1011 get_modrm(*current, &mod, &regop, &rm);
1012 AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
1013 data += PrintRightOperand(data);
1014 } else if ((opcode & 0xF8) == 0x58) {
1015 // XMM arithmetic. Mnemonic was retrieved at the start of this function.
1016 int mod, regop, rm;
1017 get_modrm(*current, &mod, &regop, &rm);
1018 AppendToBuffer("%s %s,%s", mnemonic, NameOfXMMRegister(regop),
1019 NameOfXMMRegister(rm));
1020 } else {
1021 UnimplementedInstruction();
1022 }
1023 } else if (opcode == 0x2C && group_1_prefix_ == 0xF3) {
1024 // Instruction with prefix 0xF3.
1025
1026 // CVTTSS2SI: Convert scalar single-precision FP to dword integer.
1027 // Assert that mod is not 3, so source is memory, not an XMM register.
1028 ASSERT((*current & 0xC0) != 0xC0);
1029 current += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, current);
1030 } else {
1031 UnimplementedInstruction();
1032 }
1033 return current - data;
1034 }
1035
1036
1037 // Mnemonics for two-byte opcode instructions starting with 0x0F.
1038 // The argument is the second byte of the two-byte opcode.
940 // Returns NULL if the instruction is not handled here. 1039 // Returns NULL if the instruction is not handled here.
941 static const char* F0Mnem(byte f0byte) { 1040 const char* DisassemblerX64::TwoByteMnemonic(byte opcode) {
942 switch (f0byte) { 1041 switch (opcode) {
943 case 0x1F: 1042 case 0x1F:
944 return "nop"; 1043 return "nop";
1044 case 0x2A: // F2 prefix.
1045 return "cvtsi2sd";
945 case 0x31: 1046 case 0x31:
946 return "rdtsc"; 1047 return "rdtsc";
1048 case 0x58: // F2 prefix.
1049 return "addsd";
1050 case 0x59: // F2 prefix.
1051 return "mulsd";
1052 case 0x5C: // F2 prefix.
1053 return "subsd";
1054 case 0x5E: // F2 prefix.
1055 return "divsd";
947 case 0xA2: 1056 case 0xA2:
948 return "cpuid"; 1057 return "cpuid";
1058 case 0xA5:
1059 return "shld";
1060 case 0xAB:
1061 return "bts";
1062 case 0xAD:
1063 return "shrd";
1064 case 0xAF:
1065 return "imul";
1066 case 0xB6:
1067 return "movzxb";
1068 case 0xB7:
1069 return "movzxw";
949 case 0xBE: 1070 case 0xBE:
950 return "movsxb"; 1071 return "movsxb";
951 case 0xBF: 1072 case 0xBF:
952 return "movsxw"; 1073 return "movsxw";
953 case 0xB6:
954 return "movzxb";
955 case 0xB7:
956 return "movzxw";
957 case 0xAF:
958 return "imul";
959 case 0xA5:
960 return "shld";
961 case 0xAD:
962 return "shrd";
963 case 0xAB:
964 return "bts";
965 default: 1074 default:
966 return NULL; 1075 return NULL;
967 } 1076 }
968 } 1077 }
969 1078
970 // Disassembled instruction '*instr' and writes it into 'out_buffer'. 1079
1080 // Disassembles the instruction at instr, and writes it into out_buffer.
971 int DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer, 1081 int DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer,
972 byte* instr) { 1082 byte* instr) {
973 tmp_buffer_pos_ = 0; // starting to write as position 0 1083 tmp_buffer_pos_ = 0; // starting to write as position 0
974 byte* data = instr; 1084 byte* data = instr;
975 bool processed = true; // Will be set to false if the current instruction 1085 bool processed = true; // Will be set to false if the current instruction
976 // is not in 'instructions' table. 1086 // is not in 'instructions' table.
977 byte current; 1087 byte current;
978 1088
979 // Scan for prefixes. 1089 // Scan for prefixes.
980 while (true) { 1090 while (true) {
981 current = *data; 1091 current = *data;
982 if (current == 0x66) { 1092 if (current == 0x66) { // Group 3 prefix.
983 // If the sequence is 66 0f, it's not a prefix, but a SSE escape. 1093 operand_size_ = current;
984 if (*(data + 1) == 0x0F) break; 1094 } else if ((current & 0xF0) == 0x40) { // REX prefix.
985 data++;
986 } else if ((current & 0xF0) == 0x40) {
987 setRex(current); 1095 setRex(current);
988 if (rex_w()) AppendToBuffer("REX.W "); 1096 if (rex_w()) AppendToBuffer("REX.W ");
989 data++; 1097 } else if ((current & 0xFE) == 0xF2) { // Group 1 prefix.
990 } else { 1098 group_1_prefix_ = current;
1099 } else { // Not a prefix - an opcode.
991 break; 1100 break;
992 } 1101 }
1102 data++;
993 } 1103 }
994 1104
995 const InstructionDesc& idesc = instruction_table.Get(current); 1105 const InstructionDesc& idesc = instruction_table.Get(current);
996 byte_size_operand_ = idesc.byte_size_operation; 1106 byte_size_operand_ = idesc.byte_size_operation;
997 switch (idesc.type) { 1107 switch (idesc.type) {
998 case ZERO_OPERANDS_INSTR: 1108 case ZERO_OPERANDS_INSTR:
999 AppendToBuffer(idesc.mnem); 1109 AppendToBuffer(idesc.mnem);
1000 data++; 1110 data++;
1001 break; 1111 break;
1002 1112
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1101 } 1211 }
1102 data += 3; 1212 data += 3;
1103 break; 1213 break;
1104 } 1214 }
1105 1215
1106 case 0x81: // fall through 1216 case 0x81: // fall through
1107 case 0x83: // 0x81 with sign extension bit set 1217 case 0x83: // 0x81 with sign extension bit set
1108 data += PrintImmediateOp(data); 1218 data += PrintImmediateOp(data);
1109 break; 1219 break;
1110 1220
1111 case 0x0F: { 1221 case 0x0F:
1112 byte f0byte = *(data + 1); 1222 data += TwoByteOpcodeInstruction(data);
1113 const char* f0mnem = F0Mnem(f0byte);
1114 if (f0byte == 0x1F) {
1115 data += 1;
1116 byte modrm = *data;
1117 data += 1;
1118 if (((modrm >> 3) & 7) == 4) {
1119 // SIB byte present.
1120 data += 1;
1121 }
1122 int mod = modrm >> 6;
1123 if (mod == 1) {
1124 // Byte displacement.
1125 data += 1;
1126 } else if (mod == 2) {
1127 // 32-bit displacement.
1128 data += 4;
1129 }
1130 AppendToBuffer("nop");
1131 } else if (f0byte == 0xA2 || f0byte == 0x31) {
1132 AppendToBuffer("%s", f0mnem);
1133 data += 2;
1134 } else if ((f0byte & 0xF0) == 0x80) {
1135 data += JumpConditional(data);
1136 } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 || f0byte
1137 == 0xB7 || f0byte == 0xAF) {
1138 data += 2;
1139 data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data);
1140 } else if ((f0byte & 0xF0) == 0x90) {
1141 data += SetCC(data);
1142 } else {
1143 data += 2;
1144 if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) {
1145 // shrd, shld, bts
1146 AppendToBuffer("%s ", f0mnem);
1147 int mod, regop, rm;
1148 get_modrm(*data, &mod, &regop, &rm);
1149 data += PrintRightOperand(data);
1150 if (f0byte == 0xAB) {
1151 AppendToBuffer(",%s", NameOfCPURegister(regop));
1152 } else {
1153 AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
1154 }
1155 } else {
1156 UnimplementedInstruction();
1157 }
1158 }
1159 }
1160 break; 1223 break;
1161 1224
1162 case 0x8F: { 1225 case 0x8F: {
1163 data++; 1226 data++;
1164 int mod, regop, rm; 1227 int mod, regop, rm;
1165 get_modrm(*data, &mod, &regop, &rm); 1228 get_modrm(*data, &mod, &regop, &rm);
1166 if (regop == 0) { 1229 if (regop == 0) {
1167 AppendToBuffer("pop "); 1230 AppendToBuffer("pop ");
1168 data += PrintRightOperand(data); 1231 data += PrintRightOperand(data);
1169 } 1232 }
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 value = *reinterpret_cast<uint32_t*>(data + 1); 1359 value = *reinterpret_cast<uint32_t*>(data + 1);
1297 data += 5; 1360 data += 5;
1298 break; 1361 break;
1299 case QUADWORD_SIZE: 1362 case QUADWORD_SIZE:
1300 value = *reinterpret_cast<int32_t*>(data + 1); 1363 value = *reinterpret_cast<int32_t*>(data + 1);
1301 data += 5; 1364 data += 5;
1302 break; 1365 break;
1303 default: 1366 default:
1304 UNREACHABLE(); 1367 UNREACHABLE();
1305 } 1368 }
1306 break;
1307 AppendToBuffer("test%c rax,0x%"V8_PTR_PREFIX"ux", 1369 AppendToBuffer("test%c rax,0x%"V8_PTR_PREFIX"ux",
1308 operand_size_code(), 1370 operand_size_code(),
1309 value); 1371 value);
1372 break;
1310 } 1373 }
1311 case 0xD1: // fall through 1374 case 0xD1: // fall through
1312 case 0xD3: // fall through 1375 case 0xD3: // fall through
1313 case 0xC1: 1376 case 0xC1:
1314 data += ShiftInstruction(data); 1377 data += ShiftInstruction(data);
1315 break; 1378 break;
1316 case 0xD0: // fall through 1379 case 0xD0: // fall through
1317 case 0xD2: // fall through 1380 case 0xD2: // fall through
1318 case 0xC0: 1381 case 0xC0:
1319 byte_size_operand_ = true; 1382 byte_size_operand_ = true;
1320 data += ShiftInstruction(data); 1383 data += ShiftInstruction(data);
1321 break; 1384 break;
1322 1385
1323 case 0xD9: // fall through 1386 case 0xD9: // fall through
1324 case 0xDA: // fall through 1387 case 0xDA: // fall through
1325 case 0xDB: // fall through 1388 case 0xDB: // fall through
1326 case 0xDC: // fall through 1389 case 0xDC: // fall through
1327 case 0xDD: // fall through 1390 case 0xDD: // fall through
1328 case 0xDE: // fall through 1391 case 0xDE: // fall through
1329 case 0xDF: 1392 case 0xDF:
1330 data += FPUInstruction(data); 1393 data += FPUInstruction(data);
1331 break; 1394 break;
1332 1395
1333 case 0xEB: 1396 case 0xEB:
1334 data += JumpShort(data); 1397 data += JumpShort(data);
1335 break; 1398 break;
1336 1399
1337 case 0xF2:
1338 if (*(data + 1) == 0x0F) {
1339 byte b2 = *(data + 2);
1340 if (b2 == 0x11) {
1341 AppendToBuffer("movsd ");
1342 data += 3;
1343 int mod, regop, rm;
1344 get_modrm(*data, &mod, &regop, &rm);
1345 data += PrintRightOperand(data);
1346 AppendToBuffer(",%s", NameOfXMMRegister(regop));
1347 } else if (b2 == 0x10) {
1348 data += 3;
1349 int mod, regop, rm;
1350 get_modrm(*data, &mod, &regop, &rm);
1351 AppendToBuffer("movsd %s,", NameOfXMMRegister(regop));
1352 data += PrintRightOperand(data);
1353 } else {
1354 const char* mnem = "?";
1355 switch (b2) {
1356 case 0x2A:
1357 mnem = "cvtsi2sd";
1358 break;
1359 case 0x58:
1360 mnem = "addsd";
1361 break;
1362 case 0x59:
1363 mnem = "mulsd";
1364 break;
1365 case 0x5C:
1366 mnem = "subsd";
1367 break;
1368 case 0x5E:
1369 mnem = "divsd";
1370 break;
1371 }
1372 data += 3;
1373 int mod, regop, rm;
1374 get_modrm(*data, &mod, &regop, &rm);
1375 if (b2 == 0x2A) {
1376 AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
1377 data += PrintRightOperand(data);
1378 } else {
1379 AppendToBuffer("%s %s,%s", mnem, NameOfXMMRegister(regop),
1380 NameOfXMMRegister(rm));
1381 data++;
1382 }
1383 }
1384 } else {
1385 UnimplementedInstruction();
1386 }
1387 break;
1388
1389 case 0xF3:
1390 if (*(data + 1) == 0x0F) {
1391 if (*(data + 2) == 0x2C) {
1392 data += 3;
1393 data += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, data);
1394 } else {
1395 UnimplementedInstruction();
1396 data += 1;
1397 }
1398 } else {
1399 UnimplementedInstruction();
1400 data += 1;
1401 }
1402 break;
1403
1404 case 0xF7: 1400 case 0xF7:
1405 data += F7Instruction(data); 1401 data += F7Instruction(data);
1406 break; 1402 break;
1407 1403
1408 default: 1404 default:
1409 UnimplementedInstruction(); 1405 UnimplementedInstruction();
1410 data += 1; 1406 data += 1;
1411 } 1407 }
1412 } // !processed 1408 } // !processed
1413 1409
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1528 fprintf(f, "%02x", *bp); 1524 fprintf(f, "%02x", *bp);
1529 } 1525 }
1530 for (int i = 6 - (pc - prev_pc); i >= 0; i--) { 1526 for (int i = 6 - (pc - prev_pc); i >= 0; i--) {
1531 fprintf(f, " "); 1527 fprintf(f, " ");
1532 } 1528 }
1533 fprintf(f, " %s\n", buffer.start()); 1529 fprintf(f, " %s\n", buffer.start());
1534 } 1530 }
1535 } 1531 }
1536 1532
1537 } // namespace disasm 1533 } // namespace disasm
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698