OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 | 380 |
381 stream->Add(" length "); | 381 stream->Add(" length "); |
382 length()->PrintTo(stream); | 382 length()->PrintTo(stream); |
383 | 383 |
384 stream->Add(" index "); | 384 stream->Add(" index "); |
385 index()->PrintTo(stream); | 385 index()->PrintTo(stream); |
386 } | 386 } |
387 | 387 |
388 | 388 |
389 int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) { | 389 int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) { |
390 // Skip a slot if for a double-width slot. | 390 switch (kind) { |
391 if (kind == DOUBLE_REGISTERS) { | 391 case GENERAL_REGISTERS: return spill_slot_count_++; |
392 spill_slot_count_++; | 392 case DOUBLE_REGISTERS: { |
393 spill_slot_count_ |= 1; | 393 // Skip a slot if for a double-width slot. |
394 num_double_slots_++; | 394 spill_slot_count_++; |
| 395 spill_slot_count_ |= 1; |
| 396 num_double_slots_++; |
| 397 return spill_slot_count_++; |
| 398 } |
| 399 case FLOAT32x4_REGISTERS: |
| 400 case INT32x4_REGISTERS: { |
| 401 // Skip three slots if for a double-width slot. |
| 402 spill_slot_count_ += 3; |
| 403 num_double_slots_++; // for dynamic frame alignment |
| 404 return spill_slot_count_++; |
| 405 } |
| 406 default: |
| 407 UNREACHABLE(); |
| 408 return -1; |
395 } | 409 } |
396 return spill_slot_count_++; | |
397 } | 410 } |
398 | 411 |
399 | 412 |
400 LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) { | 413 LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) { |
401 int index = GetNextSpillIndex(kind); | 414 int index = GetNextSpillIndex(kind); |
402 if (kind == DOUBLE_REGISTERS) { | 415 switch (kind) { |
403 return LDoubleStackSlot::Create(index, zone()); | 416 case GENERAL_REGISTERS: return LStackSlot::Create(index, zone()); |
404 } else { | 417 case DOUBLE_REGISTERS: return LDoubleStackSlot::Create(index, zone()); |
405 ASSERT(kind == GENERAL_REGISTERS); | 418 case FLOAT32x4_REGISTERS: return LFloat32x4StackSlot::Create(index, zone()); |
406 return LStackSlot::Create(index, zone()); | 419 case INT32x4_REGISTERS: return LInt32x4StackSlot::Create(index, zone()); |
| 420 default: |
| 421 UNREACHABLE(); |
| 422 return NULL; |
407 } | 423 } |
408 } | 424 } |
409 | 425 |
410 | 426 |
411 void LStoreNamedField::PrintDataTo(StringStream* stream) { | 427 void LStoreNamedField::PrintDataTo(StringStream* stream) { |
412 object()->PrintTo(stream); | 428 object()->PrintTo(stream); |
413 hydrogen()->access().PrintTo(stream); | 429 hydrogen()->access().PrintTo(stream); |
414 stream->Add(" <- "); | 430 stream->Add(" <- "); |
415 value()->PrintTo(stream); | 431 value()->PrintTo(stream); |
416 } | 432 } |
(...skipping 1560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1977 // Only mark conversions that might need to allocate as calling rather than | 1993 // Only mark conversions that might need to allocate as calling rather than |
1978 // all changes. This makes simple, non-allocating conversion not have to force | 1994 // all changes. This makes simple, non-allocating conversion not have to force |
1979 // building a stack frame. | 1995 // building a stack frame. |
1980 if (from.IsTagged()) { | 1996 if (from.IsTagged()) { |
1981 if (to.IsDouble()) { | 1997 if (to.IsDouble()) { |
1982 LOperand* value = UseRegister(instr->value()); | 1998 LOperand* value = UseRegister(instr->value()); |
1983 // Temp register only necessary for minus zero check. | 1999 // Temp register only necessary for minus zero check. |
1984 LOperand* temp = TempRegister(); | 2000 LOperand* temp = TempRegister(); |
1985 LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp); | 2001 LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp); |
1986 return AssignEnvironment(DefineAsRegister(res)); | 2002 return AssignEnvironment(DefineAsRegister(res)); |
| 2003 } else if (to.IsFloat32x4()) { |
| 2004 LOperand* value = UseRegister(instr->value()); |
| 2005 LOperand* temp = TempRegister(); |
| 2006 LTaggedToFloat32x4* res = new(zone()) LTaggedToFloat32x4(value, temp); |
| 2007 return AssignEnvironment(DefineAsRegister(res)); |
| 2008 } else if (to.IsInt32x4()) { |
| 2009 LOperand* value = UseRegister(instr->value()); |
| 2010 LOperand* temp = TempRegister(); |
| 2011 LTaggedToInt32x4* res = new(zone()) LTaggedToInt32x4(value, temp); |
| 2012 return AssignEnvironment(DefineAsRegister(res)); |
1987 } else if (to.IsSmi()) { | 2013 } else if (to.IsSmi()) { |
1988 HValue* val = instr->value(); | 2014 HValue* val = instr->value(); |
1989 LOperand* value = UseRegister(val); | 2015 LOperand* value = UseRegister(val); |
1990 if (val->type().IsSmi()) { | 2016 if (val->type().IsSmi()) { |
1991 return DefineSameAsFirst(new(zone()) LDummyUse(value)); | 2017 return DefineSameAsFirst(new(zone()) LDummyUse(value)); |
1992 } | 2018 } |
1993 return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value))); | 2019 return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value))); |
1994 } else { | 2020 } else { |
1995 ASSERT(to.IsInteger32()); | 2021 ASSERT(to.IsInteger32()); |
1996 HValue* val = instr->value(); | 2022 HValue* val = instr->value(); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2060 ASSERT(to.IsDouble()); | 2086 ASSERT(to.IsDouble()); |
2061 if (instr->value()->CheckFlag(HInstruction::kUint32)) { | 2087 if (instr->value()->CheckFlag(HInstruction::kUint32)) { |
2062 LOperand* temp = FixedTemp(xmm1); | 2088 LOperand* temp = FixedTemp(xmm1); |
2063 return DefineAsRegister( | 2089 return DefineAsRegister( |
2064 new(zone()) LUint32ToDouble(UseRegister(instr->value()), temp)); | 2090 new(zone()) LUint32ToDouble(UseRegister(instr->value()), temp)); |
2065 } else { | 2091 } else { |
2066 return DefineAsRegister( | 2092 return DefineAsRegister( |
2067 new(zone()) LInteger32ToDouble(Use(instr->value()))); | 2093 new(zone()) LInteger32ToDouble(Use(instr->value()))); |
2068 } | 2094 } |
2069 } | 2095 } |
| 2096 } else if (from.IsFloat32x4()) { |
| 2097 ASSERT(to.IsTagged()); |
| 2098 info()->MarkAsDeferredCalling(); |
| 2099 LOperand* value = UseRegister(instr->value()); |
| 2100 LOperand* temp = TempRegister(); |
| 2101 |
| 2102 // Make sure that temp and result_temp are different registers. |
| 2103 LUnallocated* result_temp = TempRegister(); |
| 2104 LFloat32x4ToTagged* result = |
| 2105 new(zone()) LFloat32x4ToTagged(value, temp); |
| 2106 return AssignPointerMap(Define(result, result_temp)); |
| 2107 } else if (from.IsInt32x4()) { |
| 2108 ASSERT(to.IsTagged()); |
| 2109 info()->MarkAsDeferredCalling(); |
| 2110 LOperand* value = UseRegister(instr->value()); |
| 2111 LOperand* temp = TempRegister(); |
| 2112 |
| 2113 // Make sure that temp and result_temp are different registers. |
| 2114 LUnallocated* result_temp = TempRegister(); |
| 2115 LInt32x4ToTagged* result = new(zone()) LInt32x4ToTagged(value, temp); |
| 2116 return AssignPointerMap(Define(result, result_temp)); |
2070 } | 2117 } |
2071 UNREACHABLE(); | 2118 UNREACHABLE(); |
2072 return NULL; | 2119 return NULL; |
2073 } | 2120 } |
2074 | 2121 |
2075 | 2122 |
2076 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) { | 2123 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) { |
2077 LOperand* value = UseAtStart(instr->value()); | 2124 LOperand* value = UseAtStart(instr->value()); |
2078 return AssignEnvironment(new(zone()) LCheckNonSmi(value)); | 2125 return AssignEnvironment(new(zone()) LCheckNonSmi(value)); |
2079 } | 2126 } |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2276 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { | 2323 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { |
2277 ASSERT(instr->key()->representation().IsSmiOrInteger32()); | 2324 ASSERT(instr->key()->representation().IsSmiOrInteger32()); |
2278 ElementsKind elements_kind = instr->elements_kind(); | 2325 ElementsKind elements_kind = instr->elements_kind(); |
2279 bool clobbers_key = ExternalArrayOpRequiresTemp( | 2326 bool clobbers_key = ExternalArrayOpRequiresTemp( |
2280 instr->key()->representation(), elements_kind); | 2327 instr->key()->representation(), elements_kind); |
2281 LOperand* key = clobbers_key | 2328 LOperand* key = clobbers_key |
2282 ? UseTempRegister(instr->key()) | 2329 ? UseTempRegister(instr->key()) |
2283 : UseRegisterOrConstantAtStart(instr->key()); | 2330 : UseRegisterOrConstantAtStart(instr->key()); |
2284 LLoadKeyed* result = NULL; | 2331 LLoadKeyed* result = NULL; |
2285 | 2332 |
| 2333 bool load_128bits_without_sse2 = |
| 2334 ExternalArrayOpRequiresSpecialHandling(elements_kind); |
2286 if (!instr->is_external()) { | 2335 if (!instr->is_external()) { |
2287 LOperand* obj = UseRegisterAtStart(instr->elements()); | 2336 LOperand* obj = UseRegisterAtStart(instr->elements()); |
2288 result = new(zone()) LLoadKeyed(obj, key); | 2337 result = new(zone()) LLoadKeyed(obj, key, NULL); |
2289 } else { | 2338 } else { |
2290 ASSERT( | 2339 ASSERT( |
2291 (instr->representation().IsInteger32() && | 2340 (instr->representation().IsInteger32() && |
2292 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) && | 2341 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) && |
2293 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) || | 2342 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS) && |
| 2343 (elements_kind != EXTERNAL_FLOAT32x4_ELEMENTS) && |
| 2344 (elements_kind != EXTERNAL_INT32x4_ELEMENTS)) || |
2294 (instr->representation().IsDouble() && | 2345 (instr->representation().IsDouble() && |
2295 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || | 2346 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || |
2296 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); | 2347 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))) || |
| 2348 (CpuFeatures::IsSupported(SSE2) ? |
| 2349 instr->representation().IsFloat32x4() : |
| 2350 instr->representation().IsTagged() && |
| 2351 elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS) || |
| 2352 (CpuFeatures::IsSupported(SSE2) ? |
| 2353 instr->representation().IsInt32x4() : |
| 2354 instr->representation().IsTagged() && |
| 2355 elements_kind == EXTERNAL_INT32x4_ELEMENTS)); |
2297 LOperand* external_pointer = UseRegister(instr->elements()); | 2356 LOperand* external_pointer = UseRegister(instr->elements()); |
2298 result = new(zone()) LLoadKeyed(external_pointer, key); | 2357 result = new(zone()) LLoadKeyed(external_pointer, key, |
| 2358 load_128bits_without_sse2 ? TempRegister() : NULL); |
| 2359 if (load_128bits_without_sse2) info()->MarkAsDeferredCalling(); |
2299 } | 2360 } |
2300 | 2361 |
2301 DefineAsRegister(result); | 2362 DefineAsRegister(result); |
2302 bool can_deoptimize = instr->RequiresHoleCheck() || | 2363 bool can_deoptimize = instr->RequiresHoleCheck() || |
2303 (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS); | 2364 (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS); |
2304 // An unsigned int array load might overflow and cause a deopt, make sure it | 2365 // An unsigned int array load might overflow and cause a deopt, make sure it |
2305 // has an environment. | 2366 // has an environment. |
2306 return can_deoptimize ? AssignEnvironment(result) : result; | 2367 return can_deoptimize ? AssignEnvironment(result) |
| 2368 : load_128bits_without_sse2 ? AssignPointerMap(result) : result; |
2307 } | 2369 } |
2308 | 2370 |
2309 | 2371 |
2310 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { | 2372 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
2311 LOperand* context = UseFixed(instr->context(), esi); | 2373 LOperand* context = UseFixed(instr->context(), esi); |
2312 LOperand* object = UseFixed(instr->object(), edx); | 2374 LOperand* object = UseFixed(instr->object(), edx); |
2313 LOperand* key = UseFixed(instr->key(), ecx); | 2375 LOperand* key = UseFixed(instr->key(), ecx); |
2314 | 2376 |
2315 LLoadKeyedGeneric* result = | 2377 LLoadKeyedGeneric* result = |
2316 new(zone()) LLoadKeyedGeneric(context, object, key); | 2378 new(zone()) LLoadKeyedGeneric(context, object, key); |
(...skipping 26 matching lines...) Expand all Loading... |
2343 if (!instr->is_external()) { | 2405 if (!instr->is_external()) { |
2344 ASSERT(instr->elements()->representation().IsTagged()); | 2406 ASSERT(instr->elements()->representation().IsTagged()); |
2345 ASSERT(instr->key()->representation().IsInteger32() || | 2407 ASSERT(instr->key()->representation().IsInteger32() || |
2346 instr->key()->representation().IsSmi()); | 2408 instr->key()->representation().IsSmi()); |
2347 | 2409 |
2348 if (instr->value()->representation().IsDouble()) { | 2410 if (instr->value()->representation().IsDouble()) { |
2349 LOperand* object = UseRegisterAtStart(instr->elements()); | 2411 LOperand* object = UseRegisterAtStart(instr->elements()); |
2350 LOperand* val = NULL; | 2412 LOperand* val = NULL; |
2351 val = UseRegisterAtStart(instr->value()); | 2413 val = UseRegisterAtStart(instr->value()); |
2352 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); | 2414 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
2353 return new(zone()) LStoreKeyed(object, key, val); | 2415 return new(zone()) LStoreKeyed(object, key, val, NULL); |
2354 } else { | 2416 } else { |
2355 ASSERT(instr->value()->representation().IsSmiOrTagged()); | 2417 ASSERT(instr->value()->representation().IsSmiOrTagged()); |
2356 bool needs_write_barrier = instr->NeedsWriteBarrier(); | 2418 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
2357 | 2419 |
2358 LOperand* obj = UseRegister(instr->elements()); | 2420 LOperand* obj = UseRegister(instr->elements()); |
2359 LOperand* val; | 2421 LOperand* val; |
2360 LOperand* key; | 2422 LOperand* key; |
2361 if (needs_write_barrier) { | 2423 if (needs_write_barrier) { |
2362 val = UseTempRegister(instr->value()); | 2424 val = UseTempRegister(instr->value()); |
2363 key = UseTempRegister(instr->key()); | 2425 key = UseTempRegister(instr->key()); |
2364 } else { | 2426 } else { |
2365 val = UseRegisterOrConstantAtStart(instr->value()); | 2427 val = UseRegisterOrConstantAtStart(instr->value()); |
2366 key = UseRegisterOrConstantAtStart(instr->key()); | 2428 key = UseRegisterOrConstantAtStart(instr->key()); |
2367 } | 2429 } |
2368 return new(zone()) LStoreKeyed(obj, key, val); | 2430 return new(zone()) LStoreKeyed(obj, key, val, NULL); |
2369 } | 2431 } |
2370 } | 2432 } |
2371 | 2433 |
2372 ElementsKind elements_kind = instr->elements_kind(); | 2434 ElementsKind elements_kind = instr->elements_kind(); |
2373 ASSERT( | 2435 ASSERT( |
2374 (instr->value()->representation().IsInteger32() && | 2436 (instr->value()->representation().IsInteger32() && |
2375 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) && | 2437 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) && |
2376 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) || | 2438 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS) && |
| 2439 (elements_kind != EXTERNAL_FLOAT32x4_ELEMENTS)) || |
2377 (instr->value()->representation().IsDouble() && | 2440 (instr->value()->representation().IsDouble() && |
2378 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || | 2441 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || |
2379 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); | 2442 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))) || |
| 2443 (CpuFeatures::IsSupported(SSE2) |
| 2444 ? instr->value()->representation().IsFloat32x4() |
| 2445 : instr->value()->representation().IsTagged() && |
| 2446 elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS) || |
| 2447 (CpuFeatures::IsSupported(SSE2) |
| 2448 ? instr->value()->representation().IsInt32x4() |
| 2449 : instr->value()->representation().IsTagged() && |
| 2450 elements_kind == EXTERNAL_INT32x4_ELEMENTS)); |
2380 ASSERT(instr->elements()->representation().IsExternal()); | 2451 ASSERT(instr->elements()->representation().IsExternal()); |
2381 | 2452 |
2382 LOperand* external_pointer = UseRegister(instr->elements()); | 2453 LOperand* external_pointer = UseRegister(instr->elements()); |
2383 LOperand* val = GetStoreKeyedValueOperand(instr); | 2454 LOperand* val = GetStoreKeyedValueOperand(instr); |
2384 bool clobbers_key = ExternalArrayOpRequiresTemp( | 2455 bool clobbers_key = ExternalArrayOpRequiresTemp( |
2385 instr->key()->representation(), elements_kind); | 2456 instr->key()->representation(), elements_kind); |
2386 LOperand* key = clobbers_key | 2457 LOperand* key = clobbers_key |
2387 ? UseTempRegister(instr->key()) | 2458 ? UseTempRegister(instr->key()) |
2388 : UseRegisterOrConstantAtStart(instr->key()); | 2459 : UseRegisterOrConstantAtStart(instr->key()); |
2389 return new(zone()) LStoreKeyed(external_pointer, | 2460 bool store_128bits_without_sse2 = |
2390 key, | 2461 ExternalArrayOpRequiresSpecialHandling(elements_kind); |
2391 val); | 2462 LStoreKeyed* result = |
| 2463 new(zone()) LStoreKeyed(external_pointer, key, val, |
| 2464 store_128bits_without_sse2 ? TempRegister() : NULL); |
| 2465 return store_128bits_without_sse2 ? AssignEnvironment(result) : result; |
2392 } | 2466 } |
2393 | 2467 |
2394 | 2468 |
2395 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { | 2469 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { |
2396 LOperand* context = UseFixed(instr->context(), esi); | 2470 LOperand* context = UseFixed(instr->context(), esi); |
2397 LOperand* object = UseFixed(instr->object(), edx); | 2471 LOperand* object = UseFixed(instr->object(), edx); |
2398 LOperand* key = UseFixed(instr->key(), ecx); | 2472 LOperand* key = UseFixed(instr->key(), ecx); |
2399 LOperand* value = UseFixed(instr->value(), eax); | 2473 LOperand* value = UseFixed(instr->value(), eax); |
2400 | 2474 |
2401 ASSERT(instr->object()->representation().IsTagged()); | 2475 ASSERT(instr->object()->representation().IsTagged()); |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2785 } | 2859 } |
2786 | 2860 |
2787 | 2861 |
2788 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2862 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
2789 LOperand* object = UseRegister(instr->object()); | 2863 LOperand* object = UseRegister(instr->object()); |
2790 LOperand* index = UseTempRegister(instr->index()); | 2864 LOperand* index = UseTempRegister(instr->index()); |
2791 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); | 2865 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); |
2792 } | 2866 } |
2793 | 2867 |
2794 | 2868 |
| 2869 const char* LNullarySIMDOperation::Mnemonic() const { |
| 2870 switch (op()) { |
| 2871 case kFloat32x4Zero: return "float32x4-zero"; |
| 2872 default: |
| 2873 UNREACHABLE(); |
| 2874 return NULL; |
| 2875 } |
| 2876 } |
| 2877 |
| 2878 |
| 2879 LInstruction* LChunkBuilder::DoNullarySIMDOperation( |
| 2880 HNullarySIMDOperation* instr) { |
| 2881 LNullarySIMDOperation* result = |
| 2882 new(zone()) LNullarySIMDOperation(instr->op()); |
| 2883 switch (instr->op()) { |
| 2884 case kFloat32x4Zero: |
| 2885 return DefineAsRegister(result); |
| 2886 default: |
| 2887 UNREACHABLE(); |
| 2888 return NULL; |
| 2889 } |
| 2890 } |
| 2891 |
| 2892 |
| 2893 const char* LUnarySIMDOperation::Mnemonic() const { |
| 2894 switch (op()) { |
| 2895 case kFloat32x4OrInt32x4Change: return "float32x4_int32x4-change"; |
| 2896 case kSIMDAbs: return "simd-abs"; |
| 2897 case kSIMDNeg: return "simd-neg"; |
| 2898 case kSIMDNegU32: return "simd-negu32"; |
| 2899 case kSIMDReciprocal: return "simd-reciprocal"; |
| 2900 case kSIMDReciprocalSqrt: return "simd-reciprocalSqrt"; |
| 2901 case kSIMDSqrt: return "simd-sqrt"; |
| 2902 case kSIMDBitsToFloat32x4: return "simd-bitsToFloat32x4"; |
| 2903 case kSIMDToFloat32x4: return "simd-toFloat32x4"; |
| 2904 case kSIMDBitsToInt32x4: return "simd-bitsToInt32x4"; |
| 2905 case kSIMDToInt32x4: return "simd-toInt32x4"; |
| 2906 case kFloat32x4Splat: return "float32x4-splat"; |
| 2907 case kInt32x4Splat: return "int32x4-splat"; |
| 2908 case kFloat32x4SignMask: return "float32x4-signMask"; |
| 2909 case kFloat32x4X: return "float32x4-x"; |
| 2910 case kFloat32x4Y: return "float32x4-y"; |
| 2911 case kFloat32x4Z: return "float32x4-z"; |
| 2912 case kFloat32x4W: return "float32x4-w"; |
| 2913 case kInt32x4SignMask: return "int32x4-signMask"; |
| 2914 case kInt32x4X: return "int32x4-x"; |
| 2915 case kInt32x4Y: return "int32x4-y"; |
| 2916 case kInt32x4Z: return "int32x4-z"; |
| 2917 case kInt32x4W: return "int32x4-w"; |
| 2918 case kInt32x4FlagX: return "int32x4-flagX"; |
| 2919 case kInt32x4FlagY: return "int32x4-flagY"; |
| 2920 case kInt32x4FlagZ: return "int32x4-flagZ"; |
| 2921 case kInt32x4FlagW: return "int32x4-flagW"; |
| 2922 default: |
| 2923 UNREACHABLE(); |
| 2924 return NULL; |
| 2925 } |
| 2926 } |
| 2927 |
| 2928 |
| 2929 LInstruction* LChunkBuilder::DoUnarySIMDOperation(HUnarySIMDOperation* instr) { |
| 2930 LOperand* input = UseRegisterAtStart(instr->value()); |
| 2931 LUnarySIMDOperation* result = |
| 2932 new(zone()) LUnarySIMDOperation(input, instr->op()); |
| 2933 switch (instr->op()) { |
| 2934 case kFloat32x4OrInt32x4Change: |
| 2935 return AssignEnvironment(DefineAsRegister(result)); |
| 2936 case kSIMDAbs: |
| 2937 case kSIMDNeg: |
| 2938 case kSIMDNegU32: |
| 2939 case kSIMDReciprocal: |
| 2940 case kSIMDReciprocalSqrt: |
| 2941 case kSIMDSqrt: |
| 2942 return DefineSameAsFirst(result); |
| 2943 case kSIMDBitsToFloat32x4: |
| 2944 case kSIMDToFloat32x4: |
| 2945 case kSIMDBitsToInt32x4: |
| 2946 case kSIMDToInt32x4: |
| 2947 case kFloat32x4Splat: |
| 2948 case kInt32x4Splat: |
| 2949 case kFloat32x4SignMask: |
| 2950 case kFloat32x4X: |
| 2951 case kFloat32x4Y: |
| 2952 case kFloat32x4Z: |
| 2953 case kFloat32x4W: |
| 2954 case kInt32x4SignMask: |
| 2955 case kInt32x4X: |
| 2956 case kInt32x4Y: |
| 2957 case kInt32x4Z: |
| 2958 case kInt32x4W: |
| 2959 case kInt32x4FlagX: |
| 2960 case kInt32x4FlagY: |
| 2961 case kInt32x4FlagZ: |
| 2962 case kInt32x4FlagW: |
| 2963 return DefineAsRegister(result); |
| 2964 default: |
| 2965 UNREACHABLE(); |
| 2966 return NULL; |
| 2967 } |
| 2968 } |
| 2969 |
| 2970 |
| 2971 const char* LBinarySIMDOperation::Mnemonic() const { |
| 2972 switch (op()) { |
| 2973 case kSIMDAdd: return "simd-add"; |
| 2974 case kSIMDSub: return "simd-sub"; |
| 2975 case kSIMDMul: return "simd-mul"; |
| 2976 case kSIMDDiv: return "simd-mul"; |
| 2977 case kSIMDMin: return "simd-min"; |
| 2978 case kSIMDMax: return "simd-max"; |
| 2979 case kSIMDScale: return "simd-scale"; |
| 2980 case kSIMDAnd: return "simd-and"; |
| 2981 case kSIMDOr: return "simd-or"; |
| 2982 case kSIMDXor: return "simd-xor"; |
| 2983 case kSIMDAddU32: return "simd-addu32"; |
| 2984 case kSIMDSubU32: return "simd-subu32"; |
| 2985 case kSIMDMulU32: return "simd-mulu32"; |
| 2986 case kSIMDShuffle: return "simd-shuffle"; |
| 2987 case kSIMDShuffleU32: return "simd-shuffleu32"; |
| 2988 case kSIMDLessThan: return "simd-lessThan"; |
| 2989 case kSIMDLessThanOrEqual: return "simd-lessThanOrEqual"; |
| 2990 case kSIMDEqual: return "simd-equal"; |
| 2991 case kSIMDNotEqual: return "simd-notEqual"; |
| 2992 case kSIMDGreaterThanOrEqual: return "simd-greaterThanOrEqual"; |
| 2993 case kSIMDGreaterThan: return "simd-greaterThan"; |
| 2994 case kSIMDWithX: return "simd-withX"; |
| 2995 case kSIMDWithY: return "simd-withY"; |
| 2996 case kSIMDWithZ: return "simd-withZ"; |
| 2997 case kSIMDWithW: return "simd-withW"; |
| 2998 case kSIMDWithXu32: return "simd-withXu32"; |
| 2999 case kSIMDWithYu32: return "simd-withYu32"; |
| 3000 case kSIMDWithZu32: return "simd-withZu32"; |
| 3001 case kSIMDWithWu32: return "simd-withWu32"; |
| 3002 case kSIMDWithFlagX: return "simd-withFlagX"; |
| 3003 case kSIMDWithFlagY: return "simd-withFlagY"; |
| 3004 case kSIMDWithFlagZ: return "simd-withFlagZ"; |
| 3005 case kSIMDWithFlagW: return "simd-withFlagW"; |
| 3006 default: |
| 3007 UNREACHABLE(); |
| 3008 return NULL; |
| 3009 } |
| 3010 } |
| 3011 |
| 3012 |
| 3013 LInstruction* LChunkBuilder::DoBinarySIMDOperation( |
| 3014 HBinarySIMDOperation* instr) { |
| 3015 switch (instr->op()) { |
| 3016 case kSIMDAdd: |
| 3017 case kSIMDSub: |
| 3018 case kSIMDMul: |
| 3019 case kSIMDDiv: |
| 3020 case kSIMDMin: |
| 3021 case kSIMDMax: |
| 3022 case kSIMDScale: |
| 3023 case kSIMDAnd: |
| 3024 case kSIMDOr: |
| 3025 case kSIMDXor: |
| 3026 case kSIMDAddU32: |
| 3027 case kSIMDSubU32: |
| 3028 case kSIMDMulU32: |
| 3029 case kSIMDWithX: |
| 3030 case kSIMDWithY: |
| 3031 case kSIMDWithZ: |
| 3032 case kSIMDWithW: |
| 3033 case kSIMDWithXu32: |
| 3034 case kSIMDWithYu32: |
| 3035 case kSIMDWithZu32: |
| 3036 case kSIMDWithWu32: |
| 3037 case kSIMDWithFlagX: |
| 3038 case kSIMDWithFlagY: |
| 3039 case kSIMDWithFlagZ: |
| 3040 case kSIMDWithFlagW: { |
| 3041 LOperand* left = UseRegisterAtStart(instr->left()); |
| 3042 LOperand* right = UseRegisterAtStart(instr->right()); |
| 3043 LBinarySIMDOperation* result = |
| 3044 new(zone()) LBinarySIMDOperation(left, right, instr->op()); |
| 3045 if (instr->op() == kSIMDWithFlagX || instr->op() == kSIMDWithFlagY || |
| 3046 instr->op() == kSIMDWithFlagZ || instr->op() == kSIMDWithFlagW) { |
| 3047 return AssignEnvironment(DefineSameAsFirst(result)); |
| 3048 } else { |
| 3049 return DefineSameAsFirst(result); |
| 3050 } |
| 3051 } |
| 3052 case kSIMDShuffle: |
| 3053 case kSIMDShuffleU32: { |
| 3054 LOperand* left = UseRegisterAtStart(instr->left()); |
| 3055 LOperand* right = UseOrConstant(instr->right()); |
| 3056 LBinarySIMDOperation* result = |
| 3057 new(zone()) LBinarySIMDOperation(left, right, instr->op()); |
| 3058 return AssignEnvironment(DefineSameAsFirst(result)); |
| 3059 } |
| 3060 case kSIMDLessThan: |
| 3061 case kSIMDLessThanOrEqual: |
| 3062 case kSIMDEqual: |
| 3063 case kSIMDNotEqual: |
| 3064 case kSIMDGreaterThanOrEqual: |
| 3065 case kSIMDGreaterThan: { |
| 3066 LOperand* left = UseRegisterAtStart(instr->left()); |
| 3067 LOperand* right = UseRegisterAtStart(instr->right()); |
| 3068 LBinarySIMDOperation* result = |
| 3069 new(zone()) LBinarySIMDOperation(left, right, instr->op()); |
| 3070 return DefineAsRegister(result); |
| 3071 } |
| 3072 default: |
| 3073 UNREACHABLE(); |
| 3074 return NULL; |
| 3075 } |
| 3076 } |
| 3077 |
| 3078 |
| 3079 const char* LTernarySIMDOperation::Mnemonic() const { |
| 3080 switch (op()) { |
| 3081 case kSIMDSelect: return "simd-select"; |
| 3082 case kSIMDShuffleMix: return "simd-shuffleMix"; |
| 3083 case kSIMDClamp: return "simd-clamp"; |
| 3084 default: |
| 3085 UNREACHABLE(); |
| 3086 return NULL; |
| 3087 } |
| 3088 } |
| 3089 |
| 3090 |
| 3091 LInstruction* LChunkBuilder::DoTernarySIMDOperation( |
| 3092 HTernarySIMDOperation* instr) { |
| 3093 LOperand* first = UseRegisterAtStart(instr->first()); |
| 3094 LOperand* second = UseRegisterAtStart(instr->second()); |
| 3095 LOperand* third = instr->op() == kSIMDShuffleMix |
| 3096 ? UseOrConstant(instr->third()) |
| 3097 : UseRegisterAtStart(instr->third()); |
| 3098 LTernarySIMDOperation* result = |
| 3099 new(zone()) LTernarySIMDOperation(first, second, third, instr->op()); |
| 3100 switch (instr->op()) { |
| 3101 case kSIMDSelect: { |
| 3102 return DefineAsRegister(result); |
| 3103 } |
| 3104 case kSIMDShuffleMix: { |
| 3105 return AssignEnvironment(DefineSameAsFirst(result)); |
| 3106 } |
| 3107 case kSIMDClamp: { |
| 3108 return DefineSameAsFirst(result); |
| 3109 } |
| 3110 default: |
| 3111 UNREACHABLE(); |
| 3112 return NULL; |
| 3113 } |
| 3114 } |
| 3115 |
| 3116 |
| 3117 const char* LQuarternarySIMDOperation::Mnemonic() const { |
| 3118 switch (op()) { |
| 3119 case kFloat32x4Constructor: return "float32x4-constructor"; |
| 3120 case kInt32x4Constructor: return "int32x4-constructor"; |
| 3121 case kInt32x4Bool: return "int32x4-bool"; |
| 3122 default: |
| 3123 UNREACHABLE(); |
| 3124 return NULL; |
| 3125 } |
| 3126 } |
| 3127 |
| 3128 |
| 3129 LInstruction* LChunkBuilder::DoQuarternarySIMDOperation( |
| 3130 HQuarternarySIMDOperation* instr) { |
| 3131 LOperand* x = UseRegisterAtStart(instr->x()); |
| 3132 LOperand* y = UseRegisterAtStart(instr->y()); |
| 3133 LOperand* z = UseRegisterAtStart(instr->z()); |
| 3134 LOperand* w = UseRegisterAtStart(instr->w()); |
| 3135 LQuarternarySIMDOperation* result = |
| 3136 new(zone()) LQuarternarySIMDOperation(x, y, z, w, instr->op()); |
| 3137 if (instr->op() == kInt32x4Bool) { |
| 3138 return AssignEnvironment(DefineAsRegister(result)); |
| 3139 } else { |
| 3140 return DefineAsRegister(result); |
| 3141 } |
| 3142 } |
| 3143 |
| 3144 |
2795 } } // namespace v8::internal | 3145 } } // namespace v8::internal |
2796 | 3146 |
2797 #endif // V8_TARGET_ARCH_IA32 | 3147 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |