From: dcarney@chromium.org Date: Thu, 2 Oct 2014 09:08:09 +0000 (+0000) Subject: [turbofan] support all shift operands on x64 X-Git-Tag: upstream/4.7.83~6560 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=944858e7d575e42b871d81f10964fe5d303265c5;p=platform%2Fupstream%2Fv8.git [turbofan] support all shift operands on x64 R=bmeurer@chromium.org BUG= Review URL: https://codereview.chromium.org/615223005 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24388 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/compiler/x64/code-generator-x64.cc b/src/compiler/x64/code-generator-x64.cc index 37aca10..6f9d68f 100644 --- a/src/compiler/x64/code-generator-x64.cc +++ b/src/compiler/x64/code-generator-x64.cc @@ -184,13 +184,21 @@ static bool HasImmediateInput(Instruction* instr, int index) { } while (0) -#define ASSEMBLE_SHIFT(asm_instr, width) \ - do { \ - if (HasImmediateInput(instr, 1)) { \ - __ asm_instr(i.OutputRegister(), Immediate(i.InputInt##width(1))); \ - } else { \ - __ asm_instr##_cl(i.OutputRegister()); \ - } \ +#define ASSEMBLE_SHIFT(asm_instr, width) \ + do { \ + if (HasImmediateInput(instr, 1)) { \ + if (instr->Output()->IsRegister()) { \ + __ asm_instr(i.OutputRegister(), Immediate(i.InputInt##width(1))); \ + } else { \ + __ asm_instr(i.OutputOperand(), Immediate(i.InputInt##width(1))); \ + } \ + } else { \ + if (instr->Output()->IsRegister()) { \ + __ asm_instr##_cl(i.OutputRegister()); \ + } else { \ + __ asm_instr##_cl(i.OutputOperand()); \ + } \ + } \ } while (0) diff --git a/src/compiler/x64/instruction-selector-x64.cc b/src/compiler/x64/instruction-selector-x64.cc index 8f52606..f744a2c 100644 --- a/src/compiler/x64/instruction-selector-x64.cc +++ b/src/compiler/x64/instruction-selector-x64.cc @@ -21,8 +21,6 @@ class X64OperandGenerator FINAL : public OperandGenerator { Register::ToAllocationIndex(reg)); } - InstructionOperand* UseImmediate64(Node* node) { return UseImmediate(node); } - bool CanBeImmediate(Node* node) { switch (node->opcode()) { case IrOpcode::kInt32Constant: @@ -32,23 +30,6 @@ class X64OperandGenerator FINAL : public OperandGenerator { } } - bool CanBeImmediate64(Node* node) { - switch (node->opcode()) { - case IrOpcode::kInt32Constant: - return true; - case IrOpcode::kNumberConstant: - return true; - case IrOpcode::kHeapConstant: { - // Constants in new space cannot be used as immediates in V8 because - // the GC does not scan code objects when collecting the new generation. - Unique value = OpParameter >(node); - return !isolate()->heap()->InNewSpace(*value.handle()); - } - default: - return false; - } - } - bool CanBeBetterLeftOperand(Node* node) const { return !selector()->IsLive(node); } @@ -350,9 +331,8 @@ static void VisitWord32Shift(InstructionSelector* selector, Node* node, Node* left = node->InputAt(0); Node* right = node->InputAt(1); - // TODO(turbofan): assembler only supports some addressing modes for shifts. if (g.CanBeImmediate(right)) { - selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), + selector->Emit(opcode, g.DefineSameAsFirst(node), g.Use(left), g.UseImmediate(right)); } else { Int32BinopMatcher m(node); @@ -362,7 +342,7 @@ static void VisitWord32Shift(InstructionSelector* selector, Node* node, right = mright.left().node(); } } - selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), + selector->Emit(opcode, g.DefineSameAsFirst(node), g.Use(left), g.UseFixed(right, rcx)); } } @@ -376,9 +356,8 @@ static void VisitWord64Shift(InstructionSelector* selector, Node* node, Node* left = node->InputAt(0); Node* right = node->InputAt(1); - // TODO(turbofan): assembler only supports some addressing modes for shifts. if (g.CanBeImmediate(right)) { - selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), + selector->Emit(opcode, g.DefineSameAsFirst(node), g.Use(left), g.UseImmediate(right)); } else { Int64BinopMatcher m(node); @@ -388,7 +367,7 @@ static void VisitWord64Shift(InstructionSelector* selector, Node* node, right = mright.left().node(); } } - selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), + selector->Emit(opcode, g.DefineSameAsFirst(node), g.Use(left), g.UseFixed(right, rcx)); } } diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc index a9fb834..8cc5395 100644 --- a/src/x64/assembler-x64.cc +++ b/src/x64/assembler-x64.cc @@ -617,6 +617,24 @@ void Assembler::shift(Register dst, } +void Assembler::shift(Operand dst, Immediate shift_amount, int subcode, + int size) { + EnsureSpace ensure_space(this); + DCHECK(size == kInt64Size ? is_uint6(shift_amount.value_) + : is_uint5(shift_amount.value_)); + if (shift_amount.value_ == 1) { + emit_rex(dst, size); + emit(0xD1); + emit_operand(subcode, dst); + } else { + emit_rex(dst, size); + emit(0xC1); + emit_operand(subcode, dst); + emit(shift_amount.value_); + } +} + + void Assembler::shift(Register dst, int subcode, int size) { EnsureSpace ensure_space(this); emit_rex(dst, size); @@ -625,6 +643,14 @@ void Assembler::shift(Register dst, int subcode, int size) { } +void Assembler::shift(Operand dst, int subcode, int size) { + EnsureSpace ensure_space(this); + emit_rex(dst, size); + emit(0xD3); + emit_operand(subcode, dst); +} + + void Assembler::bt(const Operand& dst, Register src) { EnsureSpace ensure_space(this); emit_rex_64(src, dst); diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h index 529b100..b461124 100644 --- a/src/x64/assembler-x64.h +++ b/src/x64/assembler-x64.h @@ -813,30 +813,42 @@ class Assembler : public AssemblerBase { // Multiply rax by src, put the result in rdx:rax. void mul(Register src); -#define DECLARE_SHIFT_INSTRUCTION(instruction, subcode) \ - void instruction##p(Register dst, Immediate imm8) { \ - shift(dst, imm8, subcode, kPointerSize); \ - } \ - \ - void instruction##l(Register dst, Immediate imm8) { \ - shift(dst, imm8, subcode, kInt32Size); \ - } \ - \ - void instruction##q(Register dst, Immediate imm8) { \ - shift(dst, imm8, subcode, kInt64Size); \ - } \ - \ - void instruction##p_cl(Register dst) { \ - shift(dst, subcode, kPointerSize); \ - } \ - \ - void instruction##l_cl(Register dst) { \ - shift(dst, subcode, kInt32Size); \ - } \ - \ - void instruction##q_cl(Register dst) { \ - shift(dst, subcode, kInt64Size); \ - } +#define DECLARE_SHIFT_INSTRUCTION(instruction, subcode) \ + void instruction##p(Register dst, Immediate imm8) { \ + shift(dst, imm8, subcode, kPointerSize); \ + } \ + \ + void instruction##l(Register dst, Immediate imm8) { \ + shift(dst, imm8, subcode, kInt32Size); \ + } \ + \ + void instruction##q(Register dst, Immediate imm8) { \ + shift(dst, imm8, subcode, kInt64Size); \ + } \ + \ + void instruction##p(Operand dst, Immediate imm8) { \ + shift(dst, imm8, subcode, kPointerSize); \ + } \ + \ + void instruction##l(Operand dst, Immediate imm8) { \ + shift(dst, imm8, subcode, kInt32Size); \ + } \ + \ + void instruction##q(Operand dst, Immediate imm8) { \ + shift(dst, imm8, subcode, kInt64Size); \ + } \ + \ + void instruction##p_cl(Register dst) { shift(dst, subcode, kPointerSize); } \ + \ + void instruction##l_cl(Register dst) { shift(dst, subcode, kInt32Size); } \ + \ + void instruction##q_cl(Register dst) { shift(dst, subcode, kInt64Size); } \ + \ + void instruction##p_cl(Operand dst) { shift(dst, subcode, kPointerSize); } \ + \ + void instruction##l_cl(Operand dst) { shift(dst, subcode, kInt32Size); } \ + \ + void instruction##q_cl(Operand dst) { shift(dst, subcode, kInt64Size); } SHIFT_INSTRUCTION_LIST(DECLARE_SHIFT_INSTRUCTION) #undef DECLARE_SHIFT_INSTRUCTION @@ -1365,9 +1377,11 @@ class Assembler : public AssemblerBase { int size); // Emit machine code for a shift operation. + void shift(Operand dst, Immediate shift_amount, int subcode, int size); void shift(Register dst, Immediate shift_amount, int subcode, int size); // Shift dst by cl % 64 bits. void shift(Register dst, int subcode, int size); + void shift(Operand dst, int subcode, int size); void emit_farith(int b1, int b2, int i); diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc index 2b8fc2d..9b55883 100644 --- a/src/x64/disasm-x64.cc +++ b/src/x64/disasm-x64.cc @@ -709,65 +709,62 @@ int DisassemblerX64::F6F7Instruction(byte* data) { int DisassemblerX64::ShiftInstruction(byte* data) { byte op = *data & (~1); + int count = 1; if (op != 0xD0 && op != 0xD2 && op != 0xC0) { UnimplementedInstruction(); - return 1; + return count; } - byte modrm = *(data + 1); - int mod, regop, rm; - get_modrm(modrm, &mod, ®op, &rm); - regop &= 0x7; // The REX.R bit does not affect the operation. - int imm8 = -1; - int num_bytes = 2; - if (mod != 3) { - UnimplementedInstruction(); - return num_bytes; - } - const char* mnem = NULL; - switch (regop) { - case 0: - mnem = "rol"; - break; - case 1: - mnem = "ror"; - break; - case 2: - mnem = "rcl"; - break; - case 3: - mnem = "rcr"; - break; - case 4: - mnem = "shl"; - break; - case 5: - mnem = "shr"; - break; - case 7: - mnem = "sar"; - break; - default: - UnimplementedInstruction(); - return num_bytes; - } - DCHECK_NE(NULL, mnem); - if (op == 0xD0) { - imm8 = 1; - } else if (op == 0xC0) { - imm8 = *(data + 2); - num_bytes = 3; + // Print mneumonic. + { + byte modrm = *(data + count); + int mod, regop, rm; + get_modrm(modrm, &mod, ®op, &rm); + regop &= 0x7; // The REX.R bit does not affect the operation. + const char* mnem = NULL; + switch (regop) { + case 0: + mnem = "rol"; + break; + case 1: + mnem = "ror"; + break; + case 2: + mnem = "rcl"; + break; + case 3: + mnem = "rcr"; + break; + case 4: + mnem = "shl"; + break; + case 5: + mnem = "shr"; + break; + case 7: + mnem = "sar"; + break; + default: + UnimplementedInstruction(); + return count + 1; + } + DCHECK_NE(NULL, mnem); + AppendToBuffer("%s%c ", mnem, operand_size_code()); } - AppendToBuffer("%s%c %s,", - mnem, - operand_size_code(), - byte_size_operand_ ? NameOfByteCPURegister(rm) - : NameOfCPURegister(rm)); + count += PrintRightOperand(data + count); if (op == 0xD2) { - AppendToBuffer("cl"); + AppendToBuffer(", cl"); } else { - AppendToBuffer("%d", imm8); + int imm8 = -1; + if (op == 0xD0) { + imm8 = 1; + } else { + DCHECK_EQ(0xC0, op); + imm8 = *(data + count); + count++; + } + AppendToBuffer(", %d", imm8); } - return num_bytes; + return count; } diff --git a/test/cctest/test-disasm-x64.cc b/test/cctest/test-disasm-x64.cc index 480c91f..3fd3ef1 100644 --- a/test/cctest/test-disasm-x64.cc +++ b/test/cctest/test-disasm-x64.cc @@ -117,6 +117,26 @@ TEST(DisasmX64) { __ imulq(rdx, rcx); __ shld(rdx, rcx); __ shrd(rdx, rcx); + __ shlq(Operand(rdi, rax, times_4, 100), Immediate(1)); + __ shlq(Operand(rdi, rax, times_4, 100), Immediate(6)); + __ shlq(Operand(r15, 0), Immediate(1)); + __ shlq(Operand(r15, 0), Immediate(6)); + __ shlq_cl(Operand(r15, 0)); + __ shlq_cl(Operand(r15, 0)); + __ shlq_cl(Operand(rdi, rax, times_4, 100)); + __ shlq_cl(Operand(rdi, rax, times_4, 100)); + __ shlq(rdx, Immediate(1)); + __ shlq(rdx, Immediate(6)); + __ shll(Operand(rdi, rax, times_4, 100), Immediate(1)); + __ shll(Operand(rdi, rax, times_4, 100), Immediate(6)); + __ shll(Operand(r15, 0), Immediate(1)); + __ shll(Operand(r15, 0), Immediate(6)); + __ shll_cl(Operand(r15, 0)); + __ shll_cl(Operand(r15, 0)); + __ shll_cl(Operand(rdi, rax, times_4, 100)); + __ shll_cl(Operand(rdi, rax, times_4, 100)); + __ shll(rdx, Immediate(1)); + __ shll(rdx, Immediate(6)); __ bts(Operand(rdx, 0), rcx); __ bts(Operand(rbx, rcx, times_4, 0), rcx); __ nop();