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 #include "src/compiler/code-generator-impl.h" | 6 #include "src/compiler/code-generator-impl.h" |
7 #include "src/compiler/gap-resolver.h" | 7 #include "src/compiler/gap-resolver.h" |
8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
9 #include "src/compiler/osr.h" | 9 #include "src/compiler/osr.h" |
10 #include "src/mips/macro-assembler-mips.h" | 10 #include "src/mips/macro-assembler-mips.h" |
(...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
897 return false; | 897 return false; |
898 } | 898 } |
899 | 899 |
900 | 900 |
901 // Assembles branches after an instruction. | 901 // Assembles branches after an instruction. |
902 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | 902 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
903 MipsOperandConverter i(this, instr); | 903 MipsOperandConverter i(this, instr); |
904 Label* tlabel = branch->true_label; | 904 Label* tlabel = branch->true_label; |
905 Label* flabel = branch->false_label; | 905 Label* flabel = branch->false_label; |
906 Condition cc = kNoCondition; | 906 Condition cc = kNoCondition; |
907 | |
908 // MIPS does not have condition code flags, so compare and branch are | 907 // MIPS does not have condition code flags, so compare and branch are |
909 // implemented differently than on the other arch's. The compare operations | 908 // implemented differently than on the other arch's. The compare operations |
910 // emit mips pseudo-instructions, which are handled here by branch | 909 // emit mips pseudo-instructions, which are handled here by branch |
911 // instructions that do the actual comparison. Essential that the input | 910 // instructions that do the actual comparison. Essential that the input |
912 // registers to compare pseudo-op are not modified before this branch op, as | 911 // registers to compare pseudo-op are not modified before this branch op, as |
913 // they are tested here. | 912 // they are tested here. |
914 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were | |
915 // not separated by other instructions. | |
916 | 913 |
917 if (instr->arch_opcode() == kMipsTst) { | 914 if (instr->arch_opcode() == kMipsTst) { |
918 cc = FlagsConditionToConditionTst(branch->condition); | 915 cc = FlagsConditionToConditionTst(branch->condition); |
919 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 916 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
920 __ Branch(tlabel, cc, at, Operand(zero_reg)); | 917 __ Branch(tlabel, cc, at, Operand(zero_reg)); |
921 } else if (instr->arch_opcode() == kMipsAddOvf || | 918 } else if (instr->arch_opcode() == kMipsAddOvf || |
922 instr->arch_opcode() == kMipsSubOvf) { | 919 instr->arch_opcode() == kMipsSubOvf) { |
923 // kMipsAddOvf, SubOvf emit negative result to 'kCompareReg' on overflow. | 920 // kMipsAddOvf, SubOvf emit negative result to 'kCompareReg' on overflow. |
924 cc = FlagsConditionToConditionOvf(branch->condition); | 921 cc = FlagsConditionToConditionOvf(branch->condition); |
925 __ Branch(tlabel, cc, kCompareReg, Operand(zero_reg)); | 922 __ Branch(tlabel, cc, kCompareReg, Operand(zero_reg)); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
957 FlagsCondition condition) { | 954 FlagsCondition condition) { |
958 MipsOperandConverter i(this, instr); | 955 MipsOperandConverter i(this, instr); |
959 Label done; | 956 Label done; |
960 | 957 |
961 // Materialize a full 32-bit 1 or 0 value. The result register is always the | 958 // Materialize a full 32-bit 1 or 0 value. The result register is always the |
962 // last output of the instruction. | 959 // last output of the instruction. |
963 Label false_value; | 960 Label false_value; |
964 DCHECK_NE(0u, instr->OutputCount()); | 961 DCHECK_NE(0u, instr->OutputCount()); |
965 Register result = i.OutputRegister(instr->OutputCount() - 1); | 962 Register result = i.OutputRegister(instr->OutputCount() - 1); |
966 Condition cc = kNoCondition; | 963 Condition cc = kNoCondition; |
967 | |
968 // MIPS does not have condition code flags, so compare and branch are | 964 // MIPS does not have condition code flags, so compare and branch are |
969 // implemented differently than on the other arch's. The compare operations | 965 // implemented differently than on the other arch's. The compare operations |
970 // emit mips psuedo-instructions, which are checked and handled here. | 966 // emit mips psuedo-instructions, which are checked and handled here. |
971 | 967 |
972 // For materializations, we use delay slot to set the result true, and | |
973 // in the false case, where we fall thru the branch, we reset the result | |
974 // false. | |
975 | |
976 if (instr->arch_opcode() == kMipsTst) { | 968 if (instr->arch_opcode() == kMipsTst) { |
977 cc = FlagsConditionToConditionTst(condition); | 969 cc = FlagsConditionToConditionTst(condition); |
978 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 970 __ And(kScratchReg, i.InputRegister(0), i.InputOperand(1)); |
979 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); | 971 __ xori(result, zero_reg, 1); // Create 1 for true. |
980 __ li(result, Operand(1)); // In delay slot. | 972 if (IsMipsArchVariant(kMips32r6)) { |
981 | 973 if (cc == eq) { |
| 974 __ seleqz(result, result, kScratchReg); |
| 975 } else { |
| 976 __ selnez(result, result, kScratchReg); |
| 977 } |
| 978 } else { |
| 979 if (cc == eq) { |
| 980 __ Movn(result, zero_reg, kScratchReg); |
| 981 } else { |
| 982 __ Movz(result, zero_reg, kScratchReg); |
| 983 } |
| 984 } |
| 985 return; |
982 } else if (instr->arch_opcode() == kMipsAddOvf || | 986 } else if (instr->arch_opcode() == kMipsAddOvf || |
983 instr->arch_opcode() == kMipsSubOvf) { | 987 instr->arch_opcode() == kMipsSubOvf) { |
984 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow. | 988 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow. |
985 cc = FlagsConditionToConditionOvf(condition); | 989 cc = FlagsConditionToConditionOvf(condition); |
986 __ Branch(USE_DELAY_SLOT, &done, cc, kCompareReg, Operand(zero_reg)); | 990 // Return 1 on overflow. |
987 __ li(result, Operand(1)); // In delay slot. | 991 __ Slt(result, kCompareReg, Operand(zero_reg)); |
988 | 992 if (cc == ge) // Invert result on not overflow. |
| 993 __ xori(result, result, 1); |
| 994 return; |
989 } else if (instr->arch_opcode() == kMipsCmp) { | 995 } else if (instr->arch_opcode() == kMipsCmp) { |
990 Register left = i.InputRegister(0); | |
991 Operand right = i.InputOperand(1); | |
992 cc = FlagsConditionToConditionCmp(condition); | 996 cc = FlagsConditionToConditionCmp(condition); |
993 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); | 997 switch (cc) { |
994 __ li(result, Operand(1)); // In delay slot. | 998 case eq: |
995 | 999 case ne: { |
| 1000 Register left = i.InputRegister(0); |
| 1001 Operand right = i.InputOperand(1); |
| 1002 __ Subu(kScratchReg, left, right); |
| 1003 __ xori(result, zero_reg, 1); |
| 1004 if (IsMipsArchVariant(kMips32r6)) { |
| 1005 if (cc == eq) { |
| 1006 __ seleqz(result, result, kScratchReg); |
| 1007 } else { |
| 1008 __ selnez(result, result, kScratchReg); |
| 1009 } |
| 1010 } else { |
| 1011 if (cc == eq) { |
| 1012 __ Movn(result, zero_reg, kScratchReg); |
| 1013 } else { |
| 1014 __ Movz(result, zero_reg, kScratchReg); |
| 1015 } |
| 1016 } |
| 1017 } break; |
| 1018 case lt: |
| 1019 case ge: { |
| 1020 Register left = i.InputRegister(0); |
| 1021 Operand right = i.InputOperand(1); |
| 1022 __ Slt(result, left, right); |
| 1023 if (cc == ge) { |
| 1024 __ xori(result, result, 1); |
| 1025 } |
| 1026 } break; |
| 1027 case gt: |
| 1028 case le: { |
| 1029 Register left = i.InputRegister(1); |
| 1030 Operand right = i.InputOperand(0); |
| 1031 __ Slt(result, left, right); |
| 1032 if (cc == le) { |
| 1033 __ xori(result, result, 1); |
| 1034 } |
| 1035 } break; |
| 1036 case lo: |
| 1037 case hs: { |
| 1038 Register left = i.InputRegister(0); |
| 1039 Operand right = i.InputOperand(1); |
| 1040 __ Sltu(result, left, right); |
| 1041 if (cc == hs) { |
| 1042 __ xori(result, result, 1); |
| 1043 } |
| 1044 } break; |
| 1045 case hi: |
| 1046 case ls: { |
| 1047 Register left = i.InputRegister(1); |
| 1048 Operand right = i.InputOperand(0); |
| 1049 __ Sltu(result, left, right); |
| 1050 if (cc == ls) { |
| 1051 __ xori(result, result, 1); |
| 1052 } |
| 1053 } break; |
| 1054 default: |
| 1055 UNREACHABLE(); |
| 1056 } |
| 1057 return; |
996 } else if (instr->arch_opcode() == kMipsCmpD || | 1058 } else if (instr->arch_opcode() == kMipsCmpD || |
997 instr->arch_opcode() == kMipsCmpS) { | 1059 instr->arch_opcode() == kMipsCmpS) { |
998 FPURegister left = i.InputDoubleRegister(0); | 1060 FPURegister left = i.InputDoubleRegister(0); |
999 FPURegister right = i.InputDoubleRegister(1); | 1061 FPURegister right = i.InputDoubleRegister(1); |
1000 | |
1001 bool predicate; | 1062 bool predicate; |
1002 FPUCondition cc = FlagsConditionToConditionCmpFPU(predicate, condition); | 1063 FPUCondition cc = FlagsConditionToConditionCmpFPU(predicate, condition); |
1003 if (!IsMipsArchVariant(kMips32r6)) { | 1064 if (!IsMipsArchVariant(kMips32r6)) { |
1004 __ li(result, Operand(1)); | 1065 __ li(result, Operand(1)); |
1005 if (instr->arch_opcode() == kMipsCmpD) { | 1066 if (instr->arch_opcode() == kMipsCmpD) { |
1006 __ c(cc, D, left, right); | 1067 __ c(cc, D, left, right); |
1007 } else { | 1068 } else { |
1008 DCHECK(instr->arch_opcode() == kMipsCmpS); | 1069 DCHECK(instr->arch_opcode() == kMipsCmpS); |
1009 __ c(cc, S, left, right); | 1070 __ c(cc, S, left, right); |
1010 } | 1071 } |
(...skipping 14 matching lines...) Expand all Loading... |
1025 if (!predicate) // Toggle result for not equal. | 1086 if (!predicate) // Toggle result for not equal. |
1026 __ xori(result, result, 1); | 1087 __ xori(result, result, 1); |
1027 } | 1088 } |
1028 return; | 1089 return; |
1029 } else { | 1090 } else { |
1030 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", | 1091 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", |
1031 instr->arch_opcode()); | 1092 instr->arch_opcode()); |
1032 TRACE_UNIMPL(); | 1093 TRACE_UNIMPL(); |
1033 UNIMPLEMENTED(); | 1094 UNIMPLEMENTED(); |
1034 } | 1095 } |
1035 | |
1036 // Fallthrough case is the false materialization. | |
1037 __ bind(&false_value); | |
1038 __ li(result, Operand(0)); | |
1039 __ bind(&done); | |
1040 } | 1096 } |
1041 | 1097 |
1042 | 1098 |
1043 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { | 1099 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { |
1044 MipsOperandConverter i(this, instr); | 1100 MipsOperandConverter i(this, instr); |
1045 Register input = i.InputRegister(0); | 1101 Register input = i.InputRegister(0); |
1046 for (size_t index = 2; index < instr->InputCount(); index += 2) { | 1102 for (size_t index = 2; index < instr->InputCount(); index += 2) { |
1047 __ li(at, Operand(i.InputInt32(index + 0))); | 1103 __ li(at, Operand(i.InputInt32(index + 0))); |
1048 __ beq(input, at, GetLabel(i.InputRpo(index + 1))); | 1104 __ beq(input, at, GetLabel(i.InputRpo(index + 1))); |
1049 } | 1105 } |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1384 padding_size -= v8::internal::Assembler::kInstrSize; | 1440 padding_size -= v8::internal::Assembler::kInstrSize; |
1385 } | 1441 } |
1386 } | 1442 } |
1387 } | 1443 } |
1388 | 1444 |
1389 #undef __ | 1445 #undef __ |
1390 | 1446 |
1391 } // namespace compiler | 1447 } // namespace compiler |
1392 } // namespace internal | 1448 } // namespace internal |
1393 } // namespace v8 | 1449 } // namespace v8 |
OLD | NEW |