Chromium Code Reviews| 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/mips/macro-assembler-mips.h" | 9 #include "src/mips/macro-assembler-mips.h" |
| 10 #include "src/scopes.h" | 10 #include "src/scopes.h" |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 193 }; | 193 }; |
| 194 | 194 |
| 195 | 195 |
| 196 class OutOfLineCeil final : public OutOfLineRound { | 196 class OutOfLineCeil final : public OutOfLineRound { |
| 197 public: | 197 public: |
| 198 OutOfLineCeil(CodeGenerator* gen, DoubleRegister result) | 198 OutOfLineCeil(CodeGenerator* gen, DoubleRegister result) |
| 199 : OutOfLineRound(gen, result) {} | 199 : OutOfLineRound(gen, result) {} |
| 200 }; | 200 }; |
| 201 | 201 |
| 202 | 202 |
| 203 Condition FlagsConditionToConditionCmp(FlagsCondition condition) { | 203 Condition FlagsConditionToConditionCmp(bool& predicate, |
|
paul.l...
2015/09/03 22:27:39
It took me some staring at the code to figure out
paul.l...
2015/09/04 03:33:58
OK, I think we both overcomplicated this. When I s
| |
| 204 FlagsCondition condition) { | |
| 204 switch (condition) { | 205 switch (condition) { |
| 205 case kEqual: | 206 case kEqual: |
| 207 predicate = true; | |
| 206 return eq; | 208 return eq; |
| 207 case kNotEqual: | 209 case kNotEqual: |
| 210 predicate = false; | |
| 208 return ne; | 211 return ne; |
| 209 case kSignedLessThan: | 212 case kSignedLessThan: |
| 213 predicate = true; | |
| 210 return lt; | 214 return lt; |
| 211 case kSignedGreaterThanOrEqual: | 215 case kSignedGreaterThanOrEqual: |
| 216 predicate = false; | |
| 212 return ge; | 217 return ge; |
| 213 case kSignedLessThanOrEqual: | 218 case kSignedLessThanOrEqual: |
| 219 predicate = false; | |
| 214 return le; | 220 return le; |
| 215 case kSignedGreaterThan: | 221 case kSignedGreaterThan: |
| 222 predicate = true; | |
| 216 return gt; | 223 return gt; |
| 217 case kUnsignedLessThan: | 224 case kUnsignedLessThan: |
| 225 predicate = true; | |
| 218 return lo; | 226 return lo; |
| 219 case kUnsignedGreaterThanOrEqual: | 227 case kUnsignedGreaterThanOrEqual: |
| 228 predicate = false; | |
| 220 return hs; | 229 return hs; |
| 221 case kUnsignedLessThanOrEqual: | 230 case kUnsignedLessThanOrEqual: |
| 231 predicate = false; | |
| 222 return ls; | 232 return ls; |
| 223 case kUnsignedGreaterThan: | 233 case kUnsignedGreaterThan: |
| 234 predicate = true; | |
| 224 return hi; | 235 return hi; |
| 225 case kUnorderedEqual: | 236 case kUnorderedEqual: |
| 226 case kUnorderedNotEqual: | 237 case kUnorderedNotEqual: |
| 238 predicate = true; | |
| 227 break; | 239 break; |
| 228 default: | 240 default: |
| 241 predicate = true; | |
| 229 break; | 242 break; |
| 230 } | 243 } |
| 231 UNREACHABLE(); | 244 UNREACHABLE(); |
| 232 return kNoCondition; | 245 return kNoCondition; |
| 233 } | 246 } |
| 234 | 247 |
| 235 | 248 |
| 236 Condition FlagsConditionToConditionTst(FlagsCondition condition) { | 249 Condition FlagsConditionToConditionTst(bool& predicate, |
| 250 FlagsCondition condition) { | |
| 237 switch (condition) { | 251 switch (condition) { |
| 238 case kNotEqual: | 252 case kNotEqual: |
| 253 predicate = false; | |
| 239 return ne; | 254 return ne; |
| 240 case kEqual: | 255 case kEqual: |
| 256 predicate = true; | |
| 241 return eq; | 257 return eq; |
| 242 default: | 258 default: |
| 259 predicate = true; | |
| 243 break; | 260 break; |
| 244 } | 261 } |
| 245 UNREACHABLE(); | 262 UNREACHABLE(); |
| 246 return kNoCondition; | 263 return kNoCondition; |
| 247 } | 264 } |
| 248 | 265 |
| 249 | 266 |
| 250 Condition FlagsConditionToConditionOvf(FlagsCondition condition) { | 267 Condition FlagsConditionToConditionOvf(bool& predicate, |
| 268 FlagsCondition condition) { | |
| 251 switch (condition) { | 269 switch (condition) { |
| 252 case kOverflow: | 270 case kOverflow: |
| 271 predicate = true; | |
| 253 return lt; | 272 return lt; |
| 254 case kNotOverflow: | 273 case kNotOverflow: |
| 274 predicate = false; | |
| 255 return ge; | 275 return ge; |
| 256 default: | 276 default: |
| 277 predicate = true; | |
| 257 break; | 278 break; |
| 258 } | 279 } |
| 259 UNREACHABLE(); | 280 UNREACHABLE(); |
| 260 return kNoCondition; | 281 return kNoCondition; |
| 261 } | 282 } |
| 262 | 283 |
| 263 FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate, | 284 FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate, |
| 264 FlagsCondition condition) { | 285 FlagsCondition condition) { |
| 265 switch (condition) { | 286 switch (condition) { |
| 266 case kEqual: | 287 case kEqual: |
| (...skipping 616 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 883 return false; | 904 return false; |
| 884 } | 905 } |
| 885 | 906 |
| 886 | 907 |
| 887 // Assembles branches after an instruction. | 908 // Assembles branches after an instruction. |
| 888 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | 909 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
| 889 MipsOperandConverter i(this, instr); | 910 MipsOperandConverter i(this, instr); |
| 890 Label* tlabel = branch->true_label; | 911 Label* tlabel = branch->true_label; |
| 891 Label* flabel = branch->false_label; | 912 Label* flabel = branch->false_label; |
| 892 Condition cc = kNoCondition; | 913 Condition cc = kNoCondition; |
| 893 | 914 bool predicate; |
| 894 // MIPS does not have condition code flags, so compare and branch are | 915 // MIPS does not have condition code flags, so compare and branch are |
| 895 // implemented differently than on the other arch's. The compare operations | 916 // implemented differently than on the other arch's. The compare operations |
| 896 // emit mips pseudo-instructions, which are handled here by branch | 917 // emit mips pseudo-instructions, which are handled here by branch |
| 897 // instructions that do the actual comparison. Essential that the input | 918 // instructions that do the actual comparison. Essential that the input |
| 898 // registers to compare pseudo-op are not modified before this branch op, as | 919 // registers to compare pseudo-op are not modified before this branch op, as |
| 899 // they are tested here. | 920 // they are tested here. |
| 900 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were | 921 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were |
| 901 // not separated by other instructions. | 922 // not separated by other instructions. |
| 902 | 923 |
| 903 if (instr->arch_opcode() == kMipsTst) { | 924 if (instr->arch_opcode() == kMipsTst) { |
| 904 cc = FlagsConditionToConditionTst(branch->condition); | 925 cc = FlagsConditionToConditionTst(predicate, branch->condition); |
| 905 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 926 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
| 906 __ Branch(tlabel, cc, at, Operand(zero_reg)); | 927 __ Branch(tlabel, cc, at, Operand(zero_reg)); |
| 907 } else if (instr->arch_opcode() == kMipsAddOvf || | 928 } else if (instr->arch_opcode() == kMipsAddOvf || |
| 908 instr->arch_opcode() == kMipsSubOvf) { | 929 instr->arch_opcode() == kMipsSubOvf) { |
| 909 // kMipsAddOvf, SubOvf emit negative result to 'kCompareReg' on overflow. | 930 // kMipsAddOvf, SubOvf emit negative result to 'kCompareReg' on overflow. |
| 910 cc = FlagsConditionToConditionOvf(branch->condition); | 931 cc = FlagsConditionToConditionOvf(predicate, branch->condition); |
| 911 __ Branch(tlabel, cc, kCompareReg, Operand(zero_reg)); | 932 __ Branch(tlabel, cc, kCompareReg, Operand(zero_reg)); |
| 912 } else if (instr->arch_opcode() == kMipsCmp) { | 933 } else if (instr->arch_opcode() == kMipsCmp) { |
| 913 cc = FlagsConditionToConditionCmp(branch->condition); | 934 cc = FlagsConditionToConditionCmp(predicate, branch->condition); |
| 914 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); | 935 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); |
| 915 } else if (instr->arch_opcode() == kMipsCmpS) { | 936 } else if (instr->arch_opcode() == kMipsCmpS) { |
| 916 if (!convertCondition(branch->condition, cc)) { | 937 if (!convertCondition(branch->condition, cc)) { |
| 917 UNSUPPORTED_COND(kMips64CmpS, branch->condition); | 938 UNSUPPORTED_COND(kMips64CmpS, branch->condition); |
| 918 } | 939 } |
| 919 __ BranchF32(tlabel, NULL, cc, i.InputSingleRegister(0), | 940 __ BranchF32(tlabel, NULL, cc, i.InputSingleRegister(0), |
| 920 i.InputSingleRegister(1)); | 941 i.InputSingleRegister(1)); |
| 921 } else if (instr->arch_opcode() == kMipsCmpD) { | 942 } else if (instr->arch_opcode() == kMipsCmpD) { |
| 922 if (!convertCondition(branch->condition, cc)) { | 943 if (!convertCondition(branch->condition, cc)) { |
| 923 UNSUPPORTED_COND(kMips64CmpD, branch->condition); | 944 UNSUPPORTED_COND(kMips64CmpD, branch->condition); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 943 FlagsCondition condition) { | 964 FlagsCondition condition) { |
| 944 MipsOperandConverter i(this, instr); | 965 MipsOperandConverter i(this, instr); |
| 945 Label done; | 966 Label done; |
| 946 | 967 |
| 947 // Materialize a full 32-bit 1 or 0 value. The result register is always the | 968 // Materialize a full 32-bit 1 or 0 value. The result register is always the |
| 948 // last output of the instruction. | 969 // last output of the instruction. |
| 949 Label false_value; | 970 Label false_value; |
| 950 DCHECK_NE(0u, instr->OutputCount()); | 971 DCHECK_NE(0u, instr->OutputCount()); |
| 951 Register result = i.OutputRegister(instr->OutputCount() - 1); | 972 Register result = i.OutputRegister(instr->OutputCount() - 1); |
| 952 Condition cc = kNoCondition; | 973 Condition cc = kNoCondition; |
| 953 | 974 bool predicate; |
| 954 // MIPS does not have condition code flags, so compare and branch are | 975 // MIPS does not have condition code flags, so compare and branch are |
| 955 // implemented differently than on the other arch's. The compare operations | 976 // implemented differently than on the other arch's. The compare operations |
| 956 // emit mips psuedo-instructions, which are checked and handled here. | 977 // emit mips psuedo-instructions, which are checked and handled here. |
| 957 | 978 |
| 958 // For materializations, we use delay slot to set the result true, and | |
| 959 // in the false case, where we fall thru the branch, we reset the result | |
| 960 // false. | |
| 961 | |
| 962 if (instr->arch_opcode() == kMipsTst) { | 979 if (instr->arch_opcode() == kMipsTst) { |
| 963 cc = FlagsConditionToConditionTst(condition); | 980 cc = FlagsConditionToConditionTst(predicate, condition); |
| 964 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 981 __ And(kScratchReg, i.InputRegister(0), i.InputOperand(1)); |
| 965 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); | 982 __ xori(kScratchReg2, zero_reg, 1); // Create 1 for true. |
|
paul.l...
2015/09/03 22:27:39
Prefer li(kScratchReg2, 1) here, for readability.
| |
| 966 __ li(result, Operand(1)); // In delay slot. | 983 if (!IsMipsArchVariant(kMips32r6)) { |
|
paul.l...
2015/09/03 22:27:39
I find that 'negative-conditions' -- if (not-somet
| |
| 967 | 984 if (predicate) { |
| 985 __ Movn(result, zero_reg, kScratchReg); | |
| 986 __ Movz(result, kScratchReg2, kScratchReg); | |
|
paul.l...
2015/09/03 22:27:39
If you refactor the code a bit, you can get by wit
paul.l...
2015/09/04 03:33:58
Never mind the last paragraph of prev comment (quo
| |
| 987 } else { | |
| 988 __ Movz(result, zero_reg, kScratchReg); | |
| 989 __ Movn(result, kScratchReg2, kScratchReg); | |
| 990 } | |
| 991 } else { | |
| 992 if (predicate) { | |
| 993 __ seleqz(result, kScratchReg2, kScratchReg); | |
| 994 } else { | |
| 995 __ selnez(result, kScratchReg2, kScratchReg); | |
| 996 } | |
| 997 } | |
| 998 return; | |
| 968 } else if (instr->arch_opcode() == kMipsAddOvf || | 999 } else if (instr->arch_opcode() == kMipsAddOvf || |
| 969 instr->arch_opcode() == kMipsSubOvf) { | 1000 instr->arch_opcode() == kMipsSubOvf) { |
| 970 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow. | 1001 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow. |
| 971 cc = FlagsConditionToConditionOvf(condition); | 1002 cc = FlagsConditionToConditionOvf(predicate, condition); |
| 972 __ Branch(USE_DELAY_SLOT, &done, cc, kCompareReg, Operand(zero_reg)); | 1003 // Return 1 on overflow. |
| 973 __ li(result, Operand(1)); // In delay slot. | 1004 __ Slt(result, kCompareReg, Operand(zero_reg)); |
| 974 | 1005 if (!predicate) // Invert result on not overflow. |
| 1006 __ xori(result, result, 1); | |
| 1007 return; | |
| 975 } else if (instr->arch_opcode() == kMipsCmp) { | 1008 } else if (instr->arch_opcode() == kMipsCmp) { |
| 976 Register left = i.InputRegister(0); | 1009 cc = FlagsConditionToConditionCmp(predicate, condition); |
| 977 Operand right = i.InputOperand(1); | 1010 switch (cc) { |
| 978 cc = FlagsConditionToConditionCmp(condition); | 1011 case eq: |
| 979 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); | 1012 case ne: { |
| 980 __ li(result, Operand(1)); // In delay slot. | 1013 Register left = i.InputRegister(0); |
| 981 | 1014 Operand right = i.InputOperand(1); |
| 1015 __ Subu(kScratchReg, left, right); | |
| 1016 __ xori(kScratchReg2, zero_reg, 1); | |
| 1017 if (!IsMipsArchVariant(kMips32r6)) { | |
| 1018 if (predicate) { | |
| 1019 __ Movn(result, zero_reg, kScratchReg); | |
| 1020 __ Movz(result, kScratchReg2, kScratchReg); | |
| 1021 } else { | |
| 1022 __ Movz(result, zero_reg, kScratchReg); | |
| 1023 __ Movn(result, kScratchReg2, kScratchReg); | |
| 1024 } | |
| 1025 } else { | |
| 1026 if (predicate) { | |
| 1027 __ seleqz(result, kScratchReg2, kScratchReg); | |
| 1028 } else { | |
| 1029 __ selnez(result, kScratchReg2, kScratchReg); | |
| 1030 } | |
| 1031 } | |
| 1032 } break; | |
| 1033 case lt: | |
| 1034 case ge: { | |
| 1035 Register left = i.InputRegister(0); | |
| 1036 Operand right = i.InputOperand(1); | |
| 1037 __ Slt(result, left, right); | |
| 1038 if (!predicate) { | |
| 1039 __ xori(result, result, 1); | |
| 1040 } | |
| 1041 } break; | |
| 1042 case gt: | |
| 1043 case le: { | |
| 1044 Register left = i.InputRegister(1); | |
| 1045 Operand right = i.InputOperand(0); | |
| 1046 __ Slt(result, left, right); | |
| 1047 if (!predicate) { | |
| 1048 __ xori(result, result, 1); | |
| 1049 } | |
| 1050 } break; | |
| 1051 case lo: | |
| 1052 case hs: { | |
| 1053 Register left = i.InputRegister(0); | |
| 1054 Operand right = i.InputOperand(1); | |
| 1055 __ Sltu(result, left, right); | |
| 1056 if (!predicate) { | |
| 1057 __ xori(result, result, 1); | |
| 1058 } | |
| 1059 } break; | |
| 1060 case hi: | |
| 1061 case ls: { | |
| 1062 Register left = i.InputRegister(1); | |
| 1063 Operand right = i.InputOperand(0); | |
| 1064 __ Sltu(result, left, right); | |
| 1065 if (!predicate) { | |
| 1066 __ xori(result, result, 1); | |
| 1067 } | |
| 1068 } break; | |
| 1069 default: | |
| 1070 UNREACHABLE(); | |
| 1071 } | |
| 1072 return; | |
| 982 } else if (instr->arch_opcode() == kMipsCmpD || | 1073 } else if (instr->arch_opcode() == kMipsCmpD || |
| 983 instr->arch_opcode() == kMipsCmpS) { | 1074 instr->arch_opcode() == kMipsCmpS) { |
| 984 FPURegister left = i.InputDoubleRegister(0); | 1075 FPURegister left = i.InputDoubleRegister(0); |
| 985 FPURegister right = i.InputDoubleRegister(1); | 1076 FPURegister right = i.InputDoubleRegister(1); |
| 986 | 1077 |
| 987 bool predicate; | |
| 988 FPUCondition cc = FlagsConditionToConditionCmpFPU(predicate, condition); | 1078 FPUCondition cc = FlagsConditionToConditionCmpFPU(predicate, condition); |
| 989 if (!IsMipsArchVariant(kMips32r6)) { | 1079 if (!IsMipsArchVariant(kMips32r6)) { |
| 990 __ li(result, Operand(1)); | 1080 __ li(result, Operand(1)); |
| 991 if (instr->arch_opcode() == kMipsCmpD) { | 1081 if (instr->arch_opcode() == kMipsCmpD) { |
| 992 __ c(cc, D, left, right); | 1082 __ c(cc, D, left, right); |
| 993 } else { | 1083 } else { |
| 994 DCHECK(instr->arch_opcode() == kMipsCmpS); | 1084 DCHECK(instr->arch_opcode() == kMipsCmpS); |
| 995 __ c(cc, S, left, right); | 1085 __ c(cc, S, left, right); |
| 996 } | 1086 } |
| 997 if (predicate) { | 1087 if (predicate) { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1011 if (!predicate) // Toggle result for not equal. | 1101 if (!predicate) // Toggle result for not equal. |
| 1012 __ xori(result, result, 1); | 1102 __ xori(result, result, 1); |
| 1013 } | 1103 } |
| 1014 return; | 1104 return; |
| 1015 } else { | 1105 } else { |
| 1016 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", | 1106 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", |
| 1017 instr->arch_opcode()); | 1107 instr->arch_opcode()); |
| 1018 TRACE_UNIMPL(); | 1108 TRACE_UNIMPL(); |
| 1019 UNIMPLEMENTED(); | 1109 UNIMPLEMENTED(); |
| 1020 } | 1110 } |
| 1021 | |
| 1022 // Fallthrough case is the false materialization. | |
| 1023 __ bind(&false_value); | |
| 1024 __ li(result, Operand(0)); | |
| 1025 __ bind(&done); | |
| 1026 } | 1111 } |
| 1027 | 1112 |
| 1028 | 1113 |
| 1029 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { | 1114 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { |
| 1030 MipsOperandConverter i(this, instr); | 1115 MipsOperandConverter i(this, instr); |
| 1031 Register input = i.InputRegister(0); | 1116 Register input = i.InputRegister(0); |
| 1032 for (size_t index = 2; index < instr->InputCount(); index += 2) { | 1117 for (size_t index = 2; index < instr->InputCount(); index += 2) { |
| 1033 __ li(at, Operand(i.InputInt32(index + 0))); | 1118 __ li(at, Operand(i.InputInt32(index + 0))); |
| 1034 __ beq(input, at, GetLabel(i.InputRpo(index + 1))); | 1119 __ beq(input, at, GetLabel(i.InputRpo(index + 1))); |
| 1035 } | 1120 } |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1367 } | 1452 } |
| 1368 } | 1453 } |
| 1369 } | 1454 } |
| 1370 } | 1455 } |
| 1371 | 1456 |
| 1372 #undef __ | 1457 #undef __ |
| 1373 | 1458 |
| 1374 } // namespace compiler | 1459 } // namespace compiler |
| 1375 } // namespace internal | 1460 } // namespace internal |
| 1376 } // namespace v8 | 1461 } // namespace v8 |
| OLD | NEW |