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_(dividend, 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 } | 890 } |
891 __ rsb(result, dividend, Operand(0)); | |
892 __ b(&done); | |
892 __ bind(&positive_dividend); | 893 __ bind(&positive_dividend); |
893 __ and_(dividend, dividend, Operand(divisor - 1)); | 894 __ and_(result, dividend, Operand(divisor - 1)); |
894 __ bind(&done); | 895 __ bind(&done); |
895 return; | 896 return; |
896 } | 897 } |
897 | 898 |
898 // These registers hold untagged 32 bit values. | 899 // These registers hold untagged 32 bit values. |
899 Register left = ToRegister(instr->InputAt(0)); | 900 Register left = ToRegister(instr->InputAt(0)); |
900 Register right = ToRegister(instr->InputAt(1)); | 901 Register right = ToRegister(instr->InputAt(1)); |
901 Register result = ToRegister(instr->result()); | 902 Register result = ToRegister(instr->result()); |
902 | 903 |
903 Register scratch = scratch0(); | 904 Register scratch = scratch0(); |
904 Register scratch2 = ToRegister(instr->TempAt(0)); | 905 Register scratch2 = ToRegister(instr->TempAt(0)); |
905 DwVfpRegister dividend = ToDoubleRegister(instr->TempAt(1)); | 906 DwVfpRegister dividend = ToDoubleRegister(instr->TempAt(1)); |
906 DwVfpRegister divisor = ToDoubleRegister(instr->TempAt(2)); | 907 DwVfpRegister divisor = ToDoubleRegister(instr->TempAt(2)); |
907 DwVfpRegister quotient = double_scratch0(); | 908 DwVfpRegister quotient = double_scratch0(); |
908 | 909 |
909 ASSERT(result.is(left)); | |
910 | |
911 ASSERT(!dividend.is(divisor)); | 910 ASSERT(!dividend.is(divisor)); |
912 ASSERT(!dividend.is(quotient)); | 911 ASSERT(!dividend.is(quotient)); |
913 ASSERT(!divisor.is(quotient)); | 912 ASSERT(!divisor.is(quotient)); |
914 ASSERT(!scratch.is(left)); | 913 ASSERT(!scratch.is(left)); |
915 ASSERT(!scratch.is(right)); | 914 ASSERT(!scratch.is(right)); |
916 ASSERT(!scratch.is(result)); | 915 ASSERT(!scratch.is(result)); |
917 | 916 |
918 Label done, vfp_modulo, both_positive, right_negative; | 917 Label done, vfp_modulo, both_positive, right_negative; |
919 | 918 |
920 // Check for x % 0. | 919 // Check for x % 0. |
921 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 920 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
922 __ cmp(right, Operand(0)); | 921 __ cmp(right, Operand(0)); |
923 DeoptimizeIf(eq, instr->environment()); | 922 DeoptimizeIf(eq, instr->environment()); |
924 } | 923 } |
925 | 924 |
925 __ Move(result, left); | |
926 | |
926 // (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). |
927 __ cmp(left, Operand(0)); | 928 __ cmp(left, Operand(0)); |
928 __ b(eq, &done); | 929 __ b(eq, &done); |
929 // Preload right in a vfp register. | 930 // Preload right in a vfp register. |
930 __ vmov(divisor.low(), right); | 931 __ vmov(divisor.low(), right); |
931 __ b(lt, &vfp_modulo); | 932 __ b(lt, &vfp_modulo); |
932 | 933 |
933 __ cmp(left, Operand(right)); | 934 __ cmp(left, Operand(right)); |
934 __ b(lt, &done); | 935 __ b(lt, &done); |
935 | 936 |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1111 __ CallStub(&stub); | 1112 __ CallStub(&stub); |
1112 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), | 1113 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), |
1113 0, | 1114 0, |
1114 Safepoint::kNoDeoptimizationIndex); | 1115 Safepoint::kNoDeoptimizationIndex); |
1115 // 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. |
1116 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); | 1117 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); |
1117 } | 1118 } |
1118 | 1119 |
1119 | 1120 |
1120 void LCodeGen::DoMulI(LMulI* instr) { | 1121 void LCodeGen::DoMulI(LMulI* instr) { |
1121 ASSERT(instr->result()->Equals(instr->InputAt(0))); | |
1122 Register scratch = scratch0(); | 1122 Register scratch = scratch0(); |
Søren Thygesen Gjesse
2011/06/16 09:38:07
Maybe add a comment that result might alias left (
Alexandre
2011/06/16 12:58:48
Done.
| |
1123 Register result = ToRegister(instr->result()); | 1123 Register result = ToRegister(instr->result()); |
1124 Register left = ToRegister(instr->InputAt(0)); | 1124 Register left = ToRegister(instr->InputAt(0)); |
1125 LOperand* right_op = instr->InputAt(1); | 1125 LOperand* right_op = instr->InputAt(1); |
1126 | 1126 |
1127 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1127 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1128 bool bailout_on_minus_zero = | 1128 bool bailout_on_minus_zero = |
1129 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1129 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
1130 | 1130 |
1131 if (right_op->IsConstantOperand() && !can_overflow) { | 1131 if (right_op->IsConstantOperand() && !can_overflow) { |
1132 // Use optimized code for specific constants. | 1132 // Use optimized code for specific constants. |
(...skipping 13 matching lines...) Expand all Loading... | |
1146 case 0: | 1146 case 0: |
1147 if (bailout_on_minus_zero) { | 1147 if (bailout_on_minus_zero) { |
1148 // If left is strictly negative and the constant is null, the | 1148 // If left is strictly negative and the constant is null, the |
1149 // result is -0. Deoptimize if required, otherwise return 0. | 1149 // result is -0. Deoptimize if required, otherwise return 0. |
1150 __ cmp(left, Operand(0)); | 1150 __ cmp(left, Operand(0)); |
1151 DeoptimizeIf(mi, instr->environment()); | 1151 DeoptimizeIf(mi, instr->environment()); |
1152 } | 1152 } |
1153 __ mov(result, Operand(0)); | 1153 __ mov(result, Operand(0)); |
1154 break; | 1154 break; |
1155 case 1: | 1155 case 1: |
1156 // Nothing to do. | 1156 __ Move(result, left); |
1157 break; | 1157 break; |
1158 default: | 1158 default: |
1159 // Multiplying by powers of two and powers of two plus or minus | 1159 // Multiplying by powers of two and powers of two plus or minus |
1160 // one can be done faster with shifted operands. | 1160 // one can be done faster with shifted operands. |
1161 // For other constants we emit standard code. | 1161 // For other constants we emit standard code. |
1162 int32_t mask = constant >> 31; | 1162 int32_t mask = constant >> 31; |
1163 uint32_t constant_abs = (constant + mask) ^ mask; | 1163 uint32_t constant_abs = (constant + mask) ^ mask; |
1164 | 1164 |
1165 if (IsPowerOf2(constant_abs) || | 1165 if (IsPowerOf2(constant_abs) || |
1166 IsPowerOf2(constant_abs - 1) || | 1166 IsPowerOf2(constant_abs - 1) || |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1208 __ b(ne, &done); | 1208 __ b(ne, &done); |
1209 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); | 1209 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); |
1210 DeoptimizeIf(mi, instr->environment()); | 1210 DeoptimizeIf(mi, instr->environment()); |
1211 __ bind(&done); | 1211 __ bind(&done); |
1212 } | 1212 } |
1213 } | 1213 } |
1214 } | 1214 } |
1215 | 1215 |
1216 | 1216 |
1217 void LCodeGen::DoBitI(LBitI* instr) { | 1217 void LCodeGen::DoBitI(LBitI* instr) { |
1218 LOperand* left = instr->InputAt(0); | 1218 LOperand* left_op = instr->InputAt(0); |
1219 LOperand* right = instr->InputAt(1); | 1219 LOperand* right_op = instr->InputAt(1); |
1220 ASSERT(left->Equals(instr->result())); | 1220 ASSERT(left_op->IsRegister()); |
1221 ASSERT(left->IsRegister()); | 1221 Register left = ToRegister(left_op); |
1222 Register result = ToRegister(left); | 1222 Register result = ToRegister(instr->result()); |
1223 Operand right_operand(no_reg); | 1223 Operand right(no_reg); |
1224 | 1224 |
1225 if (right->IsStackSlot() || right->IsArgument()) { | 1225 if (right_op->IsStackSlot() || right_op->IsArgument()) { |
1226 Register right_reg = EmitLoadRegister(right, ip); | 1226 right = Operand(EmitLoadRegister(right_op, ip)); |
1227 right_operand = Operand(right_reg); | |
1228 } else { | 1227 } else { |
1229 ASSERT(right->IsRegister() || right->IsConstantOperand()); | 1228 ASSERT(right_op->IsRegister() || right_op->IsConstantOperand()); |
1230 right_operand = ToOperand(right); | 1229 right = ToOperand(right_op); |
1231 } | 1230 } |
1232 | 1231 |
1233 switch (instr->op()) { | 1232 switch (instr->op()) { |
1234 case Token::BIT_AND: | 1233 case Token::BIT_AND: |
1235 __ and_(result, ToRegister(left), right_operand); | 1234 __ and_(result, left, right); |
1236 break; | 1235 break; |
1237 case Token::BIT_OR: | 1236 case Token::BIT_OR: |
1238 __ orr(result, ToRegister(left), right_operand); | 1237 __ orr(result, left, right); |
1239 break; | 1238 break; |
1240 case Token::BIT_XOR: | 1239 case Token::BIT_XOR: |
1241 __ eor(result, ToRegister(left), right_operand); | 1240 __ eor(result, left, right); |
1242 break; | 1241 break; |
1243 default: | 1242 default: |
1244 UNREACHABLE(); | 1243 UNREACHABLE(); |
1245 break; | 1244 break; |
1246 } | 1245 } |
1247 } | 1246 } |
1248 | 1247 |
1249 | 1248 |
1250 void LCodeGen::DoShiftI(LShiftI* instr) { | 1249 void LCodeGen::DoShiftI(LShiftI* instr) { |
Søren Thygesen Gjesse
2011/06/16 09:38:07
Please add a comment that both left and right are
Alexandre
2011/06/16 12:58:48
Done.
| |
1250 LOperand* right_op = instr->InputAt(1); | |
1251 Register left = ToRegister(instr->InputAt(0)); | |
1252 Register result = ToRegister(instr->result()); | |
1251 Register scratch = scratch0(); | 1253 Register scratch = scratch0(); |
1252 LOperand* left = instr->InputAt(0); | 1254 if (right_op->IsRegister()) { |
1253 LOperand* right = instr->InputAt(1); | 1255 // Mask the right_op operand. |
1254 ASSERT(left->Equals(instr->result())); | 1256 __ and_(scratch, ToRegister(right_op), Operand(0x1F)); |
1255 ASSERT(left->IsRegister()); | |
1256 Register result = ToRegister(left); | |
1257 if (right->IsRegister()) { | |
1258 // Mask the right operand. | |
1259 __ and_(scratch, ToRegister(right), Operand(0x1F)); | |
1260 switch (instr->op()) { | 1257 switch (instr->op()) { |
1261 case Token::SAR: | 1258 case Token::SAR: |
1262 __ mov(result, Operand(result, ASR, scratch)); | 1259 __ mov(result, Operand(left, ASR, scratch)); |
1263 break; | 1260 break; |
1264 case Token::SHR: | 1261 case Token::SHR: |
1265 if (instr->can_deopt()) { | 1262 if (instr->can_deopt()) { |
1266 __ mov(result, Operand(result, LSR, scratch), SetCC); | 1263 __ mov(result, Operand(left, LSR, scratch), SetCC); |
1267 DeoptimizeIf(mi, instr->environment()); | 1264 DeoptimizeIf(mi, instr->environment()); |
1268 } else { | 1265 } else { |
1269 __ mov(result, Operand(result, LSR, scratch)); | 1266 __ mov(result, Operand(left, LSR, scratch)); |
1270 } | 1267 } |
1271 break; | 1268 break; |
1272 case Token::SHL: | 1269 case Token::SHL: |
1273 __ mov(result, Operand(result, LSL, scratch)); | 1270 __ mov(result, Operand(left, LSL, scratch)); |
1274 break; | 1271 break; |
1275 default: | 1272 default: |
1276 UNREACHABLE(); | 1273 UNREACHABLE(); |
1277 break; | 1274 break; |
1278 } | 1275 } |
1279 } else { | 1276 } else { |
1280 int value = ToInteger32(LConstantOperand::cast(right)); | 1277 // Mask the right_op operand. |
1278 int value = ToInteger32(LConstantOperand::cast(right_op)); | |
1281 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); | 1279 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); |
1282 switch (instr->op()) { | 1280 switch (instr->op()) { |
1283 case Token::SAR: | 1281 case Token::SAR: |
1284 if (shift_count != 0) { | 1282 if (shift_count != 0) { |
1285 __ mov(result, Operand(result, ASR, shift_count)); | 1283 __ mov(result, Operand(left, ASR, shift_count)); |
1286 } | 1284 } |
1287 break; | 1285 break; |
1288 case Token::SHR: | 1286 case Token::SHR: |
1289 if (shift_count == 0 && instr->can_deopt()) { | 1287 if (shift_count == 0 && instr->can_deopt()) { |
1290 __ tst(result, Operand(0x80000000)); | 1288 __ tst(left, Operand(0x80000000)); |
1291 DeoptimizeIf(ne, instr->environment()); | 1289 DeoptimizeIf(ne, instr->environment()); |
1292 } else { | 1290 } else { |
1293 __ mov(result, Operand(result, LSR, shift_count)); | 1291 __ mov(result, Operand(left, LSR, shift_count)); |
1294 } | 1292 } |
1295 break; | 1293 break; |
1296 case Token::SHL: | 1294 case Token::SHL: |
1297 if (shift_count != 0) { | 1295 if (shift_count != 0) { |
1298 __ mov(result, Operand(result, LSL, shift_count)); | 1296 __ mov(result, Operand(left, LSL, shift_count)); |
1299 } | 1297 } |
1300 break; | 1298 break; |
1301 default: | 1299 default: |
1302 UNREACHABLE(); | 1300 UNREACHABLE(); |
1303 break; | 1301 break; |
1304 } | 1302 } |
1303 if (shift_count == 0) __ Move(result, left); | |
Søren Thygesen Gjesse
2011/06/16 09:38:07
I think this will be easier to read if you mode th
Alexandre
2011/06/16 12:58:48
The code for SHR was not optimal when ((shift_coun
| |
1305 } | 1304 } |
1306 } | 1305 } |
1307 | 1306 |
1308 | 1307 |
1309 void LCodeGen::DoSubI(LSubI* instr) { | 1308 void LCodeGen::DoSubI(LSubI* instr) { |
1310 LOperand* left = instr->InputAt(0); | 1309 LOperand* left = instr->InputAt(0); |
1311 LOperand* right = instr->InputAt(1); | 1310 LOperand* right = instr->InputAt(1); |
1312 ASSERT(left->Equals(instr->result())); | 1311 LOperand* result = instr->result(); |
1313 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1312 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1314 SBit set_cond = can_overflow ? SetCC : LeaveCC; | 1313 SBit set_cond = can_overflow ? SetCC : LeaveCC; |
1315 | 1314 |
1316 if (right->IsStackSlot() || right->IsArgument()) { | 1315 if (right->IsStackSlot() || right->IsArgument()) { |
1317 Register right_reg = EmitLoadRegister(right, ip); | 1316 Register right_reg = EmitLoadRegister(right, ip); |
1318 __ sub(ToRegister(left), ToRegister(left), Operand(right_reg), set_cond); | 1317 __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); |
1319 } else { | 1318 } else { |
1320 ASSERT(right->IsRegister() || right->IsConstantOperand()); | 1319 ASSERT(right->IsRegister() || right->IsConstantOperand()); |
1321 __ sub(ToRegister(left), ToRegister(left), ToOperand(right), set_cond); | 1320 __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); |
1322 } | 1321 } |
1323 | 1322 |
1324 if (can_overflow) { | 1323 if (can_overflow) { |
1325 DeoptimizeIf(vs, instr->environment()); | 1324 DeoptimizeIf(vs, instr->environment()); |
1326 } | 1325 } |
1327 } | 1326 } |
1328 | 1327 |
1329 | 1328 |
1330 void LCodeGen::DoConstantI(LConstantI* instr) { | 1329 void LCodeGen::DoConstantI(LConstantI* instr) { |
1331 ASSERT(instr->result()->IsRegister()); | 1330 ASSERT(instr->result()->IsRegister()); |
1332 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 1331 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
1333 } | 1332 } |
1334 | 1333 |
1335 | 1334 |
1336 void LCodeGen::DoConstantD(LConstantD* instr) { | 1335 void LCodeGen::DoConstantD(LConstantD* instr) { |
1337 ASSERT(instr->result()->IsDoubleRegister()); | 1336 ASSERT(instr->result()->IsDoubleRegister()); |
1338 DwVfpRegister result = ToDoubleRegister(instr->result()); | 1337 DwVfpRegister result = ToDoubleRegister(instr->result()); |
1339 double v = instr->value(); | 1338 double v = instr->value(); |
1340 __ vmov(result, v); | 1339 __ Vmov(result, v); |
1341 } | 1340 } |
1342 | 1341 |
1343 | 1342 |
1344 void LCodeGen::DoConstantT(LConstantT* instr) { | 1343 void LCodeGen::DoConstantT(LConstantT* instr) { |
1345 ASSERT(instr->result()->IsRegister()); | 1344 ASSERT(instr->result()->IsRegister()); |
1346 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 1345 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
1347 } | 1346 } |
1348 | 1347 |
1349 | 1348 |
1350 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 1349 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
(...skipping 14 matching lines...) Expand all Loading... | |
1365 Register result = ToRegister(instr->result()); | 1364 Register result = ToRegister(instr->result()); |
1366 Register array = ToRegister(instr->InputAt(0)); | 1365 Register array = ToRegister(instr->InputAt(0)); |
1367 __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset)); | 1366 __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset)); |
1368 } | 1367 } |
1369 | 1368 |
1370 | 1369 |
1371 void LCodeGen::DoValueOf(LValueOf* instr) { | 1370 void LCodeGen::DoValueOf(LValueOf* instr) { |
1372 Register input = ToRegister(instr->InputAt(0)); | 1371 Register input = ToRegister(instr->InputAt(0)); |
1373 Register result = ToRegister(instr->result()); | 1372 Register result = ToRegister(instr->result()); |
1374 Register map = ToRegister(instr->TempAt(0)); | 1373 Register map = ToRegister(instr->TempAt(0)); |
1375 ASSERT(input.is(result)); | |
1376 Label done; | 1374 Label done; |
1377 | 1375 |
1378 // If the object is a smi return the object. | 1376 // If the object is a smi return the object. |
1379 __ tst(input, Operand(kSmiTagMask)); | 1377 __ tst(input, Operand(kSmiTagMask)); |
1378 __ Move(result, input); | |
1380 __ b(eq, &done); | 1379 __ b(eq, &done); |
1381 | 1380 |
1382 // If the object is not a value type, return the object. | 1381 // If the object is not a value type, return the object. |
1383 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); | 1382 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); |
1384 __ b(ne, &done); | 1383 __ b(ne, &done); |
1385 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); | 1384 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); |
1386 | 1385 |
1387 __ bind(&done); | 1386 __ bind(&done); |
1388 } | 1387 } |
1389 | 1388 |
1390 | 1389 |
1391 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1390 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
1392 LOperand* input = instr->InputAt(0); | 1391 Register input = ToRegister(instr->InputAt(0)); |
1393 ASSERT(input->Equals(instr->result())); | 1392 Register result = ToRegister(instr->result()); |
1394 __ mvn(ToRegister(input), Operand(ToRegister(input))); | 1393 __ mvn(input, Operand(input)); |
1395 } | 1394 } |
1396 | 1395 |
1397 | 1396 |
1398 void LCodeGen::DoThrow(LThrow* instr) { | 1397 void LCodeGen::DoThrow(LThrow* instr) { |
1399 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); | 1398 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); |
1400 __ push(input_reg); | 1399 __ push(input_reg); |
1401 CallRuntime(Runtime::kThrow, 1, instr); | 1400 CallRuntime(Runtime::kThrow, 1, instr); |
1402 | 1401 |
1403 if (FLAG_debug_code) { | 1402 if (FLAG_debug_code) { |
1404 __ stop("Unreachable code."); | 1403 __ stop("Unreachable code."); |
1405 } | 1404 } |
1406 } | 1405 } |
1407 | 1406 |
1408 | 1407 |
1409 void LCodeGen::DoAddI(LAddI* instr) { | 1408 void LCodeGen::DoAddI(LAddI* instr) { |
1410 LOperand* left = instr->InputAt(0); | 1409 LOperand* left = instr->InputAt(0); |
1411 LOperand* right = instr->InputAt(1); | 1410 LOperand* right = instr->InputAt(1); |
1412 ASSERT(left->Equals(instr->result())); | 1411 LOperand* result = instr->result(); |
1413 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1412 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1414 SBit set_cond = can_overflow ? SetCC : LeaveCC; | 1413 SBit set_cond = can_overflow ? SetCC : LeaveCC; |
1415 | 1414 |
1416 if (right->IsStackSlot() || right->IsArgument()) { | 1415 if (right->IsStackSlot() || right->IsArgument()) { |
1417 Register right_reg = EmitLoadRegister(right, ip); | 1416 Register right_reg = EmitLoadRegister(right, ip); |
1418 __ add(ToRegister(left), ToRegister(left), Operand(right_reg), set_cond); | 1417 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); |
1419 } else { | 1418 } else { |
1420 ASSERT(right->IsRegister() || right->IsConstantOperand()); | 1419 ASSERT(right->IsRegister() || right->IsConstantOperand()); |
1421 __ add(ToRegister(left), ToRegister(left), ToOperand(right), set_cond); | 1420 __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); |
1422 } | 1421 } |
1423 | 1422 |
1424 if (can_overflow) { | 1423 if (can_overflow) { |
1425 DeoptimizeIf(vs, instr->environment()); | 1424 DeoptimizeIf(vs, instr->environment()); |
1426 } | 1425 } |
1427 } | 1426 } |
1428 | 1427 |
1429 | 1428 |
1430 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 1429 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
1431 DoubleRegister left = ToDoubleRegister(instr->InputAt(0)); | 1430 DoubleRegister left = ToDoubleRegister(instr->InputAt(0)); |
1432 DoubleRegister right = ToDoubleRegister(instr->InputAt(1)); | 1431 DoubleRegister right = ToDoubleRegister(instr->InputAt(1)); |
1432 DoubleRegister result = ToDoubleRegister(instr->result()); | |
1433 switch (instr->op()) { | 1433 switch (instr->op()) { |
1434 case Token::ADD: | 1434 case Token::ADD: |
1435 __ vadd(left, left, right); | 1435 __ vadd(result, left, right); |
1436 break; | 1436 break; |
1437 case Token::SUB: | 1437 case Token::SUB: |
1438 __ vsub(left, left, right); | 1438 __ vsub(result, left, right); |
1439 break; | 1439 break; |
1440 case Token::MUL: | 1440 case Token::MUL: |
1441 __ vmul(left, left, right); | 1441 __ vmul(result, left, right); |
1442 break; | 1442 break; |
1443 case Token::DIV: | 1443 case Token::DIV: |
1444 __ vdiv(left, left, right); | 1444 __ vdiv(result, left, right); |
1445 break; | 1445 break; |
1446 case Token::MOD: { | 1446 case Token::MOD: { |
1447 // Save r0-r3 on the stack. | 1447 // Save r0-r3 on the stack. |
1448 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); | 1448 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); |
1449 | 1449 |
1450 __ PrepareCallCFunction(0, 2, scratch0()); | 1450 __ PrepareCallCFunction(0, 2, scratch0()); |
1451 __ SetCallCDoubleArguments(left, right); | 1451 __ SetCallCDoubleArguments(left, right); |
1452 __ CallCFunction( | 1452 __ CallCFunction( |
1453 ExternalReference::double_fp_operation(Token::MOD, isolate()), | 1453 ExternalReference::double_fp_operation(Token::MOD, isolate()), |
1454 0, 2); | 1454 0, 2); |
1455 // Move the result in the double result register. | 1455 // Move the result in the double result register. |
1456 __ GetCFunctionDoubleResult(ToDoubleRegister(instr->result())); | 1456 __ GetCFunctionDoubleResult(result); |
1457 | 1457 |
1458 // Restore r0-r3. | 1458 // Restore r0-r3. |
1459 __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); | 1459 __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); |
1460 break; | 1460 break; |
1461 } | 1461 } |
1462 default: | 1462 default: |
1463 UNREACHABLE(); | 1463 UNREACHABLE(); |
1464 break; | 1464 break; |
1465 } | 1465 } |
1466 } | 1466 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1540 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 1540 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
1541 __ cmp(reg, ip); | 1541 __ cmp(reg, ip); |
1542 __ b(eq, false_label); | 1542 __ b(eq, false_label); |
1543 __ cmp(reg, Operand(0)); | 1543 __ cmp(reg, Operand(0)); |
1544 __ b(eq, false_label); | 1544 __ b(eq, false_label); |
1545 __ tst(reg, Operand(kSmiTagMask)); | 1545 __ tst(reg, Operand(kSmiTagMask)); |
1546 __ b(eq, true_label); | 1546 __ b(eq, true_label); |
1547 | 1547 |
1548 // Test double values. Zero and NaN are false. | 1548 // Test double values. Zero and NaN are false. |
1549 Label call_stub; | 1549 Label call_stub; |
1550 DoubleRegister dbl_scratch = d0; | 1550 DoubleRegister dbl_scratch = double_scratch0(); |
1551 Register scratch = scratch0(); | 1551 Register scratch = scratch0(); |
1552 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1552 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
1553 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 1553 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
1554 __ cmp(scratch, Operand(ip)); | 1554 __ cmp(scratch, Operand(ip)); |
1555 __ b(ne, &call_stub); | 1555 __ b(ne, &call_stub); |
1556 __ sub(ip, reg, Operand(kHeapObjectTag)); | 1556 __ sub(ip, reg, Operand(kHeapObjectTag)); |
1557 __ vldr(dbl_scratch, ip, HeapNumber::kValueOffset); | 1557 __ vldr(dbl_scratch, ip, HeapNumber::kValueOffset); |
1558 __ VFPCompareAndLoadFlags(dbl_scratch, 0.0, scratch); | 1558 __ VFPCompareAndLoadFlags(dbl_scratch, 0.0, scratch); |
1559 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); | 1559 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); |
1560 __ b(ne, false_label); | 1560 __ b(ne, false_label); |
(...skipping 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2585 __ add(length, length, Operand(1)); | 2585 __ add(length, length, Operand(1)); |
2586 __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2)); | 2586 __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2)); |
2587 } | 2587 } |
2588 | 2588 |
2589 | 2589 |
2590 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { | 2590 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { |
2591 Register elements = ToRegister(instr->elements()); | 2591 Register elements = ToRegister(instr->elements()); |
2592 Register key = EmitLoadRegister(instr->key(), scratch0()); | 2592 Register key = EmitLoadRegister(instr->key(), scratch0()); |
2593 Register result = ToRegister(instr->result()); | 2593 Register result = ToRegister(instr->result()); |
2594 Register scratch = scratch0(); | 2594 Register scratch = scratch0(); |
2595 ASSERT(result.is(elements)); | |
2596 | 2595 |
2597 // Load the result. | 2596 // Load the result. |
2598 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); | 2597 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); |
2599 __ ldr(result, FieldMemOperand(scratch, FixedArray::kHeaderSize)); | 2598 __ ldr(result, FieldMemOperand(scratch, FixedArray::kHeaderSize)); |
2600 | 2599 |
2601 // Check for the hole value. | 2600 // Check for the hole value. |
2602 if (instr->hydrogen()->RequiresHoleCheck()) { | 2601 if (instr->hydrogen()->RequiresHoleCheck()) { |
2603 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); | 2602 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
2604 __ cmp(result, scratch); | 2603 __ cmp(result, scratch); |
2605 DeoptimizeIf(eq, instr->environment()); | 2604 DeoptimizeIf(eq, instr->environment()); |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2904 ASSERT(ToRegister(instr->result()).is(r0)); | 2903 ASSERT(ToRegister(instr->result()).is(r0)); |
2905 __ mov(r1, Operand(instr->function())); | 2904 __ mov(r1, Operand(instr->function())); |
2906 CallKnownFunction(instr->function(), | 2905 CallKnownFunction(instr->function(), |
2907 instr->arity(), | 2906 instr->arity(), |
2908 instr, | 2907 instr, |
2909 CALL_AS_METHOD); | 2908 CALL_AS_METHOD); |
2910 } | 2909 } |
2911 | 2910 |
2912 | 2911 |
2913 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 2912 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
2914 ASSERT(instr->InputAt(0)->Equals(instr->result())); | |
2915 Register input = ToRegister(instr->InputAt(0)); | 2913 Register input = ToRegister(instr->InputAt(0)); |
2914 Register result = ToRegister(instr->result()); | |
2916 Register scratch = scratch0(); | 2915 Register scratch = scratch0(); |
2917 | 2916 |
2918 // Deoptimize if not a heap number. | 2917 // Deoptimize if not a heap number. |
2919 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 2918 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
2920 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 2919 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
2921 __ cmp(scratch, Operand(ip)); | 2920 __ cmp(scratch, Operand(ip)); |
2922 DeoptimizeIf(ne, instr->environment()); | 2921 DeoptimizeIf(ne, instr->environment()); |
2923 | 2922 |
2924 Label done; | 2923 Label done; |
2925 Register exponent = scratch0(); | 2924 Register exponent = scratch0(); |
2926 scratch = no_reg; | 2925 scratch = no_reg; |
2927 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 2926 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
2928 // Check the sign of the argument. If the argument is positive, just | 2927 // Check the sign of the argument. If the argument is positive, just |
2929 // return it. We do not need to patch the stack since |input| and | 2928 // return it. |
2930 // |result| are the same register and |input| would be restored | |
2931 // unchanged by popping safepoint registers. | |
2932 __ tst(exponent, Operand(HeapNumber::kSignMask)); | 2929 __ tst(exponent, Operand(HeapNumber::kSignMask)); |
2930 // Move the input to the result if necessary. | |
2931 __ Move(result, input); | |
2933 __ b(eq, &done); | 2932 __ b(eq, &done); |
2934 | 2933 |
2935 // Input is negative. Reverse its sign. | 2934 // Input is negative. Reverse its sign. |
2936 // Preserve the value of all registers. | 2935 // Preserve the value of all registers. |
2937 { | 2936 { |
2938 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 2937 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
2939 | 2938 |
2940 // Registers were saved at the safepoint, so we can use | 2939 // Registers were saved at the safepoint, so we can use |
2941 // many scratch registers. | 2940 // many scratch registers. |
2942 Register tmp1 = input.is(r1) ? r0 : r1; | 2941 Register tmp1 = input.is(r1) ? r0 : r1; |
(...skipping 19 matching lines...) Expand all Loading... | |
2962 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 2961 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
2963 | 2962 |
2964 __ bind(&allocated); | 2963 __ bind(&allocated); |
2965 // exponent: floating point exponent value. | 2964 // exponent: floating point exponent value. |
2966 // tmp1: allocated heap number. | 2965 // tmp1: allocated heap number. |
2967 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask)); | 2966 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask)); |
2968 __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset)); | 2967 __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset)); |
2969 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); | 2968 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); |
2970 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); | 2969 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); |
2971 | 2970 |
2972 __ StoreToSafepointRegisterSlot(tmp1, input); | 2971 __ StoreToSafepointRegisterSlot(tmp1, result); |
2973 } | 2972 } |
2974 | 2973 |
2975 __ bind(&done); | 2974 __ bind(&done); |
2976 } | 2975 } |
2977 | 2976 |
2978 | 2977 |
2979 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 2978 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
2980 Register input = ToRegister(instr->InputAt(0)); | 2979 Register input = ToRegister(instr->InputAt(0)); |
2980 Register result = ToRegister(instr->result()); | |
2981 __ cmp(input, Operand(0)); | 2981 __ cmp(input, Operand(0)); |
2982 __ Move(result, input); | |
2982 // We can make rsb conditional because the previous cmp instruction | 2983 // We can make rsb conditional because the previous cmp instruction |
2983 // will clear the V (overflow) flag and rsb won't set this flag | 2984 // will clear the V (overflow) flag and rsb won't set this flag |
2984 // if input is positive. | 2985 // if input is positive. |
2985 __ rsb(input, input, Operand(0), SetCC, mi); | 2986 __ rsb(result, input, Operand(0), SetCC, mi); |
2986 // Deoptimize on overflow. | 2987 // Deoptimize on overflow. |
2987 DeoptimizeIf(vs, instr->environment()); | 2988 DeoptimizeIf(vs, instr->environment()); |
2988 } | 2989 } |
2989 | 2990 |
2990 | 2991 |
2991 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 2992 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
2992 // Class for deferred case. | 2993 // Class for deferred case. |
2993 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 2994 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
2994 public: | 2995 public: |
2995 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 2996 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
2996 LUnaryMathOperation* instr) | 2997 LUnaryMathOperation* instr) |
2997 : LDeferredCode(codegen), instr_(instr) { } | 2998 : LDeferredCode(codegen), instr_(instr) { } |
2998 virtual void Generate() { | 2999 virtual void Generate() { |
2999 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3000 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
3000 } | 3001 } |
3001 private: | 3002 private: |
3002 LUnaryMathOperation* instr_; | 3003 LUnaryMathOperation* instr_; |
3003 }; | 3004 }; |
3004 | 3005 |
3005 ASSERT(instr->InputAt(0)->Equals(instr->result())); | |
3006 Representation r = instr->hydrogen()->value()->representation(); | 3006 Representation r = instr->hydrogen()->value()->representation(); |
3007 if (r.IsDouble()) { | 3007 if (r.IsDouble()) { |
3008 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0)); | 3008 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0)); |
3009 __ vabs(input, input); | 3009 DwVfpRegister result = ToDoubleRegister(instr->result()); |
3010 __ vabs(result, input); | |
3010 } else if (r.IsInteger32()) { | 3011 } else if (r.IsInteger32()) { |
3011 EmitIntegerMathAbs(instr); | 3012 EmitIntegerMathAbs(instr); |
3012 } else { | 3013 } else { |
3013 // Representation is tagged. | 3014 // Representation is tagged. |
3014 DeferredMathAbsTaggedHeapNumber* deferred = | 3015 DeferredMathAbsTaggedHeapNumber* deferred = |
3015 new DeferredMathAbsTaggedHeapNumber(this, instr); | 3016 new DeferredMathAbsTaggedHeapNumber(this, instr); |
3016 Register input = ToRegister(instr->InputAt(0)); | 3017 Register input = ToRegister(instr->InputAt(0)); |
3017 // Smi check. | 3018 // Smi check. |
3018 __ JumpIfNotSmi(input, deferred->entry()); | 3019 __ JumpIfNotSmi(input, deferred->entry()); |
3019 // If smi, handle it directly. | 3020 // If smi, handle it directly. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3077 } | 3078 } |
3078 | 3079 |
3079 // The following conversion will not work with numbers | 3080 // The following conversion will not work with numbers |
3080 // outside of ]-2^32, 2^32[. | 3081 // outside of ]-2^32, 2^32[. |
3081 __ cmp(scratch2, Operand(HeapNumber::kExponentBias + 32)); | 3082 __ cmp(scratch2, Operand(HeapNumber::kExponentBias + 32)); |
3082 DeoptimizeIf(ge, instr->environment()); | 3083 DeoptimizeIf(ge, instr->environment()); |
3083 | 3084 |
3084 // Save the original sign for later comparison. | 3085 // Save the original sign for later comparison. |
3085 __ and_(scratch2, scratch1, Operand(HeapNumber::kSignMask)); | 3086 __ and_(scratch2, scratch1, Operand(HeapNumber::kSignMask)); |
3086 | 3087 |
3087 __ vmov(double_scratch0(), 0.5); | 3088 __ Vmov(double_scratch0(), 0.5); |
3088 __ vadd(input, input, double_scratch0()); | 3089 __ vadd(input, input, double_scratch0()); |
3089 | 3090 |
3090 // Check sign of the result: if the sign changed, the input | 3091 // Check sign of the result: if the sign changed, the input |
3091 // value was in ]0.5, 0[ and the result should be -0. | 3092 // value was in ]0.5, 0[ and the result should be -0. |
3092 __ vmov(scratch1, input.high()); | 3093 __ vmov(scratch1, input.high()); |
3093 __ eor(scratch1, scratch1, Operand(scratch2), SetCC); | 3094 __ eor(scratch1, scratch1, Operand(scratch2), SetCC); |
3094 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3095 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3095 DeoptimizeIf(mi, instr->environment()); | 3096 DeoptimizeIf(mi, instr->environment()); |
3096 } else { | 3097 } else { |
3097 __ mov(result, Operand(0), LeaveCC, mi); | 3098 __ mov(result, Operand(0), LeaveCC, mi); |
(...skipping 16 matching lines...) Expand all Loading... | |
3114 __ vmov(scratch1, input.high()); | 3115 __ vmov(scratch1, input.high()); |
3115 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | 3116 __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
3116 DeoptimizeIf(ne, instr->environment()); | 3117 DeoptimizeIf(ne, instr->environment()); |
3117 } | 3118 } |
3118 __ bind(&done); | 3119 __ bind(&done); |
3119 } | 3120 } |
3120 | 3121 |
3121 | 3122 |
3122 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 3123 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
3123 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); | 3124 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
3124 ASSERT(ToDoubleRegister(instr->result()).is(input)); | 3125 DoubleRegister result = ToDoubleRegister(instr->result()); |
3125 __ vsqrt(input, input); | 3126 __ vsqrt(result, input); |
3126 } | 3127 } |
3127 | 3128 |
3128 | 3129 |
3129 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { | 3130 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
3130 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); | 3131 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
3131 Register scratch = scratch0(); | 3132 DoubleRegister result = ToDoubleRegister(instr->result()); |
3132 SwVfpRegister single_scratch = double_scratch0().low(); | |
3133 DoubleRegister double_scratch = double_scratch0(); | |
3134 ASSERT(ToDoubleRegister(instr->result()).is(input)); | |
3135 | |
3136 // Add +0 to convert -0 to +0. | 3133 // Add +0 to convert -0 to +0. |
3137 __ mov(scratch, Operand(0)); | 3134 __ vadd(input, input, kDoubleRegZero); |
3138 __ vmov(single_scratch, scratch); | 3135 __ vsqrt(result, input); |
3139 __ vcvt_f64_s32(double_scratch, single_scratch); | |
3140 __ vadd(input, input, double_scratch); | |
3141 __ vsqrt(input, input); | |
3142 } | 3136 } |
3143 | 3137 |
3144 | 3138 |
3145 void LCodeGen::DoPower(LPower* instr) { | 3139 void LCodeGen::DoPower(LPower* instr) { |
3146 LOperand* left = instr->InputAt(0); | 3140 LOperand* left = instr->InputAt(0); |
3147 LOperand* right = instr->InputAt(1); | 3141 LOperand* right = instr->InputAt(1); |
3148 Register scratch = scratch0(); | 3142 Register scratch = scratch0(); |
3149 DoubleRegister result_reg = ToDoubleRegister(instr->result()); | 3143 DoubleRegister result_reg = ToDoubleRegister(instr->result()); |
3150 Representation exponent_type = instr->hydrogen()->right()->representation(); | 3144 Representation exponent_type = instr->hydrogen()->right()->representation(); |
3151 if (exponent_type.IsDouble()) { | 3145 if (exponent_type.IsDouble()) { |
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3729 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); | 3723 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); |
3730 __ SmiTag(reg, SetCC); | 3724 __ SmiTag(reg, SetCC); |
3731 __ b(vs, deferred->entry()); | 3725 __ b(vs, deferred->entry()); |
3732 __ bind(deferred->exit()); | 3726 __ bind(deferred->exit()); |
3733 } | 3727 } |
3734 | 3728 |
3735 | 3729 |
3736 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { | 3730 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { |
3737 Label slow; | 3731 Label slow; |
3738 Register reg = ToRegister(instr->InputAt(0)); | 3732 Register reg = ToRegister(instr->InputAt(0)); |
3739 DoubleRegister dbl_scratch = d0; | 3733 DoubleRegister dbl_scratch = double_scratch0(); |
3740 SwVfpRegister flt_scratch = s0; | 3734 SwVfpRegister flt_scratch = dbl_scratch.low(); |
3741 | 3735 |
3742 // Preserve the value of all registers. | 3736 // Preserve the value of all registers. |
3743 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 3737 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
3744 | 3738 |
3745 // There was overflow, so bits 30 and 31 of the original integer | 3739 // There was overflow, so bits 30 and 31 of the original integer |
3746 // disagree. Try to allocate a heap number in new space and store | 3740 // disagree. Try to allocate a heap number in new space and store |
3747 // the value in there. If that fails, call the runtime system. | 3741 // the value in there. If that fails, call the runtime system. |
3748 Label done; | 3742 Label done; |
3749 __ SmiUntag(reg); | 3743 __ SmiUntag(reg); |
3750 __ eor(reg, reg, Operand(0x80000000)); | 3744 __ eor(reg, reg, Operand(0x80000000)); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3839 __ SmiUntag(ToRegister(input)); | 3833 __ SmiUntag(ToRegister(input)); |
3840 } | 3834 } |
3841 } | 3835 } |
3842 | 3836 |
3843 | 3837 |
3844 void LCodeGen::EmitNumberUntagD(Register input_reg, | 3838 void LCodeGen::EmitNumberUntagD(Register input_reg, |
3845 DoubleRegister result_reg, | 3839 DoubleRegister result_reg, |
3846 bool deoptimize_on_undefined, | 3840 bool deoptimize_on_undefined, |
3847 LEnvironment* env) { | 3841 LEnvironment* env) { |
3848 Register scratch = scratch0(); | 3842 Register scratch = scratch0(); |
3849 SwVfpRegister flt_scratch = s0; | 3843 SwVfpRegister flt_scratch = double_scratch0().low(); |
3850 ASSERT(!result_reg.is(d0)); | 3844 ASSERT(!result_reg.is(double_scratch0())); |
3851 | 3845 |
3852 Label load_smi, heap_number, done; | 3846 Label load_smi, heap_number, done; |
3853 | 3847 |
3854 // Smi check. | 3848 // Smi check. |
3855 __ tst(input_reg, Operand(kSmiTagMask)); | 3849 __ tst(input_reg, Operand(kSmiTagMask)); |
3856 __ b(eq, &load_smi); | 3850 __ b(eq, &load_smi); |
3857 | 3851 |
3858 // Heap number map check. | 3852 // Heap number map check. |
3859 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 3853 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
3860 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 3854 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
(...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4586 ASSERT(osr_pc_offset_ == -1); | 4580 ASSERT(osr_pc_offset_ == -1); |
4587 osr_pc_offset_ = masm()->pc_offset(); | 4581 osr_pc_offset_ = masm()->pc_offset(); |
4588 } | 4582 } |
4589 | 4583 |
4590 | 4584 |
4591 | 4585 |
4592 | 4586 |
4593 #undef __ | 4587 #undef __ |
4594 | 4588 |
4595 } } // namespace v8::internal | 4589 } } // namespace v8::internal |
OLD | NEW |