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

Unified Diff: src/x64/disasm-x64.cc

Issue 757503002: [x64] Introduce FMA3 instructions on scalar data elements. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: remove avx_os_support Created 6 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | test/cctest/test-assembler-x64.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/x64/disasm-x64.cc
diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc
index 837da27941d33666b527f29a77632b7ee7dc84cc..bb8f5430ccb0d3e03ad565f9e38290ae81f26b6c 100644
--- a/src/x64/disasm-x64.cc
+++ b/src/x64/disasm-x64.cc
@@ -148,6 +148,8 @@ enum Prefixes {
ESCAPE_PREFIX = 0x0F,
OPERAND_SIZE_OVERRIDE_PREFIX = 0x66,
ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67,
+ VEX3_PREFIX = 0xC4,
+ VEX2_PREFIX = 0xC5,
REPNE_PREFIX = 0xF2,
REP_PREFIX = 0xF3,
REPEQ_PREFIX = REP_PREFIX
@@ -290,11 +292,14 @@ class DisassemblerX64 {
ABORT_ON_UNIMPLEMENTED_OPCODE)
: converter_(converter),
tmp_buffer_pos_(0),
- abort_on_unimplemented_(
- unimplemented_action == ABORT_ON_UNIMPLEMENTED_OPCODE),
+ abort_on_unimplemented_(unimplemented_action ==
+ ABORT_ON_UNIMPLEMENTED_OPCODE),
rex_(0),
operand_size_(0),
group_1_prefix_(0),
+ vex_byte0_(0),
+ vex_byte1_(0),
+ vex_byte2_(0),
byte_size_operand_(false),
instruction_table_(instruction_table.Pointer()) {
tmp_buffer_[0] = '\0';
@@ -323,6 +328,9 @@ class DisassemblerX64 {
byte rex_;
byte operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0.
byte group_1_prefix_; // 0xF2, 0xF3, or (if no group 1 prefix is present) 0.
+ byte vex_byte0_; // 0xc4 or 0xc5
+ byte vex_byte1_;
+ byte vex_byte2_; // only for 3 bytes vex prefix
// Byte size operand override.
bool byte_size_operand_;
const InstructionTable* const instruction_table_;
@@ -345,6 +353,51 @@ class DisassemblerX64 {
bool rex_w() { return (rex_ & 0x08) != 0; }
+ bool vex_128() {
+ DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
+ byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
+ return (checked & 4) != 1;
+ }
+
+ bool vex_66() {
+ DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
+ byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
+ return (checked & 3) == 1;
+ }
+
+ bool vex_f3() {
+ DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
+ byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
+ return (checked & 3) == 2;
+ }
+
+ bool vex_f2() {
+ DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
+ byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
+ return (checked & 3) == 3;
+ }
+
+ bool vex_0f() {
+ if (vex_byte0_ == VEX2_PREFIX) return true;
+ return (vex_byte1_ & 3) == 1;
+ }
+
+ bool vex_0f38() {
+ DCHECK(vex_byte0_ == VEX3_PREFIX);
+ return (vex_byte1_ & 3) == 2;
+ }
+
+ bool vex_0f3a() {
+ DCHECK(vex_byte0_ == VEX3_PREFIX);
+ return (vex_byte1_ & 3) == 3;
+ }
+
+ int vex_vreg() {
+ DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
+ byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
+ return ~(checked >> 3) & 0xf;
+ }
+
OperandSize operand_size() {
if (byte_size_operand_) return OPERAND_BYTE_SIZE;
if (rex_w()) return OPERAND_QUADWORD_SIZE;
@@ -356,6 +409,8 @@ class DisassemblerX64 {
return "bwlq"[operand_size()];
}
+ char float_size_code() { return "sd"[rex_w()]; }
+
const char* NameOfCPURegister(int reg) const {
return converter_.NameOfCPURegister(reg);
}
@@ -414,6 +469,7 @@ class DisassemblerX64 {
int FPUInstruction(byte* data);
int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
+ int AVXInstruction(byte* data);
void AppendToBuffer(const char* format, ...);
void UnimplementedInstruction() {
@@ -811,6 +867,92 @@ int DisassemblerX64::SetCC(byte* data) {
}
+int DisassemblerX64::AVXInstruction(byte* data) {
+ byte opcode = *data;
+ byte* current = data + 1;
+ if (vex_byte0_ == VEX3_PREFIX) {
+ if (vex_128()) {
+ if (vex_66() && vex_0f38()) {
+ int mod, regop, rm, vvvv = vex_vreg();
+ get_modrm(*current, &mod, &regop, &rm);
+ switch (opcode) {
+ case 0x99:
+ AppendToBuffer("vfmadd132s%c %s,%s,", float_size_code(),
+ NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ break;
+ case 0xa9:
+ AppendToBuffer("vfmadd213s%c %s,%s,", float_size_code(),
+ NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ break;
+ case 0xb9:
+ AppendToBuffer("vfmadd231s%c %s,%s,", float_size_code(),
+ NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ break;
+ case 0x9b:
+ AppendToBuffer("vfmsub132s%c %s,%s,", float_size_code(),
+ NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ break;
+ case 0xab:
+ AppendToBuffer("vfmsub213s%c %s,%s,", float_size_code(),
+ NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ break;
+ case 0xbb:
+ AppendToBuffer("vfmsub231s%c %s,%s,", float_size_code(),
+ NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ break;
+ case 0x9d:
+ AppendToBuffer("vfnmadd132s%c %s,%s,", float_size_code(),
+ NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ break;
+ case 0xad:
+ AppendToBuffer("vfnmadd213s%c %s,%s,", float_size_code(),
+ NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ break;
+ case 0xbd:
+ AppendToBuffer("vfnmadd231s%c %s,%s,", float_size_code(),
+ NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ break;
+ case 0x9f:
+ AppendToBuffer("vfnmsub132s%c %s,%s,", float_size_code(),
+ NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ break;
+ case 0xaf:
+ AppendToBuffer("vfnmsub213s%c %s,%s,", float_size_code(),
+ NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ break;
+ case 0xbf:
+ AppendToBuffer("vfnmsub231s%c %s,%s,", float_size_code(),
+ NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ break;
+ default:
+ UnimplementedInstruction();
+ }
+ }
+ } else {
+ UnimplementedInstruction();
+ }
+ } else if (vex_byte0_ == VEX2_PREFIX) {
+ UnimplementedInstruction();
+ } else {
+ UNREACHABLE();
+ }
+
+ return static_cast<int>(current - data);
+}
+
+
// Returns number of bytes used, including *data.
int DisassemblerX64::FPUInstruction(byte* data) {
byte escape_opcode = *data;
@@ -1189,6 +1331,16 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
AppendToBuffer("cvttss2si%c %s,",
operand_size_code(), NameOfCPURegister(regop));
current += PrintRightXMMOperand(current);
+ } else if (opcode == 0x58) {
+ int mod, regop, rm;
+ get_modrm(*current, &mod, &regop, &rm);
+ AppendToBuffer("addss %s,", NameOfXMMRegister(regop));
+ current += PrintRightXMMOperand(current);
+ } else if (opcode == 0x59) {
+ int mod, regop, rm;
+ get_modrm(*current, &mod, &regop, &rm);
+ AppendToBuffer("mulss %s,", NameOfXMMRegister(regop));
+ current += PrintRightXMMOperand(current);
} else if (opcode == 0x5A) {
// CVTSS2SD:
// Convert scalar single-precision FP to scalar double-precision FP.
@@ -1196,6 +1348,16 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
get_modrm(*current, &mod, &regop, &rm);
AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
current += PrintRightXMMOperand(current);
+ } else if (opcode == 0x5c) {
+ int mod, regop, rm;
+ get_modrm(*current, &mod, &regop, &rm);
+ AppendToBuffer("subss %s,", NameOfXMMRegister(regop));
+ current += PrintRightXMMOperand(current);
+ } else if (opcode == 0x5e) {
+ int mod, regop, rm;
+ get_modrm(*current, &mod, &regop, &rm);
+ AppendToBuffer("divss %s,", NameOfXMMRegister(regop));
+ current += PrintRightXMMOperand(current);
} else if (opcode == 0x7E) {
int mod, regop, rm;
get_modrm(*current, &mod, &regop, &rm);
@@ -1234,6 +1396,11 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
current += PrintRightXMMOperand(current);
AppendToBuffer(",%s", NameOfXMMRegister(regop));
+ } else if (opcode == 0x2e) {
+ int mod, regop, rm;
+ get_modrm(*current, &mod, &regop, &rm);
+ AppendToBuffer("ucomiss %s,", NameOfXMMRegister(regop));
+ current += PrintRightXMMOperand(current);
} else if (opcode == 0xA2) {
// CPUID
AppendToBuffer("%s", mnemonic);
@@ -1387,99 +1554,114 @@ int DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer,
if (rex_w()) AppendToBuffer("REX.W ");
} else if ((current & 0xFE) == 0xF2) { // Group 1 prefix (0xF2 or 0xF3).
group_1_prefix_ = current;
+ } else if (current == VEX3_PREFIX) {
+ vex_byte0_ = current;
+ vex_byte1_ = *(data + 1);
+ vex_byte2_ = *(data + 2);
+ setRex(0x40 | (~(vex_byte1_ >> 5) & 7) | ((vex_byte2_ >> 4) & 8));
+ data += 2;
+ } else if (current == VEX2_PREFIX) {
+ vex_byte0_ = current;
+ vex_byte1_ = *(data + 1);
+ setRex(0x40 | (~(vex_byte1_ >> 5) & 4));
+ data++;
} else { // Not a prefix - an opcode.
break;
}
data++;
}
- const InstructionDesc& idesc = instruction_table_->Get(current);
- byte_size_operand_ = idesc.byte_size_operation;
- switch (idesc.type) {
- case ZERO_OPERANDS_INSTR:
- if (current >= 0xA4 && current <= 0xA7) {
- // String move or compare operations.
- if (group_1_prefix_ == REP_PREFIX) {
- // REP.
- AppendToBuffer("rep ");
+ // Decode AVX instructions.
+ if (vex_byte0_ != 0) {
+ processed = true;
+ data += AVXInstruction(data);
+ } else {
+ const InstructionDesc& idesc = instruction_table_->Get(current);
+ byte_size_operand_ = idesc.byte_size_operation;
+ switch (idesc.type) {
+ case ZERO_OPERANDS_INSTR:
+ if (current >= 0xA4 && current <= 0xA7) {
+ // String move or compare operations.
+ if (group_1_prefix_ == REP_PREFIX) {
+ // REP.
+ AppendToBuffer("rep ");
+ }
+ if (rex_w()) AppendToBuffer("REX.W ");
+ AppendToBuffer("%s%c", idesc.mnem, operand_size_code());
+ } else {
+ AppendToBuffer("%s", idesc.mnem, operand_size_code());
}
- if (rex_w()) AppendToBuffer("REX.W ");
- AppendToBuffer("%s%c", idesc.mnem, operand_size_code());
- } else {
- AppendToBuffer("%s", idesc.mnem, operand_size_code());
- }
- data++;
- break;
+ data++;
+ break;
- case TWO_OPERANDS_INSTR:
- data++;
- data += PrintOperands(idesc.mnem, idesc.op_order_, data);
- break;
+ case TWO_OPERANDS_INSTR:
+ data++;
+ data += PrintOperands(idesc.mnem, idesc.op_order_, data);
+ break;
- case JUMP_CONDITIONAL_SHORT_INSTR:
- data += JumpConditionalShort(data);
- break;
+ case JUMP_CONDITIONAL_SHORT_INSTR:
+ data += JumpConditionalShort(data);
+ break;
- case REGISTER_INSTR:
- AppendToBuffer("%s%c %s",
- idesc.mnem,
- operand_size_code(),
- NameOfCPURegister(base_reg(current & 0x07)));
- data++;
- break;
- case PUSHPOP_INSTR:
- AppendToBuffer("%s %s",
- idesc.mnem,
- NameOfCPURegister(base_reg(current & 0x07)));
- data++;
- break;
- case MOVE_REG_INSTR: {
- byte* addr = NULL;
- switch (operand_size()) {
- case OPERAND_WORD_SIZE:
- addr = reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1));
- data += 3;
- break;
- case OPERAND_DOUBLEWORD_SIZE:
- addr =
- reinterpret_cast<byte*>(*reinterpret_cast<uint32_t*>(data + 1));
- data += 5;
- break;
- case OPERAND_QUADWORD_SIZE:
- addr = reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1));
- data += 9;
- break;
- default:
- UNREACHABLE();
+ case REGISTER_INSTR:
+ AppendToBuffer("%s%c %s", idesc.mnem, operand_size_code(),
+ NameOfCPURegister(base_reg(current & 0x07)));
+ data++;
+ break;
+ case PUSHPOP_INSTR:
+ AppendToBuffer("%s %s", idesc.mnem,
+ NameOfCPURegister(base_reg(current & 0x07)));
+ data++;
+ break;
+ case MOVE_REG_INSTR: {
+ byte* addr = NULL;
+ switch (operand_size()) {
+ case OPERAND_WORD_SIZE:
+ addr =
+ reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1));
+ data += 3;
+ break;
+ case OPERAND_DOUBLEWORD_SIZE:
+ addr =
+ reinterpret_cast<byte*>(*reinterpret_cast<uint32_t*>(data + 1));
+ data += 5;
+ break;
+ case OPERAND_QUADWORD_SIZE:
+ addr =
+ reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1));
+ data += 9;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ AppendToBuffer("mov%c %s,%s", operand_size_code(),
+ NameOfCPURegister(base_reg(current & 0x07)),
+ NameOfAddress(addr));
+ break;
}
- AppendToBuffer("mov%c %s,%s",
- operand_size_code(),
- NameOfCPURegister(base_reg(current & 0x07)),
- NameOfAddress(addr));
- break;
- }
- case CALL_JUMP_INSTR: {
- byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
- AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
- data += 5;
- break;
- }
+ case CALL_JUMP_INSTR: {
+ byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
+ AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
+ data += 5;
+ break;
+ }
- case SHORT_IMMEDIATE_INSTR: {
- byte* addr =
- reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
- AppendToBuffer("%s rax,%s", idesc.mnem, NameOfAddress(addr));
- data += 5;
- break;
- }
+ case SHORT_IMMEDIATE_INSTR: {
+ byte* addr =
+ reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
+ AppendToBuffer("%s rax,%s", idesc.mnem, NameOfAddress(addr));
+ data += 5;
+ break;
+ }
- case NO_INSTR:
- processed = false;
- break;
+ case NO_INSTR:
+ processed = false;
+ break;
- default:
- UNIMPLEMENTED(); // This type is not implemented.
+ default:
+ UNIMPLEMENTED(); // This type is not implemented.
+ }
}
// The first byte didn't match any of the simple opcodes, so we
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | test/cctest/test-assembler-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698