OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/arm64/frames-arm64.h" | 7 #include "src/arm64/frames-arm64.h" |
8 #include "src/arm64/macro-assembler-arm64.h" | 8 #include "src/arm64/macro-assembler-arm64.h" |
9 #include "src/compiler/code-generator-impl.h" | 9 #include "src/compiler/code-generator-impl.h" |
10 #include "src/compiler/gap-resolver.h" | 10 #include "src/compiler/gap-resolver.h" |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
378 if (descriptor->IsJSFunctionCall() || stack_slots > 0) { | 378 if (descriptor->IsJSFunctionCall() || stack_slots > 0) { |
379 __ Mov(jssp, fp); | 379 __ Mov(jssp, fp); |
380 __ Pop(fp, lr); | 380 __ Pop(fp, lr); |
381 } | 381 } |
382 } | 382 } |
383 | 383 |
384 | 384 |
385 // Assembles an instruction after register allocation, producing machine code. | 385 // Assembles an instruction after register allocation, producing machine code. |
386 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 386 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
387 Arm64OperandConverter i(this, instr); | 387 Arm64OperandConverter i(this, instr); |
388 InstructionCode opcode = instr->opcode(); | 388 switch (instr->arch_opcode()) { |
389 switch (ArchOpcodeField::decode(opcode)) { | |
390 case kArchCallCodeObject: { | 389 case kArchCallCodeObject: { |
391 EnsureSpaceForLazyDeopt(); | 390 EnsureSpaceForLazyDeopt(); |
392 if (instr->InputAt(0)->IsImmediate()) { | 391 if (instr->InputAt(0)->IsImmediate()) { |
393 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 392 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
394 RelocInfo::CODE_TARGET); | 393 RelocInfo::CODE_TARGET); |
395 } else { | 394 } else { |
396 Register target = i.InputRegister(0); | 395 Register target = i.InputRegister(0); |
397 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag); | 396 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag); |
398 __ Call(target); | 397 __ Call(target); |
399 } | 398 } |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
499 case kArm64Float64RoundTruncate: | 498 case kArm64Float64RoundTruncate: |
500 __ Frintz(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); | 499 __ Frintz(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
501 break; | 500 break; |
502 case kArm64Float64RoundUp: | 501 case kArm64Float64RoundUp: |
503 __ Frintp(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); | 502 __ Frintp(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
504 break; | 503 break; |
505 case kArm64Add: | 504 case kArm64Add: |
506 __ Add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2_64(1)); | 505 __ Add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2_64(1)); |
507 break; | 506 break; |
508 case kArm64Add32: | 507 case kArm64Add32: |
509 if (FlagsModeField::decode(opcode) != kFlags_none) { | 508 if (instr->flags_mode() != kFlags_none) { |
510 __ Adds(i.OutputRegister32(), i.InputRegister32(0), | 509 __ Adds(i.OutputRegister32(), i.InputRegister32(0), |
511 i.InputOperand2_32(1)); | 510 i.InputOperand2_32(1)); |
512 } else { | 511 } else { |
513 __ Add(i.OutputRegister32(), i.InputRegister32(0), | 512 __ Add(i.OutputRegister32(), i.InputRegister32(0), |
514 i.InputOperand2_32(1)); | 513 i.InputOperand2_32(1)); |
515 } | 514 } |
516 break; | 515 break; |
517 case kArm64And: | 516 case kArm64And: |
518 __ And(i.OutputRegister(), i.InputRegister(0), i.InputOperand2_64(1)); | 517 __ And(i.OutputRegister(), i.InputRegister(0), i.InputOperand2_64(1)); |
519 break; | 518 break; |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
635 case kArm64Eon: | 634 case kArm64Eon: |
636 __ Eon(i.OutputRegister(), i.InputRegister(0), i.InputOperand2_64(1)); | 635 __ Eon(i.OutputRegister(), i.InputRegister(0), i.InputOperand2_64(1)); |
637 break; | 636 break; |
638 case kArm64Eon32: | 637 case kArm64Eon32: |
639 __ Eon(i.OutputRegister32(), i.InputRegister32(0), i.InputOperand2_32(1)); | 638 __ Eon(i.OutputRegister32(), i.InputRegister32(0), i.InputOperand2_32(1)); |
640 break; | 639 break; |
641 case kArm64Sub: | 640 case kArm64Sub: |
642 __ Sub(i.OutputRegister(), i.InputRegister(0), i.InputOperand2_64(1)); | 641 __ Sub(i.OutputRegister(), i.InputRegister(0), i.InputOperand2_64(1)); |
643 break; | 642 break; |
644 case kArm64Sub32: | 643 case kArm64Sub32: |
645 if (FlagsModeField::decode(opcode) != kFlags_none) { | 644 if (instr->flags_mode() != kFlags_none) { |
646 __ Subs(i.OutputRegister32(), i.InputRegister32(0), | 645 __ Subs(i.OutputRegister32(), i.InputRegister32(0), |
647 i.InputOperand2_32(1)); | 646 i.InputOperand2_32(1)); |
648 } else { | 647 } else { |
649 __ Sub(i.OutputRegister32(), i.InputRegister32(0), | 648 __ Sub(i.OutputRegister32(), i.InputRegister32(0), |
650 i.InputOperand2_32(1)); | 649 i.InputOperand2_32(1)); |
651 } | 650 } |
652 break; | 651 break; |
653 case kArm64Lsl: | 652 case kArm64Lsl: |
654 ASSEMBLE_SHIFT(Lsl, 64); | 653 ASSEMBLE_SHIFT(Lsl, 64); |
655 break; | 654 break; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
741 break; | 740 break; |
742 case kArm64Cmn32: | 741 case kArm64Cmn32: |
743 __ Cmn(i.InputRegister32(0), i.InputOperand32(1)); | 742 __ Cmn(i.InputRegister32(0), i.InputOperand32(1)); |
744 break; | 743 break; |
745 case kArm64Tst: | 744 case kArm64Tst: |
746 __ Tst(i.InputRegister(0), i.InputOperand(1)); | 745 __ Tst(i.InputRegister(0), i.InputOperand(1)); |
747 break; | 746 break; |
748 case kArm64Tst32: | 747 case kArm64Tst32: |
749 __ Tst(i.InputRegister32(0), i.InputOperand32(1)); | 748 __ Tst(i.InputRegister32(0), i.InputOperand32(1)); |
750 break; | 749 break; |
750 case kArm64Float32CmpAndFloat32Sel: | |
Benedikt Meurer
2015/09/21 17:31:43
Hm, this instruction looks redundant. Why do you n
jbramley
2015/09/22 07:45:20
Because, although I haven't done so yet, we might
| |
751 DCHECK(instr->flags_mode() == kFlags_select); | |
752 // Fall through. | |
751 case kArm64Float32Cmp: | 753 case kArm64Float32Cmp: |
752 if (instr->InputAt(1)->IsDoubleRegister()) { | 754 if (instr->InputAt(1)->IsDoubleRegister()) { |
753 __ Fcmp(i.InputFloat32Register(0), i.InputFloat32Register(1)); | 755 __ Fcmp(i.InputFloat32Register(0), i.InputFloat32Register(1)); |
754 } else { | 756 } else { |
755 DCHECK(instr->InputAt(1)->IsImmediate()); | 757 DCHECK(instr->InputAt(1)->IsImmediate()); |
756 // 0.0 is the only immediate supported by fcmp instructions. | 758 // 0.0 is the only immediate supported by fcmp instructions. |
757 DCHECK(i.InputDouble(1) == 0.0); | 759 DCHECK(i.InputDouble(1) == 0.0); |
758 __ Fcmp(i.InputFloat32Register(0), i.InputDouble(1)); | 760 __ Fcmp(i.InputFloat32Register(0), i.InputDouble(1)); |
759 } | 761 } |
760 break; | 762 break; |
(...skipping 20 matching lines...) Expand all Loading... | |
781 case kArm64Float32Min: | 783 case kArm64Float32Min: |
782 __ Fmin(i.OutputFloat32Register(), i.InputFloat32Register(0), | 784 __ Fmin(i.OutputFloat32Register(), i.InputFloat32Register(0), |
783 i.InputFloat32Register(1)); | 785 i.InputFloat32Register(1)); |
784 break; | 786 break; |
785 case kArm64Float32Abs: | 787 case kArm64Float32Abs: |
786 __ Fabs(i.OutputFloat32Register(), i.InputFloat32Register(0)); | 788 __ Fabs(i.OutputFloat32Register(), i.InputFloat32Register(0)); |
787 break; | 789 break; |
788 case kArm64Float32Sqrt: | 790 case kArm64Float32Sqrt: |
789 __ Fsqrt(i.OutputFloat32Register(), i.InputFloat32Register(0)); | 791 __ Fsqrt(i.OutputFloat32Register(), i.InputFloat32Register(0)); |
790 break; | 792 break; |
793 case kArm64Float64CmpAndFloat64Sel: | |
Benedikt Meurer
2015/09/21 17:31:43
Same here?
| |
794 DCHECK(instr->flags_mode() == kFlags_select); | |
795 // Fall through. | |
791 case kArm64Float64Cmp: | 796 case kArm64Float64Cmp: |
792 if (instr->InputAt(1)->IsDoubleRegister()) { | 797 if (instr->InputAt(1)->IsDoubleRegister()) { |
793 __ Fcmp(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); | 798 __ Fcmp(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); |
794 } else { | 799 } else { |
795 DCHECK(instr->InputAt(1)->IsImmediate()); | 800 DCHECK(instr->InputAt(1)->IsImmediate()); |
796 // 0.0 is the only immediate supported by fcmp instructions. | 801 // 0.0 is the only immediate supported by fcmp instructions. |
797 DCHECK(i.InputDouble(1) == 0.0); | 802 DCHECK(i.InputDouble(1) == 0.0); |
798 __ Fcmp(i.InputDoubleRegister(0), i.InputDouble(1)); | 803 __ Fcmp(i.InputDoubleRegister(0), i.InputDouble(1)); |
799 } | 804 } |
800 break; | 805 break; |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1062 | 1067 |
1063 // Materialize a full 64-bit 1 or 0 value. The result register is always the | 1068 // Materialize a full 64-bit 1 or 0 value. The result register is always the |
1064 // last output of the instruction. | 1069 // last output of the instruction. |
1065 DCHECK_NE(0u, instr->OutputCount()); | 1070 DCHECK_NE(0u, instr->OutputCount()); |
1066 Register reg = i.OutputRegister(instr->OutputCount() - 1); | 1071 Register reg = i.OutputRegister(instr->OutputCount() - 1); |
1067 Condition cc = FlagsConditionToCondition(condition); | 1072 Condition cc = FlagsConditionToCondition(condition); |
1068 __ Cset(reg, cc); | 1073 __ Cset(reg, cc); |
1069 } | 1074 } |
1070 | 1075 |
1071 | 1076 |
1077 void CodeGenerator::AssembleArchSelect(Instruction* instr, | |
1078 FlagsCondition condition) { | |
1079 Arm64OperandConverter i(this, instr); | |
1080 | |
1081 DCHECK_EQ(1u, instr->OutputCount()); | |
1082 | |
1083 Condition cc = FlagsConditionToCondition(condition); | |
1084 switch (instr->arch_opcode()) { | |
1085 case kArm64Float32CmpAndFloat32Sel: { | |
Benedikt Meurer
2015/09/21 17:31:43
I'm not sure if this approach scales well. Because
jbramley
2015/09/22 07:45:21
Indeed, but (unless I'm mistaken), TF can't track
| |
1086 DoubleRegister result = i.OutputFloat32Register(); | |
1087 DoubleRegister a = i.InputFloat32Register(instr->InputCount() - 2); | |
1088 DoubleRegister b = i.InputFloat32Register(instr->InputCount() - 1); | |
1089 __ Fcsel(result, a, b, cc); | |
1090 return; | |
1091 } | |
1092 case kArm64Float64CmpAndFloat64Sel: { | |
1093 DoubleRegister result = i.OutputFloat64Register(); | |
1094 DoubleRegister a = i.InputFloat64Register(instr->InputCount() - 2); | |
1095 DoubleRegister b = i.InputFloat64Register(instr->InputCount() - 1); | |
1096 __ Fcsel(result, a, b, cc); | |
1097 return; | |
1098 } | |
1099 default: | |
1100 UNREACHABLE(); | |
1101 return; | |
1102 } | |
1103 } | |
1104 | |
1105 | |
1072 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { | 1106 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { |
1073 Arm64OperandConverter i(this, instr); | 1107 Arm64OperandConverter i(this, instr); |
1074 Register input = i.InputRegister32(0); | 1108 Register input = i.InputRegister32(0); |
1075 for (size_t index = 2; index < instr->InputCount(); index += 2) { | 1109 for (size_t index = 2; index < instr->InputCount(); index += 2) { |
1076 __ Cmp(input, i.InputInt32(index + 0)); | 1110 __ Cmp(input, i.InputInt32(index + 0)); |
1077 __ B(eq, GetLabel(i.InputRpo(index + 1))); | 1111 __ B(eq, GetLabel(i.InputRpo(index + 1))); |
1078 } | 1112 } |
1079 AssembleArchJump(i.InputRpo(1)); | 1113 AssembleArchJump(i.InputRpo(1)); |
1080 } | 1114 } |
1081 | 1115 |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1400 padding_size -= kInstructionSize; | 1434 padding_size -= kInstructionSize; |
1401 } | 1435 } |
1402 } | 1436 } |
1403 } | 1437 } |
1404 | 1438 |
1405 #undef __ | 1439 #undef __ |
1406 | 1440 |
1407 } // namespace compiler | 1441 } // namespace compiler |
1408 } // namespace internal | 1442 } // namespace internal |
1409 } // namespace v8 | 1443 } // namespace v8 |
OLD | NEW |