OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
6 | 6 |
7 #include "src/compiler/code-generator-impl.h" | 7 #include "src/compiler/code-generator-impl.h" |
8 #include "src/compiler/gap-resolver.h" | 8 #include "src/compiler/gap-resolver.h" |
9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
10 #include "src/compiler/node-properties-inl.h" | 10 #include "src/compiler/node-properties-inl.h" |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 __ asm_instr##_cl(i.OutputRegister()); \ | 197 __ asm_instr##_cl(i.OutputRegister()); \ |
198 } \ | 198 } \ |
199 } while (0) | 199 } while (0) |
200 | 200 |
201 | 201 |
202 // Assembles an instruction after register allocation, producing machine code. | 202 // Assembles an instruction after register allocation, producing machine code. |
203 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 203 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
204 X64OperandConverter i(this, instr); | 204 X64OperandConverter i(this, instr); |
205 | 205 |
206 switch (ArchOpcodeField::decode(instr->opcode())) { | 206 switch (ArchOpcodeField::decode(instr->opcode())) { |
| 207 case kArchCallCodeObject: { |
| 208 if (HasImmediateInput(instr, 0)) { |
| 209 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
| 210 __ Call(code, RelocInfo::CODE_TARGET); |
| 211 } else { |
| 212 Register reg = i.InputRegister(0); |
| 213 int entry = Code::kHeaderSize - kHeapObjectTag; |
| 214 __ Call(Operand(reg, entry)); |
| 215 } |
| 216 AddSafepointAndDeopt(instr); |
| 217 AddNopForSmiCodeInlining(); |
| 218 break; |
| 219 } |
| 220 case kArchCallAddress: |
| 221 if (HasImmediateInput(instr, 0)) { |
| 222 Immediate64 imm = i.InputImmediate64(0); |
| 223 DCHECK_EQ(kImm64Value, imm.type); |
| 224 __ Call(reinterpret_cast<byte*>(imm.value), RelocInfo::NONE64); |
| 225 } else { |
| 226 __ call(i.InputRegister(0)); |
| 227 } |
| 228 break; |
| 229 case kArchCallJSFunction: { |
| 230 // TODO(jarin) The load of the context should be separated from the call. |
| 231 Register func = i.InputRegister(0); |
| 232 __ movp(rsi, FieldOperand(func, JSFunction::kContextOffset)); |
| 233 __ Call(FieldOperand(func, JSFunction::kCodeEntryOffset)); |
| 234 AddSafepointAndDeopt(instr); |
| 235 break; |
| 236 } |
| 237 case kArchDeoptimize: { |
| 238 int deoptimization_id = MiscField::decode(instr->opcode()); |
| 239 BuildTranslation(instr, 0, deoptimization_id); |
| 240 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( |
| 241 isolate(), deoptimization_id, Deoptimizer::LAZY); |
| 242 __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY); |
| 243 break; |
| 244 } |
| 245 case kArchDrop: { |
| 246 int words = MiscField::decode(instr->opcode()); |
| 247 __ addq(rsp, Immediate(kPointerSize * words)); |
| 248 break; |
| 249 } |
207 case kArchJmp: | 250 case kArchJmp: |
208 __ jmp(code_->GetLabel(i.InputBlock(0))); | 251 __ jmp(code_->GetLabel(i.InputBlock(0))); |
209 break; | 252 break; |
210 case kArchNop: | 253 case kArchNop: |
211 // don't emit code for nops. | 254 // don't emit code for nops. |
212 break; | 255 break; |
213 case kArchRet: | 256 case kArchRet: |
214 AssembleReturn(); | 257 AssembleReturn(); |
215 break; | 258 break; |
216 case kArchDeoptimize: { | |
217 int deoptimization_id = MiscField::decode(instr->opcode()); | |
218 BuildTranslation(instr, 0, deoptimization_id); | |
219 | |
220 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( | |
221 isolate(), deoptimization_id, Deoptimizer::LAZY); | |
222 __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY); | |
223 break; | |
224 } | |
225 case kArchTruncateDoubleToI: | 259 case kArchTruncateDoubleToI: |
226 __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); | 260 __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); |
227 break; | 261 break; |
228 case kX64Add32: | 262 case kX64Add32: |
229 ASSEMBLE_BINOP(addl); | 263 ASSEMBLE_BINOP(addl); |
230 break; | 264 break; |
231 case kX64Add: | 265 case kX64Add: |
232 ASSEMBLE_BINOP(addq); | 266 ASSEMBLE_BINOP(addq); |
233 break; | 267 break; |
234 case kX64Sub32: | 268 case kX64Sub32: |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 break; | 406 break; |
373 case kX64Sar: | 407 case kX64Sar: |
374 ASSEMBLE_SHIFT(sarq, 6); | 408 ASSEMBLE_SHIFT(sarq, 6); |
375 break; | 409 break; |
376 case kX64Ror32: | 410 case kX64Ror32: |
377 ASSEMBLE_SHIFT(rorl, 5); | 411 ASSEMBLE_SHIFT(rorl, 5); |
378 break; | 412 break; |
379 case kX64Ror: | 413 case kX64Ror: |
380 ASSEMBLE_SHIFT(rorq, 6); | 414 ASSEMBLE_SHIFT(rorq, 6); |
381 break; | 415 break; |
382 case kX64Push: { | |
383 RegisterOrOperand input = i.InputRegisterOrOperand(0); | |
384 if (input.type == kRegister) { | |
385 __ pushq(input.reg); | |
386 } else { | |
387 __ pushq(input.operand); | |
388 } | |
389 break; | |
390 } | |
391 case kX64PushI: | |
392 __ pushq(i.InputImmediate(0)); | |
393 break; | |
394 case kX64CallCodeObject: { | |
395 if (HasImmediateInput(instr, 0)) { | |
396 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | |
397 __ Call(code, RelocInfo::CODE_TARGET); | |
398 } else { | |
399 Register reg = i.InputRegister(0); | |
400 int entry = Code::kHeaderSize - kHeapObjectTag; | |
401 __ Call(Operand(reg, entry)); | |
402 } | |
403 | |
404 AddSafepointAndDeopt(instr); | |
405 | |
406 AddNopForSmiCodeInlining(); | |
407 break; | |
408 } | |
409 case kX64CallAddress: | |
410 if (HasImmediateInput(instr, 0)) { | |
411 Immediate64 imm = i.InputImmediate64(0); | |
412 DCHECK_EQ(kImm64Value, imm.type); | |
413 __ Call(reinterpret_cast<byte*>(imm.value), RelocInfo::NONE64); | |
414 } else { | |
415 __ call(i.InputRegister(0)); | |
416 } | |
417 break; | |
418 case kPopStack: { | |
419 int words = MiscField::decode(instr->opcode()); | |
420 __ addq(rsp, Immediate(kPointerSize * words)); | |
421 break; | |
422 } | |
423 case kX64CallJSFunction: { | |
424 Register func = i.InputRegister(0); | |
425 | |
426 // TODO(jarin) The load of the context should be separated from the call. | |
427 __ movp(rsi, FieldOperand(func, JSFunction::kContextOffset)); | |
428 __ Call(FieldOperand(func, JSFunction::kCodeEntryOffset)); | |
429 | |
430 AddSafepointAndDeopt(instr); | |
431 break; | |
432 } | |
433 case kSSEFloat64Cmp: { | 416 case kSSEFloat64Cmp: { |
434 RegisterOrOperand input = i.InputRegisterOrOperand(1); | 417 RegisterOrOperand input = i.InputRegisterOrOperand(1); |
435 if (input.type == kDoubleRegister) { | 418 if (input.type == kDoubleRegister) { |
436 __ ucomisd(i.InputDoubleRegister(0), input.double_reg); | 419 __ ucomisd(i.InputDoubleRegister(0), input.double_reg); |
437 } else { | 420 } else { |
438 __ ucomisd(i.InputDoubleRegister(0), input.operand); | 421 __ ucomisd(i.InputDoubleRegister(0), input.operand); |
439 } | 422 } |
440 break; | 423 break; |
441 } | 424 } |
442 case kSSEFloat64Add: | 425 case kSSEFloat64Add: |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 } else { | 489 } else { |
507 __ cvtlsi2sd(i.OutputDoubleRegister(), input.operand); | 490 __ cvtlsi2sd(i.OutputDoubleRegister(), input.operand); |
508 } | 491 } |
509 break; | 492 break; |
510 } | 493 } |
511 case kSSEUint32ToFloat64: { | 494 case kSSEUint32ToFloat64: { |
512 // TODO(turbofan): X64 SSE cvtqsi2sd should support operands. | 495 // TODO(turbofan): X64 SSE cvtqsi2sd should support operands. |
513 __ cvtqsi2sd(i.OutputDoubleRegister(), i.InputRegister(0)); | 496 __ cvtqsi2sd(i.OutputDoubleRegister(), i.InputRegister(0)); |
514 break; | 497 break; |
515 } | 498 } |
516 | |
517 case kX64Movsxbl: | 499 case kX64Movsxbl: |
518 __ movsxbl(i.OutputRegister(), i.MemoryOperand()); | 500 __ movsxbl(i.OutputRegister(), i.MemoryOperand()); |
519 break; | 501 break; |
520 case kX64Movzxbl: | 502 case kX64Movzxbl: |
521 __ movzxbl(i.OutputRegister(), i.MemoryOperand()); | 503 __ movzxbl(i.OutputRegister(), i.MemoryOperand()); |
522 break; | 504 break; |
523 case kX64Movb: { | 505 case kX64Movb: { |
524 int index = 0; | 506 int index = 0; |
525 Operand operand = i.MemoryOperand(&index); | 507 Operand operand = i.MemoryOperand(&index); |
526 if (HasImmediateInput(instr, index)) { | 508 if (HasImmediateInput(instr, index)) { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 break; | 585 break; |
604 case kX64Movsd: | 586 case kX64Movsd: |
605 if (instr->HasOutput()) { | 587 if (instr->HasOutput()) { |
606 __ movsd(i.OutputDoubleRegister(), i.MemoryOperand()); | 588 __ movsd(i.OutputDoubleRegister(), i.MemoryOperand()); |
607 } else { | 589 } else { |
608 int index = 0; | 590 int index = 0; |
609 Operand operand = i.MemoryOperand(&index); | 591 Operand operand = i.MemoryOperand(&index); |
610 __ movsd(operand, i.InputDoubleRegister(index)); | 592 __ movsd(operand, i.InputDoubleRegister(index)); |
611 } | 593 } |
612 break; | 594 break; |
| 595 case kX64Push: |
| 596 if (HasImmediateInput(instr, 0)) { |
| 597 __ pushq(i.InputImmediate(0)); |
| 598 } else { |
| 599 RegisterOrOperand input = i.InputRegisterOrOperand(0); |
| 600 if (input.type == kRegister) { |
| 601 __ pushq(input.reg); |
| 602 } else { |
| 603 __ pushq(input.operand); |
| 604 } |
| 605 } |
| 606 break; |
613 case kX64StoreWriteBarrier: { | 607 case kX64StoreWriteBarrier: { |
614 Register object = i.InputRegister(0); | 608 Register object = i.InputRegister(0); |
615 Register index = i.InputRegister(1); | 609 Register index = i.InputRegister(1); |
616 Register value = i.InputRegister(2); | 610 Register value = i.InputRegister(2); |
617 __ movsxlq(index, index); | 611 __ movsxlq(index, index); |
618 __ movq(Operand(object, index, times_1, 0), value); | 612 __ movq(Operand(object, index, times_1, 0), value); |
619 __ leaq(index, Operand(object, index, times_1, 0)); | 613 __ leaq(index, Operand(object, index, times_1, 0)); |
620 SaveFPRegsMode mode = code_->frame()->DidAllocateDoubleRegisters() | 614 SaveFPRegsMode mode = code_->frame()->DidAllocateDoubleRegisters() |
621 ? kSaveFPRegs | 615 ? kSaveFPRegs |
622 : kDontSaveFPRegs; | 616 : kDontSaveFPRegs; |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1003 } | 997 } |
1004 | 998 |
1005 | 999 |
1006 void CodeGenerator::AddNopForSmiCodeInlining() { __ nop(); } | 1000 void CodeGenerator::AddNopForSmiCodeInlining() { __ nop(); } |
1007 | 1001 |
1008 #undef __ | 1002 #undef __ |
1009 | 1003 |
1010 } // namespace internal | 1004 } // namespace internal |
1011 } // namespace compiler | 1005 } // namespace compiler |
1012 } // namespace v8 | 1006 } // namespace v8 |
OLD | NEW |