| 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/macro-assembler-arm64.h" | 7 #include "src/arm64/macro-assembler-arm64.h" |
| 8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
| 9 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
| 10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 if (instr->InputAt(1)->IsRegister()) { \ | 273 if (instr->InputAt(1)->IsRegister()) { \ |
| 274 __ asm_instr(i.OutputRegister##width(), i.InputRegister##width(0), \ | 274 __ asm_instr(i.OutputRegister##width(), i.InputRegister##width(0), \ |
| 275 i.InputRegister##width(1)); \ | 275 i.InputRegister##width(1)); \ |
| 276 } else { \ | 276 } else { \ |
| 277 int64_t imm = i.InputOperand##width(1).immediate().value(); \ | 277 int64_t imm = i.InputOperand##width(1).immediate().value(); \ |
| 278 __ asm_instr(i.OutputRegister##width(), i.InputRegister##width(0), imm); \ | 278 __ asm_instr(i.OutputRegister##width(), i.InputRegister##width(0), imm); \ |
| 279 } \ | 279 } \ |
| 280 } while (0) | 280 } while (0) |
| 281 | 281 |
| 282 | 282 |
| 283 #define ASSEMBLE_BRANCH_TO(target) \ | |
| 284 do { \ | |
| 285 bool fallthrough = IsNextInAssemblyOrder(target); \ | |
| 286 if (!fallthrough) __ B(GetLabel(target)); \ | |
| 287 } while (0) | |
| 288 | |
| 289 | |
| 290 // Assembles an instruction after register allocation, producing machine code. | 283 // Assembles an instruction after register allocation, producing machine code. |
| 291 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 284 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
| 292 Arm64OperandConverter i(this, instr); | 285 Arm64OperandConverter i(this, instr); |
| 293 InstructionCode opcode = instr->opcode(); | 286 InstructionCode opcode = instr->opcode(); |
| 294 switch (ArchOpcodeField::decode(opcode)) { | 287 switch (ArchOpcodeField::decode(opcode)) { |
| 295 case kArchCallCodeObject: { | 288 case kArchCallCodeObject: { |
| 296 EnsureSpaceForLazyDeopt(); | 289 EnsureSpaceForLazyDeopt(); |
| 297 if (instr->InputAt(0)->IsImmediate()) { | 290 if (instr->InputAt(0)->IsImmediate()) { |
| 298 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 291 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
| 299 RelocInfo::CODE_TARGET); | 292 RelocInfo::CODE_TARGET); |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 __ Sxtw(i.OutputRegister(), i.InputRegister32(0)); | 527 __ Sxtw(i.OutputRegister(), i.InputRegister32(0)); |
| 535 break; | 528 break; |
| 536 case kArm64Ubfx: | 529 case kArm64Ubfx: |
| 537 __ Ubfx(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1), | 530 __ Ubfx(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1), |
| 538 i.InputInt8(2)); | 531 i.InputInt8(2)); |
| 539 break; | 532 break; |
| 540 case kArm64Ubfx32: | 533 case kArm64Ubfx32: |
| 541 __ Ubfx(i.OutputRegister32(), i.InputRegister32(0), i.InputInt8(1), | 534 __ Ubfx(i.OutputRegister32(), i.InputRegister32(0), i.InputInt8(1), |
| 542 i.InputInt8(2)); | 535 i.InputInt8(2)); |
| 543 break; | 536 break; |
| 544 case kArm64Tbz: | 537 case kArm64TestAndBranch32: |
| 545 __ Tbz(i.InputRegister64(0), i.InputInt6(1), GetLabel(i.InputRpo(2))); | 538 case kArm64TestAndBranch: |
| 546 ASSEMBLE_BRANCH_TO(i.InputRpo(3)); | 539 // Pseudo instructions turned into tbz/tbnz in AssembleArchBranch. |
| 547 break; | 540 break; |
| 548 case kArm64Tbz32: | 541 case kArm64CompareAndBranch32: |
| 549 __ Tbz(i.InputRegister32(0), i.InputInt5(1), GetLabel(i.InputRpo(2))); | 542 // Pseudo instruction turned into cbz/cbnz in AssembleArchBranch. |
| 550 ASSEMBLE_BRANCH_TO(i.InputRpo(3)); | |
| 551 break; | |
| 552 case kArm64Tbnz: | |
| 553 __ Tbnz(i.InputRegister64(0), i.InputInt6(1), GetLabel(i.InputRpo(2))); | |
| 554 ASSEMBLE_BRANCH_TO(i.InputRpo(3)); | |
| 555 break; | |
| 556 case kArm64Tbnz32: | |
| 557 __ Tbnz(i.InputRegister32(0), i.InputInt5(1), GetLabel(i.InputRpo(2))); | |
| 558 ASSEMBLE_BRANCH_TO(i.InputRpo(3)); | |
| 559 break; | |
| 560 case kArm64Cbz32: | |
| 561 __ Cbz(i.InputRegister32(0), GetLabel(i.InputRpo(1))); | |
| 562 ASSEMBLE_BRANCH_TO(i.InputRpo(2)); | |
| 563 break; | |
| 564 case kArm64Cbnz32: | |
| 565 __ Cbnz(i.InputRegister32(0), GetLabel(i.InputRpo(1))); | |
| 566 ASSEMBLE_BRANCH_TO(i.InputRpo(2)); | |
| 567 break; | 543 break; |
| 568 case kArm64Claim: { | 544 case kArm64Claim: { |
| 569 int words = MiscField::decode(instr->opcode()); | 545 int words = MiscField::decode(instr->opcode()); |
| 570 __ Claim(words); | 546 __ Claim(words); |
| 571 break; | 547 break; |
| 572 } | 548 } |
| 573 case kArm64Poke: { | 549 case kArm64Poke: { |
| 574 int slot = MiscField::decode(instr->opcode()); | 550 int slot = MiscField::decode(instr->opcode()); |
| 575 Operand operand(slot * kPointerSize); | 551 Operand operand(slot * kPointerSize); |
| 576 __ Poke(i.InputRegister(0), operand); | 552 __ Poke(i.InputRegister(0), operand); |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 759 break; | 735 break; |
| 760 } | 736 } |
| 761 } | 737 } |
| 762 | 738 |
| 763 | 739 |
| 764 // Assemble branches after this instruction. | 740 // Assemble branches after this instruction. |
| 765 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | 741 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
| 766 Arm64OperandConverter i(this, instr); | 742 Arm64OperandConverter i(this, instr); |
| 767 Label* tlabel = branch->true_label; | 743 Label* tlabel = branch->true_label; |
| 768 Label* flabel = branch->false_label; | 744 Label* flabel = branch->false_label; |
| 769 switch (branch->condition) { | 745 FlagsCondition condition = branch->condition; |
| 770 case kUnorderedEqual: | 746 ArchOpcode opcode = instr->arch_opcode(); |
| 771 __ B(vs, flabel); | 747 |
| 772 // Fall through. | 748 if (opcode == kArm64CompareAndBranch32) { |
| 773 case kEqual: | 749 switch (condition) { |
| 774 __ B(eq, tlabel); | 750 case kEqual: |
| 775 break; | 751 __ Cbz(i.InputRegister32(0), tlabel); |
| 776 case kUnorderedNotEqual: | 752 break; |
| 777 __ B(vs, tlabel); | 753 case kNotEqual: |
| 778 // Fall through. | 754 __ Cbnz(i.InputRegister32(0), tlabel); |
| 779 case kNotEqual: | 755 break; |
| 780 __ B(ne, tlabel); | 756 default: |
| 781 break; | 757 UNREACHABLE(); |
| 782 case kSignedLessThan: | 758 } |
| 783 __ B(lt, tlabel); | 759 } else if (opcode == kArm64TestAndBranch32) { |
| 784 break; | 760 switch (condition) { |
| 785 case kSignedGreaterThanOrEqual: | 761 case kEqual: |
| 786 __ B(ge, tlabel); | 762 __ Tbz(i.InputRegister32(0), i.InputInt5(1), tlabel); |
| 787 break; | 763 break; |
| 788 case kSignedLessThanOrEqual: | 764 case kNotEqual: |
| 789 __ B(le, tlabel); | 765 __ Tbnz(i.InputRegister32(0), i.InputInt5(1), tlabel); |
| 790 break; | 766 break; |
| 791 case kSignedGreaterThan: | 767 default: |
| 792 __ B(gt, tlabel); | 768 UNREACHABLE(); |
| 793 break; | 769 } |
| 794 case kUnorderedLessThan: | 770 } else if (opcode == kArm64TestAndBranch) { |
| 795 __ B(vs, flabel); | 771 switch (condition) { |
| 796 // Fall through. | 772 case kEqual: |
| 797 case kUnsignedLessThan: | 773 __ Tbz(i.InputRegister64(0), i.InputInt6(1), tlabel); |
| 798 __ B(lo, tlabel); | 774 break; |
| 799 break; | 775 case kNotEqual: |
| 800 case kUnorderedGreaterThanOrEqual: | 776 __ Tbnz(i.InputRegister64(0), i.InputInt6(1), tlabel); |
| 801 __ B(vs, tlabel); | 777 break; |
| 802 // Fall through. | 778 default: |
| 803 case kUnsignedGreaterThanOrEqual: | 779 UNREACHABLE(); |
| 804 __ B(hs, tlabel); | 780 } |
| 805 break; | 781 } else { |
| 806 case kUnorderedLessThanOrEqual: | 782 switch (condition) { |
| 807 __ B(vs, flabel); | 783 case kUnorderedEqual: |
| 808 // Fall through. | 784 __ B(vs, flabel); |
| 809 case kUnsignedLessThanOrEqual: | 785 // Fall through. |
| 810 __ B(ls, tlabel); | 786 case kEqual: |
| 811 break; | 787 __ B(eq, tlabel); |
| 812 case kUnorderedGreaterThan: | 788 break; |
| 813 __ B(vs, tlabel); | 789 case kUnorderedNotEqual: |
| 814 // Fall through. | 790 __ B(vs, tlabel); |
| 815 case kUnsignedGreaterThan: | 791 // Fall through. |
| 816 __ B(hi, tlabel); | 792 case kNotEqual: |
| 817 break; | 793 __ B(ne, tlabel); |
| 818 case kOverflow: | 794 break; |
| 819 __ B(vs, tlabel); | 795 case kSignedLessThan: |
| 820 break; | 796 __ B(lt, tlabel); |
| 821 case kNotOverflow: | 797 break; |
| 822 __ B(vc, tlabel); | 798 case kSignedGreaterThanOrEqual: |
| 823 break; | 799 __ B(ge, tlabel); |
| 800 break; |
| 801 case kSignedLessThanOrEqual: |
| 802 __ B(le, tlabel); |
| 803 break; |
| 804 case kSignedGreaterThan: |
| 805 __ B(gt, tlabel); |
| 806 break; |
| 807 case kUnorderedLessThan: |
| 808 __ B(vs, flabel); |
| 809 // Fall through. |
| 810 case kUnsignedLessThan: |
| 811 __ B(lo, tlabel); |
| 812 break; |
| 813 case kUnorderedGreaterThanOrEqual: |
| 814 __ B(vs, tlabel); |
| 815 // Fall through. |
| 816 case kUnsignedGreaterThanOrEqual: |
| 817 __ B(hs, tlabel); |
| 818 break; |
| 819 case kUnorderedLessThanOrEqual: |
| 820 __ B(vs, flabel); |
| 821 // Fall through. |
| 822 case kUnsignedLessThanOrEqual: |
| 823 __ B(ls, tlabel); |
| 824 break; |
| 825 case kUnorderedGreaterThan: |
| 826 __ B(vs, tlabel); |
| 827 // Fall through. |
| 828 case kUnsignedGreaterThan: |
| 829 __ B(hi, tlabel); |
| 830 break; |
| 831 case kOverflow: |
| 832 __ B(vs, tlabel); |
| 833 break; |
| 834 case kNotOverflow: |
| 835 __ B(vc, tlabel); |
| 836 break; |
| 837 } |
| 824 } | 838 } |
| 825 if (!branch->fallthru) __ B(flabel); // no fallthru to flabel. | 839 if (!branch->fallthru) __ B(flabel); // no fallthru to flabel. |
| 826 } | 840 } |
| 827 | 841 |
| 828 | 842 |
| 829 void CodeGenerator::AssembleArchJump(BasicBlock::RpoNumber target) { | 843 void CodeGenerator::AssembleArchJump(BasicBlock::RpoNumber target) { |
| 830 if (!IsNextInAssemblyOrder(target)) __ B(GetLabel(target)); | 844 if (!IsNextInAssemblyOrder(target)) __ B(GetLabel(target)); |
| 831 } | 845 } |
| 832 | 846 |
| 833 | 847 |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1157 } | 1171 } |
| 1158 } | 1172 } |
| 1159 MarkLazyDeoptSite(); | 1173 MarkLazyDeoptSite(); |
| 1160 } | 1174 } |
| 1161 | 1175 |
| 1162 #undef __ | 1176 #undef __ |
| 1163 | 1177 |
| 1164 } // namespace compiler | 1178 } // namespace compiler |
| 1165 } // namespace internal | 1179 } // namespace internal |
| 1166 } // namespace v8 | 1180 } // namespace v8 |
| OLD | NEW |