OLD | NEW |
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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 { 0x1D, UNSET_OP_ORDER, "sbb" }, | 132 { 0x1D, UNSET_OP_ORDER, "sbb" }, |
133 { 0x25, UNSET_OP_ORDER, "and" }, | 133 { 0x25, UNSET_OP_ORDER, "and" }, |
134 { 0x2D, UNSET_OP_ORDER, "sub" }, | 134 { 0x2D, UNSET_OP_ORDER, "sub" }, |
135 { 0x35, UNSET_OP_ORDER, "xor" }, | 135 { 0x35, UNSET_OP_ORDER, "xor" }, |
136 { 0x3D, UNSET_OP_ORDER, "cmp" }, | 136 { 0x3D, UNSET_OP_ORDER, "cmp" }, |
137 { -1, UNSET_OP_ORDER, "" } | 137 { -1, UNSET_OP_ORDER, "" } |
138 }; | 138 }; |
139 | 139 |
140 | 140 |
141 static const char* conditional_code_suffix[] = { | 141 static const char* conditional_code_suffix[] = { |
142 "o", "no", "c", "nc", "z", "nz", "a", "na", | 142 "o", "no", "c", "nc", "z", "nz", "na", "a", |
143 "s", "ns", "pe", "po", "l", "ge", "le", "g" | 143 "s", "ns", "pe", "po", "l", "ge", "le", "g" |
144 }; | 144 }; |
145 | 145 |
146 | 146 |
147 enum InstructionType { | 147 enum InstructionType { |
148 NO_INSTR, | 148 NO_INSTR, |
149 ZERO_OPERANDS_INSTR, | 149 ZERO_OPERANDS_INSTR, |
150 TWO_OPERANDS_INSTR, | 150 TWO_OPERANDS_INSTR, |
151 JUMP_CONDITIONAL_SHORT_INSTR, | 151 JUMP_CONDITIONAL_SHORT_INSTR, |
152 REGISTER_INSTR, | 152 REGISTER_INSTR, |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 InstructionDesc* id = &instructions_[b]; | 245 InstructionDesc* id = &instructions_[b]; |
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 static InstructionDesc cmov_instructions[16] = { |
| 256 {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 257 {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 258 {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 259 {"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 260 {"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 261 {"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 262 {"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 263 {"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 264 {"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 265 {"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 266 {"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 267 {"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 268 {"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 269 {"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 270 {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 271 {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false} |
| 272 }; |
255 | 273 |
256 //------------------------------------------------------------------------------ | 274 //------------------------------------------------------------------------------ |
257 // DisassemblerX64 implementation. | 275 // DisassemblerX64 implementation. |
258 | 276 |
259 enum UnimplementedOpcodeAction { | 277 enum UnimplementedOpcodeAction { |
260 CONTINUE_ON_UNIMPLEMENTED_OPCODE, | 278 CONTINUE_ON_UNIMPLEMENTED_OPCODE, |
261 ABORT_ON_UNIMPLEMENTED_OPCODE | 279 ABORT_ON_UNIMPLEMENTED_OPCODE |
262 }; | 280 }; |
263 | 281 |
264 // A new DisassemblerX64 object is created to disassemble each instruction. | 282 // A new DisassemblerX64 object is created to disassemble each instruction. |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 break; | 544 break; |
527 case QUADWORD_SIZE: | 545 case QUADWORD_SIZE: |
528 value = *reinterpret_cast<int32_t*>(data); | 546 value = *reinterpret_cast<int32_t*>(data); |
529 count = 4; | 547 count = 4; |
530 break; | 548 break; |
531 default: | 549 default: |
532 UNREACHABLE(); | 550 UNREACHABLE(); |
533 value = 0; // Initialize variables on all paths to satisfy the compiler. | 551 value = 0; // Initialize variables on all paths to satisfy the compiler. |
534 count = 0; | 552 count = 0; |
535 } | 553 } |
536 AppendToBuffer(V8_PTR_PREFIX"x", value); | 554 AppendToBuffer("%" V8_PTR_PREFIX "x", value); |
537 return count; | 555 return count; |
538 } | 556 } |
539 | 557 |
540 | 558 |
541 int DisassemblerX64::PrintRightOperand(byte* modrmp) { | 559 int DisassemblerX64::PrintRightOperand(byte* modrmp) { |
542 return PrintRightOperandHelper(modrmp, | 560 return PrintRightOperandHelper(modrmp, |
543 &DisassemblerX64::NameOfCPURegister); | 561 &DisassemblerX64::NameOfCPURegister); |
544 } | 562 } |
545 | 563 |
546 | 564 |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 current += 1; | 977 current += 1; |
960 } else if (mod == 2) { // 32-bit displacement. | 978 } else if (mod == 2) { // 32-bit displacement. |
961 current += 4; | 979 current += 4; |
962 } // else no immediate displacement. | 980 } // else no immediate displacement. |
963 AppendToBuffer("nop"); | 981 AppendToBuffer("nop"); |
964 | 982 |
965 } else if (opcode == 0xA2 || opcode == 0x31) { | 983 } else if (opcode == 0xA2 || opcode == 0x31) { |
966 // RDTSC or CPUID | 984 // RDTSC or CPUID |
967 AppendToBuffer("%s", mnemonic); | 985 AppendToBuffer("%s", mnemonic); |
968 | 986 |
| 987 } else if ((opcode & 0xF0) == 0x40) { |
| 988 // CMOVcc: conditional move. |
| 989 int condition = opcode & 0x0F; |
| 990 const InstructionDesc& idesc = cmov_instructions[condition]; |
| 991 byte_size_operand_ = idesc.byte_size_operation; |
| 992 current += PrintOperands(idesc.mnem, idesc.op_order_, current); |
| 993 |
969 } else if ((opcode & 0xF0) == 0x80) { | 994 } else if ((opcode & 0xF0) == 0x80) { |
970 // Jcc: Conditional jump (branch). | 995 // Jcc: Conditional jump (branch). |
971 current = data + JumpConditional(data); | 996 current = data + JumpConditional(data); |
972 | 997 |
973 } else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 || | 998 } else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 || |
974 opcode == 0xB7 || opcode == 0xAF) { | 999 opcode == 0xB7 || opcode == 0xAF) { |
975 // Size-extending moves, IMUL. | 1000 // Size-extending moves, IMUL. |
976 current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current); | 1001 current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current); |
977 | 1002 |
978 } else if ((opcode & 0xF0) == 0x90) { | 1003 } else if ((opcode & 0xF0) == 0x90) { |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1343 data += 2; | 1368 data += 2; |
1344 break; | 1369 break; |
1345 | 1370 |
1346 case 0xA1: // Fall through. | 1371 case 0xA1: // Fall through. |
1347 case 0xA3: | 1372 case 0xA3: |
1348 switch (operand_size()) { | 1373 switch (operand_size()) { |
1349 case DOUBLEWORD_SIZE: { | 1374 case DOUBLEWORD_SIZE: { |
1350 const char* memory_location = NameOfAddress( | 1375 const char* memory_location = NameOfAddress( |
1351 reinterpret_cast<byte*>( | 1376 reinterpret_cast<byte*>( |
1352 *reinterpret_cast<int32_t*>(data + 1))); | 1377 *reinterpret_cast<int32_t*>(data + 1))); |
1353 if (*data == 0xA3) { // Opcode 0xA3 | 1378 if (*data == 0xA1) { // Opcode 0xA1 |
1354 AppendToBuffer("movzxlq rax,(%s)", memory_location); | 1379 AppendToBuffer("movzxlq rax,(%s)", memory_location); |
1355 } else { // Opcode 0xA1 | 1380 } else { // Opcode 0xA3 |
1356 AppendToBuffer("movzxlq (%s),rax", memory_location); | 1381 AppendToBuffer("movzxlq (%s),rax", memory_location); |
1357 } | 1382 } |
1358 data += 5; | 1383 data += 5; |
1359 break; | 1384 break; |
1360 } | 1385 } |
1361 case QUADWORD_SIZE: { | 1386 case QUADWORD_SIZE: { |
1362 // New x64 instruction mov rax,(imm_64). | 1387 // New x64 instruction mov rax,(imm_64). |
1363 const char* memory_location = NameOfAddress( | 1388 const char* memory_location = NameOfAddress( |
1364 *reinterpret_cast<byte**>(data + 1)); | 1389 *reinterpret_cast<byte**>(data + 1)); |
1365 if (*data == 0xA3) { // Opcode 0xA3 | 1390 if (*data == 0xA1) { // Opcode 0xA1 |
1366 AppendToBuffer("movq rax,(%s)", memory_location); | 1391 AppendToBuffer("movq rax,(%s)", memory_location); |
1367 } else { // Opcode 0xA1 | 1392 } else { // Opcode 0xA3 |
1368 AppendToBuffer("movq (%s),rax", memory_location); | 1393 AppendToBuffer("movq (%s),rax", memory_location); |
1369 } | 1394 } |
1370 data += 9; | 1395 data += 9; |
1371 break; | 1396 break; |
1372 } | 1397 } |
1373 default: | 1398 default: |
1374 UnimplementedInstruction(); | 1399 UnimplementedInstruction(); |
1375 data += 2; | 1400 data += 2; |
1376 } | 1401 } |
1377 break; | 1402 break; |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1557 fprintf(f, "%02x", *bp); | 1582 fprintf(f, "%02x", *bp); |
1558 } | 1583 } |
1559 for (int i = 6 - (pc - prev_pc); i >= 0; i--) { | 1584 for (int i = 6 - (pc - prev_pc); i >= 0; i--) { |
1560 fprintf(f, " "); | 1585 fprintf(f, " "); |
1561 } | 1586 } |
1562 fprintf(f, " %s\n", buffer.start()); | 1587 fprintf(f, " %s\n", buffer.start()); |
1563 } | 1588 } |
1564 } | 1589 } |
1565 | 1590 |
1566 } // namespace disasm | 1591 } // namespace disasm |
OLD | NEW |