OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 855 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
866 | 866 |
867 | 867 |
868 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 868 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
869 // Nothing to do. | 869 // Nothing to do. |
870 } | 870 } |
871 | 871 |
872 | 872 |
873 void LCodeGen::DoModI(LModI* instr) { | 873 void LCodeGen::DoModI(LModI* instr) { |
874 if (instr->hydrogen()->HasPowerOf2Divisor()) { | 874 if (instr->hydrogen()->HasPowerOf2Divisor()) { |
875 Register dividend = ToRegister(instr->InputAt(0)); | 875 Register dividend = ToRegister(instr->InputAt(0)); |
| 876 Register result = ToRegister(instr->result()); |
876 | 877 |
877 int32_t divisor = | 878 int32_t divisor = |
878 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | 879 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
879 | 880 |
880 if (divisor < 0) divisor = -divisor; | 881 if (divisor < 0) divisor = -divisor; |
881 | 882 |
882 Label positive_dividend, done; | 883 Label positive_dividend, done; |
883 __ cmp(dividend, Operand(0)); | 884 __ cmp(dividend, Operand(0)); |
884 __ b(pl, &positive_dividend); | 885 __ b(pl, &positive_dividend); |
885 __ rsb(dividend, dividend, Operand(0)); | 886 __ rsb(result, dividend, Operand(0)); |
886 __ and_(dividend, dividend, Operand(divisor - 1)); | 887 __ and_(result, result, Operand(divisor - 1), SetCC); |
887 __ rsb(dividend, dividend, Operand(0), SetCC); | |
888 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 888 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
889 __ b(ne, &done); | 889 DeoptimizeIf(eq, instr->environment()); |
890 DeoptimizeIf(al, instr->environment()); | |
891 } else { | |
892 __ b(&done); | |
893 } | 890 } |
| 891 __ rsb(result, result, Operand(0)); |
| 892 __ b(&done); |
894 __ bind(&positive_dividend); | 893 __ bind(&positive_dividend); |
895 __ and_(dividend, dividend, Operand(divisor - 1)); | 894 __ and_(result, dividend, Operand(divisor - 1)); |
896 __ bind(&done); | 895 __ bind(&done); |
897 return; | 896 return; |
898 } | 897 } |
899 | 898 |
900 // These registers hold untagged 32 bit values. | 899 // These registers hold untagged 32 bit values. |
901 Register left = ToRegister(instr->InputAt(0)); | 900 Register left = ToRegister(instr->InputAt(0)); |
902 Register right = ToRegister(instr->InputAt(1)); | 901 Register right = ToRegister(instr->InputAt(1)); |
903 Register result = ToRegister(instr->result()); | 902 Register result = ToRegister(instr->result()); |
904 | 903 |
905 Register scratch = scratch0(); | 904 Register scratch = scratch0(); |
906 Register scratch2 = ToRegister(instr->TempAt(0)); | 905 Register scratch2 = ToRegister(instr->TempAt(0)); |
907 DwVfpRegister dividend = ToDoubleRegister(instr->TempAt(1)); | 906 DwVfpRegister dividend = ToDoubleRegister(instr->TempAt(1)); |
908 DwVfpRegister divisor = ToDoubleRegister(instr->TempAt(2)); | 907 DwVfpRegister divisor = ToDoubleRegister(instr->TempAt(2)); |
909 DwVfpRegister quotient = double_scratch0(); | 908 DwVfpRegister quotient = double_scratch0(); |
910 | 909 |
911 ASSERT(result.is(left)); | |
912 | |
913 ASSERT(!dividend.is(divisor)); | 910 ASSERT(!dividend.is(divisor)); |
914 ASSERT(!dividend.is(quotient)); | 911 ASSERT(!dividend.is(quotient)); |
915 ASSERT(!divisor.is(quotient)); | 912 ASSERT(!divisor.is(quotient)); |
916 ASSERT(!scratch.is(left)); | 913 ASSERT(!scratch.is(left)); |
917 ASSERT(!scratch.is(right)); | 914 ASSERT(!scratch.is(right)); |
918 ASSERT(!scratch.is(result)); | 915 ASSERT(!scratch.is(result)); |
919 | 916 |
920 Label done, vfp_modulo, both_positive, right_negative; | 917 Label done, vfp_modulo, both_positive, right_negative; |
921 | 918 |
922 // Check for x % 0. | 919 // Check for x % 0. |
923 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 920 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
924 __ cmp(right, Operand(0)); | 921 __ cmp(right, Operand(0)); |
925 DeoptimizeIf(eq, instr->environment()); | 922 DeoptimizeIf(eq, instr->environment()); |
926 } | 923 } |
927 | 924 |
| 925 __ Move(result, left); |
| 926 |
928 // (0 % x) must yield 0 (if x is finite, which is the case here). | 927 // (0 % x) must yield 0 (if x is finite, which is the case here). |
929 __ cmp(left, Operand(0)); | 928 __ cmp(left, Operand(0)); |
930 __ b(eq, &done); | 929 __ b(eq, &done); |
931 // Preload right in a vfp register. | 930 // Preload right in a vfp register. |
932 __ vmov(divisor.low(), right); | 931 __ vmov(divisor.low(), right); |
933 __ b(lt, &vfp_modulo); | 932 __ b(lt, &vfp_modulo); |
934 | 933 |
935 __ cmp(left, Operand(right)); | 934 __ cmp(left, Operand(right)); |
936 __ b(lt, &done); | 935 __ b(lt, &done); |
937 | 936 |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1113 __ CallStub(&stub); | 1112 __ CallStub(&stub); |
1114 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), | 1113 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), |
1115 0, | 1114 0, |
1116 Safepoint::kNoDeoptimizationIndex); | 1115 Safepoint::kNoDeoptimizationIndex); |
1117 // Overwrite the stored value of r0 with the result of the stub. | 1116 // Overwrite the stored value of r0 with the result of the stub. |
1118 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); | 1117 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); |
1119 } | 1118 } |
1120 | 1119 |
1121 | 1120 |
1122 void LCodeGen::DoMulI(LMulI* instr) { | 1121 void LCodeGen::DoMulI(LMulI* instr) { |
1123 ASSERT(instr->result()->Equals(instr->InputAt(0))); | |
1124 Register scratch = scratch0(); | 1122 Register scratch = scratch0(); |
1125 Register result = ToRegister(instr->result()); | 1123 Register result = ToRegister(instr->result()); |
| 1124 // Note that result may alias left. |
1126 Register left = ToRegister(instr->InputAt(0)); | 1125 Register left = ToRegister(instr->InputAt(0)); |
1127 LOperand* right_op = instr->InputAt(1); | 1126 LOperand* right_op = instr->InputAt(1); |
1128 | 1127 |
1129 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1128 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1130 bool bailout_on_minus_zero = | 1129 bool bailout_on_minus_zero = |
1131 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1130 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
1132 | 1131 |
1133 if (right_op->IsConstantOperand() && !can_overflow) { | 1132 if (right_op->IsConstantOperand() && !can_overflow) { |
1134 // Use optimized code for specific constants. | 1133 // Use optimized code for specific constants. |
1135 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1134 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); |
(...skipping 12 matching lines...) Expand all Loading... |
1148 case 0: | 1147 case 0: |
1149 if (bailout_on_minus_zero) { | 1148 if (bailout_on_minus_zero) { |
1150 // If left is strictly negative and the constant is null, the | 1149 // If left is strictly negative and the constant is null, the |
1151 // result is -0. Deoptimize if required, otherwise return 0. | 1150 // result is -0. Deoptimize if required, otherwise return 0. |
1152 __ cmp(left, Operand(0)); | 1151 __ cmp(left, Operand(0)); |
1153 DeoptimizeIf(mi, instr->environment()); | 1152 DeoptimizeIf(mi, instr->environment()); |
1154 } | 1153 } |
1155 __ mov(result, Operand(0)); | 1154 __ mov(result, Operand(0)); |
1156 break; | 1155 break; |
1157 case 1: | 1156 case 1: |
1158 // Nothing to do. | 1157 __ Move(result, left); |
1159 break; | 1158 break; |
1160 default: | 1159 default: |
1161 // Multiplying by powers of two and powers of two plus or minus | 1160 // Multiplying by powers of two and powers of two plus or minus |
1162 // one can be done faster with shifted operands. | 1161 // one can be done faster with shifted operands. |
1163 // For other constants we emit standard code. | 1162 // For other constants we emit standard code. |
1164 int32_t mask = constant >> 31; | 1163 int32_t mask = constant >> 31; |
1165 uint32_t constant_abs = (constant + mask) ^ mask; | 1164 uint32_t constant_abs = (constant + mask) ^ mask; |
1166 | 1165 |
1167 if (IsPowerOf2(constant_abs) || | 1166 if (IsPowerOf2(constant_abs) || |
1168 IsPowerOf2(constant_abs - 1) || | 1167 IsPowerOf2(constant_abs - 1) || |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1210 __ b(ne, &done); | 1209 __ b(ne, &done); |
1211 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); | 1210 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); |
1212 DeoptimizeIf(mi, instr->environment()); | 1211 DeoptimizeIf(mi, instr->environment()); |
1213 __ bind(&done); | 1212 __ bind(&done); |
1214 } | 1213 } |
1215 } | 1214 } |
1216 } | 1215 } |
1217 | 1216 |
1218 | 1217 |
1219 void LCodeGen::DoBitI(LBitI* instr) { | 1218 void LCodeGen::DoBitI(LBitI* instr) { |
1220 LOperand* left = instr->InputAt(0); | 1219 LOperand* left_op = instr->InputAt(0); |
1221 LOperand* right = instr->InputAt(1); | 1220 LOperand* right_op = instr->InputAt(1); |
1222 ASSERT(left->Equals(instr->result())); | 1221 ASSERT(left_op->IsRegister()); |
1223 ASSERT(left->IsRegister()); | 1222 Register left = ToRegister(left_op); |
1224 Register result = ToRegister(left); | 1223 Register result = ToRegister(instr->result()); |
1225 Operand right_operand(no_reg); | 1224 Operand right(no_reg); |
1226 | 1225 |
1227 if (right->IsStackSlot() || right->IsArgument()) { | 1226 if (right_op->IsStackSlot() || right_op->IsArgument()) { |
1228 Register right_reg = EmitLoadRegister(right, ip); | 1227 right = Operand(EmitLoadRegister(right_op, ip)); |
1229 right_operand = Operand(right_reg); | |
1230 } else { | 1228 } else { |
1231 ASSERT(right->IsRegister() || right->IsConstantOperand()); | 1229 ASSERT(right_op->IsRegister() || right_op->IsConstantOperand()); |
1232 right_operand = ToOperand(right); | 1230 right = ToOperand(right_op); |
1233 } | 1231 } |
1234 | 1232 |
1235 switch (instr->op()) { | 1233 switch (instr->op()) { |
1236 case Token::BIT_AND: | 1234 case Token::BIT_AND: |
1237 __ and_(result, ToRegister(left), right_operand); | 1235 __ and_(result, left, right); |
1238 break; | 1236 break; |
1239 case Token::BIT_OR: | 1237 case Token::BIT_OR: |
1240 __ orr(result, ToRegister(left), right_operand); | 1238 __ orr(result, left, right); |
1241 break; | 1239 break; |
1242 case Token::BIT_XOR: | 1240 case Token::BIT_XOR: |
1243 __ eor(result, ToRegister(left), right_operand); | 1241 __ eor(result, left, right); |
1244 break; | 1242 break; |
1245 default: | 1243 default: |
1246 UNREACHABLE(); | 1244 UNREACHABLE(); |
1247 break; | 1245 break; |
1248 } | 1246 } |
1249 } | 1247 } |
1250 | 1248 |
1251 | 1249 |
1252 void LCodeGen::DoShiftI(LShiftI* instr) { | 1250 void LCodeGen::DoShiftI(LShiftI* instr) { |
| 1251 // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so |
| 1252 // result may alias either of them. |
| 1253 LOperand* right_op = instr->InputAt(1); |
| 1254 Register left = ToRegister(instr->InputAt(0)); |
| 1255 Register result = ToRegister(instr->result()); |
1253 Register scratch = scratch0(); | 1256 Register scratch = scratch0(); |
1254 LOperand* left = instr->InputAt(0); | 1257 if (right_op->IsRegister()) { |
1255 LOperand* right = instr->InputAt(1); | 1258 // Mask the right_op operand. |
1256 ASSERT(left->Equals(instr->result())); | 1259 __ and_(scratch, ToRegister(right_op), Operand(0x1F)); |
1257 ASSERT(left->IsRegister()); | |
1258 Register result = ToRegister(left); | |
1259 if (right->IsRegister()) { | |
1260 // Mask the right operand. | |
1261 __ and_(scratch, ToRegister(right), Operand(0x1F)); | |
1262 switch (instr->op()) { | 1260 switch (instr->op()) { |
1263 case Token::SAR: | 1261 case Token::SAR: |
1264 __ mov(result, Operand(result, ASR, scratch)); | 1262 __ mov(result, Operand(left, ASR, scratch)); |
1265 break; | 1263 break; |
1266 case Token::SHR: | 1264 case Token::SHR: |
1267 if (instr->can_deopt()) { | 1265 if (instr->can_deopt()) { |
1268 __ mov(result, Operand(result, LSR, scratch), SetCC); | 1266 __ mov(result, Operand(left, LSR, scratch), SetCC); |
1269 DeoptimizeIf(mi, instr->environment()); | 1267 DeoptimizeIf(mi, instr->environment()); |
1270 } else { | 1268 } else { |
1271 __ mov(result, Operand(result, LSR, scratch)); | 1269 __ mov(result, Operand(left, LSR, scratch)); |
1272 } | 1270 } |
1273 break; | 1271 break; |
1274 case Token::SHL: | 1272 case Token::SHL: |
1275 __ mov(result, Operand(result, LSL, scratch)); | 1273 __ mov(result, Operand(left, LSL, scratch)); |
1276 break; | 1274 break; |
1277 default: | 1275 default: |
1278 UNREACHABLE(); | 1276 UNREACHABLE(); |
1279 break; | 1277 break; |
1280 } | 1278 } |
1281 } else { | 1279 } else { |
1282 int value = ToInteger32(LConstantOperand::cast(right)); | 1280 // Mask the right_op operand. |
| 1281 int value = ToInteger32(LConstantOperand::cast(right_op)); |
1283 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); | 1282 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); |
1284 switch (instr->op()) { | 1283 switch (instr->op()) { |
1285 case Token::SAR: | 1284 case Token::SAR: |
1286 if (shift_count != 0) { | 1285 if (shift_count != 0) { |
1287 __ mov(result, Operand(result, ASR, shift_count)); | 1286 __ mov(result, Operand(left, ASR, shift_count)); |
| 1287 } else { |
| 1288 __ Move(result, left); |
1288 } | 1289 } |
1289 break; | 1290 break; |
1290 case Token::SHR: | 1291 case Token::SHR: |
1291 if (shift_count == 0 && instr->can_deopt()) { | 1292 if (shift_count != 0) { |
1292 __ tst(result, Operand(0x80000000)); | 1293 __ mov(result, Operand(left, LSR, shift_count)); |
1293 DeoptimizeIf(ne, instr->environment()); | |
1294 } else { | 1294 } else { |
1295 __ mov(result, Operand(result, LSR, shift_count)); | 1295 if (instr->can_deopt()) { |
| 1296 __ tst(left, Operand(0x80000000)); |
| 1297 DeoptimizeIf(ne, instr->environment()); |
| 1298 } |
| 1299 __ Move(result, left); |
1296 } | 1300 } |
1297 break; | 1301 break; |
1298 case Token::SHL: | 1302 case Token::SHL: |
1299 if (shift_count != 0) { | 1303 if (shift_count != 0) { |
1300 __ mov(result, Operand(result, LSL, shift_count)); | 1304 __ mov(result, Operand(left, LSL, shift_count)); |
| 1305 } else { |
| 1306 __ Move(result, left); |
1301 } | 1307 } |
1302 break; | 1308 break; |
1303 default: | 1309 default: |
1304 UNREACHABLE(); | 1310 UNREACHABLE(); |
1305 break; | 1311 break; |
1306 } | 1312 } |
1307 } | 1313 } |
1308 } | 1314 } |
1309 | 1315 |
1310 | 1316 |
1311 void LCodeGen::DoSubI(LSubI* instr) { | 1317 void LCodeGen::DoSubI(LSubI* instr) { |
1312 LOperand* left = instr->InputAt(0); | 1318 LOperand* left = instr->InputAt(0); |
1313 LOperand* right = instr->InputAt(1); | 1319 LOperand* right = instr->InputAt(1); |
1314 ASSERT(left->Equals(instr->result())); | 1320 LOperand* result = instr->result(); |
1315 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1321 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1316 SBit set_cond = can_overflow ? SetCC : LeaveCC; | 1322 SBit set_cond = can_overflow ? SetCC : LeaveCC; |
1317 | 1323 |
1318 if (right->IsStackSlot() || right->IsArgument()) { | 1324 if (right->IsStackSlot() || right->IsArgument()) { |
1319 Register right_reg = EmitLoadRegister(right, ip); | 1325 Register right_reg = EmitLoadRegister(right, ip); |
1320 __ sub(ToRegister(left), ToRegister(left), Operand(right_reg), set_cond); | 1326 __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); |
1321 } else { | 1327 } else { |
1322 ASSERT(right->IsRegister() || right->IsConstantOperand()); | 1328 ASSERT(right->IsRegister() || right->IsConstantOperand()); |
1323 __ sub(ToRegister(left), ToRegister(left), ToOperand(right), set_cond); | 1329 __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); |
1324 } | 1330 } |
1325 | 1331 |
1326 if (can_overflow) { | 1332 if (can_overflow) { |
1327 DeoptimizeIf(vs, instr->environment()); | 1333 DeoptimizeIf(vs, instr->environment()); |
1328 } | 1334 } |
1329 } | 1335 } |
1330 | 1336 |
1331 | 1337 |
1332 void LCodeGen::DoConstantI(LConstantI* instr) { | 1338 void LCodeGen::DoConstantI(LConstantI* instr) { |
1333 ASSERT(instr->result()->IsRegister()); | 1339 ASSERT(instr->result()->IsRegister()); |
1334 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 1340 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
1335 } | 1341 } |
1336 | 1342 |
1337 | 1343 |
1338 void LCodeGen::DoConstantD(LConstantD* instr) { | 1344 void LCodeGen::DoConstantD(LConstantD* instr) { |
1339 ASSERT(instr->result()->IsDoubleRegister()); | 1345 ASSERT(instr->result()->IsDoubleRegister()); |
1340 DwVfpRegister result = ToDoubleRegister(instr->result()); | 1346 DwVfpRegister result = ToDoubleRegister(instr->result()); |
1341 double v = instr->value(); | 1347 double v = instr->value(); |
1342 __ vmov(result, v); | 1348 __ Vmov(result, v); |
1343 } | 1349 } |
1344 | 1350 |
1345 | 1351 |
1346 void LCodeGen::DoConstantT(LConstantT* instr) { | 1352 void LCodeGen::DoConstantT(LConstantT* instr) { |
1347 ASSERT(instr->result()->IsRegister()); | 1353 ASSERT(instr->result()->IsRegister()); |
1348 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 1354 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
1349 } | 1355 } |
1350 | 1356 |
1351 | 1357 |
1352 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 1358 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
(...skipping 28 matching lines...) Expand all Loading... |
1381 __ ldr(result, FieldMemOperand(result, Map::kBitField2Offset)); | 1387 __ ldr(result, FieldMemOperand(result, Map::kBitField2Offset)); |
1382 // Retrieve elements_kind from bit field 2. | 1388 // Retrieve elements_kind from bit field 2. |
1383 __ ubfx(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount); | 1389 __ ubfx(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount); |
1384 } | 1390 } |
1385 | 1391 |
1386 | 1392 |
1387 void LCodeGen::DoValueOf(LValueOf* instr) { | 1393 void LCodeGen::DoValueOf(LValueOf* instr) { |
1388 Register input = ToRegister(instr->InputAt(0)); | 1394 Register input = ToRegister(instr->InputAt(0)); |
1389 Register result = ToRegister(instr->result()); | 1395 Register result = ToRegister(instr->result()); |
1390 Register map = ToRegister(instr->TempAt(0)); | 1396 Register map = ToRegister(instr->TempAt(0)); |
1391 ASSERT(input.is(result)); | |
1392 Label done; | 1397 Label done; |
1393 | 1398 |
1394 // If the object is a smi return the object. | 1399 // If the object is a smi return the object. |
1395 __ JumpIfSmi(input, &done); | 1400 __ tst(input, Operand(kSmiTagMask)); |
| 1401 __ Move(result, input, eq); |
| 1402 __ b(eq, &done); |
1396 | 1403 |
1397 // If the object is not a value type, return the object. | 1404 // If the object is not a value type, return the object. |
1398 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); | 1405 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); |
| 1406 __ Move(result, input, ne); |
1399 __ b(ne, &done); | 1407 __ b(ne, &done); |
1400 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); | 1408 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); |
1401 | 1409 |
1402 __ bind(&done); | 1410 __ bind(&done); |
1403 } | 1411 } |
1404 | 1412 |
1405 | 1413 |
1406 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1414 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
1407 LOperand* input = instr->InputAt(0); | 1415 Register input = ToRegister(instr->InputAt(0)); |
1408 ASSERT(input->Equals(instr->result())); | 1416 Register result = ToRegister(instr->result()); |
1409 __ mvn(ToRegister(input), Operand(ToRegister(input))); | 1417 __ mvn(result, Operand(input)); |
1410 } | 1418 } |
1411 | 1419 |
1412 | 1420 |
1413 void LCodeGen::DoThrow(LThrow* instr) { | 1421 void LCodeGen::DoThrow(LThrow* instr) { |
1414 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); | 1422 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); |
1415 __ push(input_reg); | 1423 __ push(input_reg); |
1416 CallRuntime(Runtime::kThrow, 1, instr); | 1424 CallRuntime(Runtime::kThrow, 1, instr); |
1417 | 1425 |
1418 if (FLAG_debug_code) { | 1426 if (FLAG_debug_code) { |
1419 __ stop("Unreachable code."); | 1427 __ stop("Unreachable code."); |
1420 } | 1428 } |
1421 } | 1429 } |
1422 | 1430 |
1423 | 1431 |
1424 void LCodeGen::DoAddI(LAddI* instr) { | 1432 void LCodeGen::DoAddI(LAddI* instr) { |
1425 LOperand* left = instr->InputAt(0); | 1433 LOperand* left = instr->InputAt(0); |
1426 LOperand* right = instr->InputAt(1); | 1434 LOperand* right = instr->InputAt(1); |
1427 ASSERT(left->Equals(instr->result())); | 1435 LOperand* result = instr->result(); |
1428 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1436 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1429 SBit set_cond = can_overflow ? SetCC : LeaveCC; | 1437 SBit set_cond = can_overflow ? SetCC : LeaveCC; |
1430 | 1438 |
1431 if (right->IsStackSlot() || right->IsArgument()) { | 1439 if (right->IsStackSlot() || right->IsArgument()) { |
1432 Register right_reg = EmitLoadRegister(right, ip); | 1440 Register right_reg = EmitLoadRegister(right, ip); |
1433 __ add(ToRegister(left), ToRegister(left), Operand(right_reg), set_cond); | 1441 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); |
1434 } else { | 1442 } else { |
1435 ASSERT(right->IsRegister() || right->IsConstantOperand()); | 1443 ASSERT(right->IsRegister() || right->IsConstantOperand()); |
1436 __ add(ToRegister(left), ToRegister(left), ToOperand(right), set_cond); | 1444 __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); |
1437 } | 1445 } |
1438 | 1446 |
1439 if (can_overflow) { | 1447 if (can_overflow) { |
1440 DeoptimizeIf(vs, instr->environment()); | 1448 DeoptimizeIf(vs, instr->environment()); |
1441 } | 1449 } |
1442 } | 1450 } |
1443 | 1451 |
1444 | 1452 |
1445 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 1453 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
1446 DoubleRegister left = ToDoubleRegister(instr->InputAt(0)); | 1454 DoubleRegister left = ToDoubleRegister(instr->InputAt(0)); |
1447 DoubleRegister right = ToDoubleRegister(instr->InputAt(1)); | 1455 DoubleRegister right = ToDoubleRegister(instr->InputAt(1)); |
| 1456 DoubleRegister result = ToDoubleRegister(instr->result()); |
1448 switch (instr->op()) { | 1457 switch (instr->op()) { |
1449 case Token::ADD: | 1458 case Token::ADD: |
1450 __ vadd(left, left, right); | 1459 __ vadd(result, left, right); |
1451 break; | 1460 break; |
1452 case Token::SUB: | 1461 case Token::SUB: |
1453 __ vsub(left, left, right); | 1462 __ vsub(result, left, right); |
1454 break; | 1463 break; |
1455 case Token::MUL: | 1464 case Token::MUL: |
1456 __ vmul(left, left, right); | 1465 __ vmul(result, left, right); |
1457 break; | 1466 break; |
1458 case Token::DIV: | 1467 case Token::DIV: |
1459 __ vdiv(left, left, right); | 1468 __ vdiv(result, left, right); |
1460 break; | 1469 break; |
1461 case Token::MOD: { | 1470 case Token::MOD: { |
1462 // Save r0-r3 on the stack. | 1471 // Save r0-r3 on the stack. |
1463 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); | 1472 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); |
1464 | 1473 |
1465 __ PrepareCallCFunction(0, 2, scratch0()); | 1474 __ PrepareCallCFunction(0, 2, scratch0()); |
1466 __ SetCallCDoubleArguments(left, right); | 1475 __ SetCallCDoubleArguments(left, right); |
1467 __ CallCFunction( | 1476 __ CallCFunction( |
1468 ExternalReference::double_fp_operation(Token::MOD, isolate()), | 1477 ExternalReference::double_fp_operation(Token::MOD, isolate()), |
1469 0, 2); | 1478 0, 2); |
1470 // Move the result in the double result register. | 1479 // Move the result in the double result register. |
1471 __ GetCFunctionDoubleResult(ToDoubleRegister(instr->result())); | 1480 __ GetCFunctionDoubleResult(result); |
1472 | 1481 |
1473 // Restore r0-r3. | 1482 // Restore r0-r3. |
1474 __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); | 1483 __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); |
1475 break; | 1484 break; |
1476 } | 1485 } |
1477 default: | 1486 default: |
1478 UNREACHABLE(); | 1487 UNREACHABLE(); |
1479 break; | 1488 break; |
1480 } | 1489 } |
1481 } | 1490 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1554 __ b(eq, true_label); | 1563 __ b(eq, true_label); |
1555 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 1564 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
1556 __ cmp(reg, ip); | 1565 __ cmp(reg, ip); |
1557 __ b(eq, false_label); | 1566 __ b(eq, false_label); |
1558 __ cmp(reg, Operand(0)); | 1567 __ cmp(reg, Operand(0)); |
1559 __ b(eq, false_label); | 1568 __ b(eq, false_label); |
1560 __ JumpIfSmi(reg, true_label); | 1569 __ JumpIfSmi(reg, true_label); |
1561 | 1570 |
1562 // Test double values. Zero and NaN are false. | 1571 // Test double values. Zero and NaN are false. |
1563 Label call_stub; | 1572 Label call_stub; |
1564 DoubleRegister dbl_scratch = d0; | 1573 DoubleRegister dbl_scratch = double_scratch0(); |
1565 Register scratch = scratch0(); | 1574 Register scratch = scratch0(); |
1566 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1575 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
1567 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 1576 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
1568 __ cmp(scratch, Operand(ip)); | 1577 __ cmp(scratch, Operand(ip)); |
1569 __ b(ne, &call_stub); | 1578 __ b(ne, &call_stub); |
1570 __ sub(ip, reg, Operand(kHeapObjectTag)); | 1579 __ sub(ip, reg, Operand(kHeapObjectTag)); |
1571 __ vldr(dbl_scratch, ip, HeapNumber::kValueOffset); | 1580 __ vldr(dbl_scratch, ip, HeapNumber::kValueOffset); |
1572 __ VFPCompareAndLoadFlags(dbl_scratch, 0.0, scratch); | 1581 __ VFPCompareAndLoadFlags(dbl_scratch, 0.0, scratch); |
1573 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); | 1582 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); |
1574 __ b(ne, false_label); | 1583 __ b(ne, false_label); |
(...skipping 997 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2572 __ add(length, length, Operand(1)); | 2581 __ add(length, length, Operand(1)); |
2573 __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2)); | 2582 __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2)); |
2574 } | 2583 } |
2575 | 2584 |
2576 | 2585 |
2577 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { | 2586 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { |
2578 Register elements = ToRegister(instr->elements()); | 2587 Register elements = ToRegister(instr->elements()); |
2579 Register key = EmitLoadRegister(instr->key(), scratch0()); | 2588 Register key = EmitLoadRegister(instr->key(), scratch0()); |
2580 Register result = ToRegister(instr->result()); | 2589 Register result = ToRegister(instr->result()); |
2581 Register scratch = scratch0(); | 2590 Register scratch = scratch0(); |
2582 ASSERT(result.is(elements)); | |
2583 | 2591 |
2584 // Load the result. | 2592 // Load the result. |
2585 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); | 2593 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); |
2586 __ ldr(result, FieldMemOperand(scratch, FixedArray::kHeaderSize)); | 2594 __ ldr(result, FieldMemOperand(scratch, FixedArray::kHeaderSize)); |
2587 | 2595 |
2588 // Check for the hole value. | 2596 // Check for the hole value. |
2589 if (instr->hydrogen()->RequiresHoleCheck()) { | 2597 if (instr->hydrogen()->RequiresHoleCheck()) { |
2590 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); | 2598 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
2591 __ cmp(result, scratch); | 2599 __ cmp(result, scratch); |
2592 DeoptimizeIf(eq, instr->environment()); | 2600 DeoptimizeIf(eq, instr->environment()); |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2892 ASSERT(ToRegister(instr->result()).is(r0)); | 2900 ASSERT(ToRegister(instr->result()).is(r0)); |
2893 __ mov(r1, Operand(instr->function())); | 2901 __ mov(r1, Operand(instr->function())); |
2894 CallKnownFunction(instr->function(), | 2902 CallKnownFunction(instr->function(), |
2895 instr->arity(), | 2903 instr->arity(), |
2896 instr, | 2904 instr, |
2897 CALL_AS_METHOD); | 2905 CALL_AS_METHOD); |
2898 } | 2906 } |
2899 | 2907 |
2900 | 2908 |
2901 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 2909 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
2902 ASSERT(instr->InputAt(0)->Equals(instr->result())); | |
2903 Register input = ToRegister(instr->InputAt(0)); | 2910 Register input = ToRegister(instr->InputAt(0)); |
| 2911 Register result = ToRegister(instr->result()); |
2904 Register scratch = scratch0(); | 2912 Register scratch = scratch0(); |
2905 | 2913 |
2906 // Deoptimize if not a heap number. | 2914 // Deoptimize if not a heap number. |
2907 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 2915 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
2908 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 2916 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
2909 __ cmp(scratch, Operand(ip)); | 2917 __ cmp(scratch, Operand(ip)); |
2910 DeoptimizeIf(ne, instr->environment()); | 2918 DeoptimizeIf(ne, instr->environment()); |
2911 | 2919 |
2912 Label done; | 2920 Label done; |
2913 Register exponent = scratch0(); | 2921 Register exponent = scratch0(); |
2914 scratch = no_reg; | 2922 scratch = no_reg; |
2915 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 2923 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
2916 // Check the sign of the argument. If the argument is positive, just | 2924 // Check the sign of the argument. If the argument is positive, just |
2917 // return it. We do not need to patch the stack since |input| and | 2925 // return it. |
2918 // |result| are the same register and |input| would be restored | |
2919 // unchanged by popping safepoint registers. | |
2920 __ tst(exponent, Operand(HeapNumber::kSignMask)); | 2926 __ tst(exponent, Operand(HeapNumber::kSignMask)); |
| 2927 // Move the input to the result if necessary. |
| 2928 __ Move(result, input); |
2921 __ b(eq, &done); | 2929 __ b(eq, &done); |
2922 | 2930 |
2923 // Input is negative. Reverse its sign. | 2931 // Input is negative. Reverse its sign. |
2924 // Preserve the value of all registers. | 2932 // Preserve the value of all registers. |
2925 { | 2933 { |
2926 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 2934 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
2927 | 2935 |
2928 // Registers were saved at the safepoint, so we can use | 2936 // Registers were saved at the safepoint, so we can use |
2929 // many scratch registers. | 2937 // many scratch registers. |
2930 Register tmp1 = input.is(r1) ? r0 : r1; | 2938 Register tmp1 = input.is(r1) ? r0 : r1; |
(...skipping 19 matching lines...) Expand all Loading... |
2950 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 2958 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
2951 | 2959 |
2952 __ bind(&allocated); | 2960 __ bind(&allocated); |
2953 // exponent: floating point exponent value. | 2961 // exponent: floating point exponent value. |
2954 // tmp1: allocated heap number. | 2962 // tmp1: allocated heap number. |
2955 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask)); | 2963 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask)); |
2956 __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset)); | 2964 __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset)); |
2957 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); | 2965 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); |
2958 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); | 2966 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); |
2959 | 2967 |
2960 __ StoreToSafepointRegisterSlot(tmp1, input); | 2968 __ StoreToSafepointRegisterSlot(tmp1, result); |
2961 } | 2969 } |
2962 | 2970 |
2963 __ bind(&done); | 2971 __ bind(&done); |
2964 } | 2972 } |
2965 | 2973 |
2966 | 2974 |
2967 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 2975 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
2968 Register input = ToRegister(instr->InputAt(0)); | 2976 Register input = ToRegister(instr->InputAt(0)); |
| 2977 Register result = ToRegister(instr->result()); |
2969 __ cmp(input, Operand(0)); | 2978 __ cmp(input, Operand(0)); |
| 2979 __ Move(result, input, pl); |
2970 // We can make rsb conditional because the previous cmp instruction | 2980 // We can make rsb conditional because the previous cmp instruction |
2971 // will clear the V (overflow) flag and rsb won't set this flag | 2981 // will clear the V (overflow) flag and rsb won't set this flag |
2972 // if input is positive. | 2982 // if input is positive. |
2973 __ rsb(input, input, Operand(0), SetCC, mi); | 2983 __ rsb(result, input, Operand(0), SetCC, mi); |
2974 // Deoptimize on overflow. | 2984 // Deoptimize on overflow. |
2975 DeoptimizeIf(vs, instr->environment()); | 2985 DeoptimizeIf(vs, instr->environment()); |
2976 } | 2986 } |
2977 | 2987 |
2978 | 2988 |
2979 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 2989 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
2980 // Class for deferred case. | 2990 // Class for deferred case. |
2981 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 2991 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
2982 public: | 2992 public: |
2983 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 2993 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
2984 LUnaryMathOperation* instr) | 2994 LUnaryMathOperation* instr) |
2985 : LDeferredCode(codegen), instr_(instr) { } | 2995 : LDeferredCode(codegen), instr_(instr) { } |
2986 virtual void Generate() { | 2996 virtual void Generate() { |
2987 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 2997 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
2988 } | 2998 } |
2989 private: | 2999 private: |
2990 LUnaryMathOperation* instr_; | 3000 LUnaryMathOperation* instr_; |
2991 }; | 3001 }; |
2992 | 3002 |
2993 ASSERT(instr->InputAt(0)->Equals(instr->result())); | |
2994 Representation r = instr->hydrogen()->value()->representation(); | 3003 Representation r = instr->hydrogen()->value()->representation(); |
2995 if (r.IsDouble()) { | 3004 if (r.IsDouble()) { |
2996 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0)); | 3005 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0)); |
2997 __ vabs(input, input); | 3006 DwVfpRegister result = ToDoubleRegister(instr->result()); |
| 3007 __ vabs(result, input); |
2998 } else if (r.IsInteger32()) { | 3008 } else if (r.IsInteger32()) { |
2999 EmitIntegerMathAbs(instr); | 3009 EmitIntegerMathAbs(instr); |
3000 } else { | 3010 } else { |
3001 // Representation is tagged. | 3011 // Representation is tagged. |
3002 DeferredMathAbsTaggedHeapNumber* deferred = | 3012 DeferredMathAbsTaggedHeapNumber* deferred = |
3003 new DeferredMathAbsTaggedHeapNumber(this, instr); | 3013 new DeferredMathAbsTaggedHeapNumber(this, instr); |
3004 Register input = ToRegister(instr->InputAt(0)); | 3014 Register input = ToRegister(instr->InputAt(0)); |
3005 // Smi check. | 3015 // Smi check. |
3006 __ JumpIfNotSmi(input, deferred->entry()); | 3016 __ JumpIfNotSmi(input, deferred->entry()); |
3007 // If smi, handle it directly. | 3017 // If smi, handle it directly. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3065 } | 3075 } |
3066 | 3076 |
3067 // The following conversion will not work with numbers | 3077 // The following conversion will not work with numbers |
3068 // outside of ]-2^32, 2^32[. | 3078 // outside of ]-2^32, 2^32[. |
3069 __ cmp(scratch2, Operand(HeapNumber::kExponentBias + 32)); | 3079 __ cmp(scratch2, Operand(HeapNumber::kExponentBias + 32)); |
3070 DeoptimizeIf(ge, instr->environment()); | 3080 DeoptimizeIf(ge, instr->environment()); |
3071 | 3081 |
3072 // Save the original sign for later comparison. | 3082 // Save the original sign for later comparison. |
3073 __ and_(scratch2, scratch1, Operand(HeapNumber::kSignMask)); | 3083 __ and_(scratch2, scratch1, Operand(HeapNumber::kSignMask)); |
3074 | 3084 |
3075 __ vmov(double_scratch0(), 0.5); | 3085 __ Vmov(double_scratch0(), 0.5); |
3076 __ vadd(input, input, double_scratch0()); | 3086 __ vadd(input, input, double_scratch0()); |
3077 | 3087 |
3078 // Check sign of the result: if the sign changed, the input | 3088 // Check sign of the result: if the sign changed, the input |
3079 // value was in ]0.5, 0[ and the result should be -0. | 3089 // value was in ]0.5, 0[ and the result should be -0. |
3080 __ vmov(scratch1, input.high()); | 3090 __ vmov(scratch1, input.high()); |
3081 __ eor(scratch1, scratch1, Operand(scratch2), SetCC); | 3091 __ eor(scratch1, scratch1, Operand(scratch2), SetCC); |
3082 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3092 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3083 DeoptimizeIf(mi, instr->environment()); | 3093 DeoptimizeIf(mi, instr->environment()); |
3084 } else { | 3094 } else { |
3085 __ mov(result, Operand(0), LeaveCC, mi); | 3095 __ mov(result, Operand(0), LeaveCC, mi); |
(...skipping 16 matching lines...) Expand all Loading... |
3102 __ vmov(scratch1, input.high()); | 3112 __ vmov(scratch1, input.high()); |
3103 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | 3113 __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
3104 DeoptimizeIf(ne, instr->environment()); | 3114 DeoptimizeIf(ne, instr->environment()); |
3105 } | 3115 } |
3106 __ bind(&done); | 3116 __ bind(&done); |
3107 } | 3117 } |
3108 | 3118 |
3109 | 3119 |
3110 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 3120 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
3111 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); | 3121 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
3112 ASSERT(ToDoubleRegister(instr->result()).is(input)); | 3122 DoubleRegister result = ToDoubleRegister(instr->result()); |
3113 __ vsqrt(input, input); | 3123 __ vsqrt(result, input); |
3114 } | 3124 } |
3115 | 3125 |
3116 | 3126 |
3117 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { | 3127 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
3118 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); | 3128 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
3119 Register scratch = scratch0(); | 3129 DoubleRegister result = ToDoubleRegister(instr->result()); |
3120 SwVfpRegister single_scratch = double_scratch0().low(); | |
3121 DoubleRegister double_scratch = double_scratch0(); | |
3122 ASSERT(ToDoubleRegister(instr->result()).is(input)); | |
3123 | |
3124 // Add +0 to convert -0 to +0. | 3130 // Add +0 to convert -0 to +0. |
3125 __ mov(scratch, Operand(0)); | 3131 __ vadd(result, input, kDoubleRegZero); |
3126 __ vmov(single_scratch, scratch); | 3132 __ vsqrt(result, result); |
3127 __ vcvt_f64_s32(double_scratch, single_scratch); | |
3128 __ vadd(input, input, double_scratch); | |
3129 __ vsqrt(input, input); | |
3130 } | 3133 } |
3131 | 3134 |
3132 | 3135 |
3133 void LCodeGen::DoPower(LPower* instr) { | 3136 void LCodeGen::DoPower(LPower* instr) { |
3134 LOperand* left = instr->InputAt(0); | 3137 LOperand* left = instr->InputAt(0); |
3135 LOperand* right = instr->InputAt(1); | 3138 LOperand* right = instr->InputAt(1); |
3136 Register scratch = scratch0(); | 3139 Register scratch = scratch0(); |
3137 DoubleRegister result_reg = ToDoubleRegister(instr->result()); | 3140 DoubleRegister result_reg = ToDoubleRegister(instr->result()); |
3138 Representation exponent_type = instr->hydrogen()->right()->representation(); | 3141 Representation exponent_type = instr->hydrogen()->right()->representation(); |
3139 if (exponent_type.IsDouble()) { | 3142 if (exponent_type.IsDouble()) { |
(...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3718 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); | 3721 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); |
3719 __ SmiTag(reg, SetCC); | 3722 __ SmiTag(reg, SetCC); |
3720 __ b(vs, deferred->entry()); | 3723 __ b(vs, deferred->entry()); |
3721 __ bind(deferred->exit()); | 3724 __ bind(deferred->exit()); |
3722 } | 3725 } |
3723 | 3726 |
3724 | 3727 |
3725 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { | 3728 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { |
3726 Label slow; | 3729 Label slow; |
3727 Register reg = ToRegister(instr->InputAt(0)); | 3730 Register reg = ToRegister(instr->InputAt(0)); |
3728 DoubleRegister dbl_scratch = d0; | 3731 DoubleRegister dbl_scratch = double_scratch0(); |
3729 SwVfpRegister flt_scratch = s0; | 3732 SwVfpRegister flt_scratch = dbl_scratch.low(); |
3730 | 3733 |
3731 // Preserve the value of all registers. | 3734 // Preserve the value of all registers. |
3732 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 3735 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
3733 | 3736 |
3734 // There was overflow, so bits 30 and 31 of the original integer | 3737 // There was overflow, so bits 30 and 31 of the original integer |
3735 // disagree. Try to allocate a heap number in new space and store | 3738 // disagree. Try to allocate a heap number in new space and store |
3736 // the value in there. If that fails, call the runtime system. | 3739 // the value in there. If that fails, call the runtime system. |
3737 Label done; | 3740 Label done; |
3738 __ SmiUntag(reg); | 3741 __ SmiUntag(reg); |
3739 __ eor(reg, reg, Operand(0x80000000)); | 3742 __ eor(reg, reg, Operand(0x80000000)); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3828 __ SmiUntag(ToRegister(input)); | 3831 __ SmiUntag(ToRegister(input)); |
3829 } | 3832 } |
3830 } | 3833 } |
3831 | 3834 |
3832 | 3835 |
3833 void LCodeGen::EmitNumberUntagD(Register input_reg, | 3836 void LCodeGen::EmitNumberUntagD(Register input_reg, |
3834 DoubleRegister result_reg, | 3837 DoubleRegister result_reg, |
3835 bool deoptimize_on_undefined, | 3838 bool deoptimize_on_undefined, |
3836 LEnvironment* env) { | 3839 LEnvironment* env) { |
3837 Register scratch = scratch0(); | 3840 Register scratch = scratch0(); |
3838 SwVfpRegister flt_scratch = s0; | 3841 SwVfpRegister flt_scratch = double_scratch0().low(); |
3839 ASSERT(!result_reg.is(d0)); | 3842 ASSERT(!result_reg.is(double_scratch0())); |
3840 | 3843 |
3841 Label load_smi, heap_number, done; | 3844 Label load_smi, heap_number, done; |
3842 | 3845 |
3843 // Smi check. | 3846 // Smi check. |
3844 __ JumpIfSmi(input_reg, &load_smi); | 3847 __ JumpIfSmi(input_reg, &load_smi); |
3845 | 3848 |
3846 // Heap number map check. | 3849 // Heap number map check. |
3847 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 3850 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
3848 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 3851 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
3849 __ cmp(scratch, Operand(ip)); | 3852 __ cmp(scratch, Operand(ip)); |
(...skipping 751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4601 ASSERT(osr_pc_offset_ == -1); | 4604 ASSERT(osr_pc_offset_ == -1); |
4602 osr_pc_offset_ = masm()->pc_offset(); | 4605 osr_pc_offset_ = masm()->pc_offset(); |
4603 } | 4606 } |
4604 | 4607 |
4605 | 4608 |
4606 | 4609 |
4607 | 4610 |
4608 #undef __ | 4611 #undef __ |
4609 | 4612 |
4610 } } // namespace v8::internal | 4613 } } // namespace v8::internal |
OLD | NEW |