| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 j(not_sign, &done, Label::kNear); | 313 j(not_sign, &done, Label::kNear); |
| 314 ExternalReference uint32_bias = | 314 ExternalReference uint32_bias = |
| 315 ExternalReference::address_of_uint32_bias(); | 315 ExternalReference::address_of_uint32_bias(); |
| 316 fld_d(Operand::StaticVariable(uint32_bias)); | 316 fld_d(Operand::StaticVariable(uint32_bias)); |
| 317 faddp(1); | 317 faddp(1); |
| 318 bind(&done); | 318 bind(&done); |
| 319 add(esp, Immediate(kPointerSize)); | 319 add(esp, Immediate(kPointerSize)); |
| 320 } | 320 } |
| 321 | 321 |
| 322 | 322 |
| 323 void MacroAssembler::RecordWriteArray( | |
| 324 Register object, Register value, Register index, SaveFPRegsMode save_fp, | |
| 325 RememberedSetAction remembered_set_action, SmiCheck smi_check, | |
| 326 PointersToHereCheck pointers_to_here_check_for_value) { | |
| 327 // First, check if a write barrier is even needed. The tests below | |
| 328 // catch stores of Smis. | |
| 329 Label done; | |
| 330 | |
| 331 // Skip barrier if writing a smi. | |
| 332 if (smi_check == INLINE_SMI_CHECK) { | |
| 333 DCHECK_EQ(0, kSmiTag); | |
| 334 test(value, Immediate(kSmiTagMask)); | |
| 335 j(zero, &done); | |
| 336 } | |
| 337 | |
| 338 // Array access: calculate the destination address in the same manner as | |
| 339 // KeyedStoreIC::GenerateGeneric. Multiply a smi by 2 to get an offset | |
| 340 // into an array of words. | |
| 341 Register dst = index; | |
| 342 lea(dst, Operand(object, index, times_half_pointer_size, | |
| 343 FixedArray::kHeaderSize - kHeapObjectTag)); | |
| 344 | |
| 345 RecordWrite(object, dst, value, save_fp, remembered_set_action, | |
| 346 OMIT_SMI_CHECK, pointers_to_here_check_for_value); | |
| 347 | |
| 348 bind(&done); | |
| 349 | |
| 350 // Clobber clobbered input registers when running with the debug-code flag | |
| 351 // turned on to provoke errors. | |
| 352 if (emit_debug_code()) { | |
| 353 mov(value, Immediate(bit_cast<int32_t>(kZapValue))); | |
| 354 mov(index, Immediate(bit_cast<int32_t>(kZapValue))); | |
| 355 } | |
| 356 } | |
| 357 | |
| 358 | |
| 359 void MacroAssembler::RecordWriteField( | 323 void MacroAssembler::RecordWriteField( |
| 360 Register object, int offset, Register value, Register dst, | 324 Register object, int offset, Register value, Register dst, |
| 361 SaveFPRegsMode save_fp, RememberedSetAction remembered_set_action, | 325 SaveFPRegsMode save_fp, RememberedSetAction remembered_set_action, |
| 362 SmiCheck smi_check, PointersToHereCheck pointers_to_here_check_for_value) { | 326 SmiCheck smi_check, PointersToHereCheck pointers_to_here_check_for_value) { |
| 363 // First, check if a write barrier is even needed. The tests below | 327 // First, check if a write barrier is even needed. The tests below |
| 364 // catch stores of Smis. | 328 // catch stores of Smis. |
| 365 Label done; | 329 Label done; |
| 366 | 330 |
| 367 // Skip barrier if writing a smi. | 331 // Skip barrier if writing a smi. |
| 368 if (smi_check == INLINE_SMI_CHECK) { | 332 if (smi_check == INLINE_SMI_CHECK) { |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 713 SmiCheckType smi_check_type) { | 677 SmiCheckType smi_check_type) { |
| 714 if (smi_check_type == DO_SMI_CHECK) { | 678 if (smi_check_type == DO_SMI_CHECK) { |
| 715 JumpIfSmi(obj, fail); | 679 JumpIfSmi(obj, fail); |
| 716 } | 680 } |
| 717 | 681 |
| 718 CompareMap(obj, map); | 682 CompareMap(obj, map); |
| 719 j(not_equal, fail); | 683 j(not_equal, fail); |
| 720 } | 684 } |
| 721 | 685 |
| 722 | 686 |
| 723 void MacroAssembler::DispatchWeakMap(Register obj, Register scratch1, | |
| 724 Register scratch2, Handle<WeakCell> cell, | |
| 725 Handle<Code> success, | |
| 726 SmiCheckType smi_check_type) { | |
| 727 Label fail; | |
| 728 if (smi_check_type == DO_SMI_CHECK) { | |
| 729 JumpIfSmi(obj, &fail); | |
| 730 } | |
| 731 mov(scratch1, FieldOperand(obj, HeapObject::kMapOffset)); | |
| 732 CmpWeakValue(scratch1, cell, scratch2); | |
| 733 j(equal, success); | |
| 734 | |
| 735 bind(&fail); | |
| 736 } | |
| 737 | |
| 738 | |
| 739 Condition MacroAssembler::IsObjectStringType(Register heap_object, | 687 Condition MacroAssembler::IsObjectStringType(Register heap_object, |
| 740 Register map, | 688 Register map, |
| 741 Register instance_type) { | 689 Register instance_type) { |
| 742 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); | 690 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); |
| 743 movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); | 691 movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); |
| 744 STATIC_ASSERT(kNotStringTag != 0); | 692 STATIC_ASSERT(kNotStringTag != 0); |
| 745 test(instance_type, Immediate(kIsNotStringMask)); | 693 test(instance_type, Immediate(kIsNotStringMask)); |
| 746 return zero; | 694 return zero; |
| 747 } | 695 } |
| 748 | 696 |
| 749 | 697 |
| 750 Condition MacroAssembler::IsObjectNameType(Register heap_object, | |
| 751 Register map, | |
| 752 Register instance_type) { | |
| 753 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); | |
| 754 movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); | |
| 755 cmpb(instance_type, Immediate(LAST_NAME_TYPE)); | |
| 756 return below_equal; | |
| 757 } | |
| 758 | |
| 759 | |
| 760 void MacroAssembler::FCmp() { | 698 void MacroAssembler::FCmp() { |
| 761 fucompp(); | 699 fucompp(); |
| 762 push(eax); | 700 push(eax); |
| 763 fnstsw_ax(); | 701 fnstsw_ax(); |
| 764 sahf(); | 702 sahf(); |
| 765 pop(eax); | 703 pop(eax); |
| 766 } | 704 } |
| 767 | 705 |
| 768 | 706 |
| 769 void MacroAssembler::FXamMinusZero() { | 707 void MacroAssembler::FXamMinusZero() { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 | 753 |
| 816 void MacroAssembler::X87SetFPUCW(int cw) { | 754 void MacroAssembler::X87SetFPUCW(int cw) { |
| 817 RecordComment("-- X87SetFPUCW start --"); | 755 RecordComment("-- X87SetFPUCW start --"); |
| 818 push(Immediate(cw)); | 756 push(Immediate(cw)); |
| 819 fldcw(MemOperand(esp, 0)); | 757 fldcw(MemOperand(esp, 0)); |
| 820 add(esp, Immediate(kPointerSize)); | 758 add(esp, Immediate(kPointerSize)); |
| 821 RecordComment("-- X87SetFPUCW end--"); | 759 RecordComment("-- X87SetFPUCW end--"); |
| 822 } | 760 } |
| 823 | 761 |
| 824 | 762 |
| 825 void MacroAssembler::AssertNumber(Register object) { | |
| 826 if (emit_debug_code()) { | |
| 827 Label ok; | |
| 828 JumpIfSmi(object, &ok); | |
| 829 cmp(FieldOperand(object, HeapObject::kMapOffset), | |
| 830 isolate()->factory()->heap_number_map()); | |
| 831 Check(equal, kOperandNotANumber); | |
| 832 bind(&ok); | |
| 833 } | |
| 834 } | |
| 835 | |
| 836 void MacroAssembler::AssertNotNumber(Register object) { | |
| 837 if (emit_debug_code()) { | |
| 838 test(object, Immediate(kSmiTagMask)); | |
| 839 Check(not_equal, kOperandIsANumber); | |
| 840 cmp(FieldOperand(object, HeapObject::kMapOffset), | |
| 841 isolate()->factory()->heap_number_map()); | |
| 842 Check(not_equal, kOperandIsANumber); | |
| 843 } | |
| 844 } | |
| 845 | |
| 846 void MacroAssembler::AssertSmi(Register object) { | 763 void MacroAssembler::AssertSmi(Register object) { |
| 847 if (emit_debug_code()) { | 764 if (emit_debug_code()) { |
| 848 test(object, Immediate(kSmiTagMask)); | 765 test(object, Immediate(kSmiTagMask)); |
| 849 Check(equal, kOperandIsNotASmi); | 766 Check(equal, kOperandIsNotASmi); |
| 850 } | 767 } |
| 851 } | 768 } |
| 852 | 769 |
| 853 | 770 |
| 854 void MacroAssembler::AssertString(Register object) { | |
| 855 if (emit_debug_code()) { | |
| 856 test(object, Immediate(kSmiTagMask)); | |
| 857 Check(not_equal, kOperandIsASmiAndNotAString); | |
| 858 push(object); | |
| 859 mov(object, FieldOperand(object, HeapObject::kMapOffset)); | |
| 860 CmpInstanceType(object, FIRST_NONSTRING_TYPE); | |
| 861 pop(object); | |
| 862 Check(below, kOperandIsNotAString); | |
| 863 } | |
| 864 } | |
| 865 | |
| 866 | |
| 867 void MacroAssembler::AssertName(Register object) { | |
| 868 if (emit_debug_code()) { | |
| 869 test(object, Immediate(kSmiTagMask)); | |
| 870 Check(not_equal, kOperandIsASmiAndNotAName); | |
| 871 push(object); | |
| 872 mov(object, FieldOperand(object, HeapObject::kMapOffset)); | |
| 873 CmpInstanceType(object, LAST_NAME_TYPE); | |
| 874 pop(object); | |
| 875 Check(below_equal, kOperandIsNotAName); | |
| 876 } | |
| 877 } | |
| 878 | |
| 879 | |
| 880 void MacroAssembler::AssertFunction(Register object) { | 771 void MacroAssembler::AssertFunction(Register object) { |
| 881 if (emit_debug_code()) { | 772 if (emit_debug_code()) { |
| 882 test(object, Immediate(kSmiTagMask)); | 773 test(object, Immediate(kSmiTagMask)); |
| 883 Check(not_equal, kOperandIsASmiAndNotAFunction); | 774 Check(not_equal, kOperandIsASmiAndNotAFunction); |
| 884 Push(object); | 775 Push(object); |
| 885 CmpObjectType(object, JS_FUNCTION_TYPE, object); | 776 CmpObjectType(object, JS_FUNCTION_TYPE, object); |
| 886 Pop(object); | 777 Pop(object); |
| 887 Check(equal, kOperandIsNotAFunction); | 778 Check(equal, kOperandIsNotAFunction); |
| 888 } | 779 } |
| 889 } | 780 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 904 if (emit_debug_code()) { | 795 if (emit_debug_code()) { |
| 905 test(object, Immediate(kSmiTagMask)); | 796 test(object, Immediate(kSmiTagMask)); |
| 906 Check(not_equal, kOperandIsASmiAndNotAGeneratorObject); | 797 Check(not_equal, kOperandIsASmiAndNotAGeneratorObject); |
| 907 Push(object); | 798 Push(object); |
| 908 CmpObjectType(object, JS_GENERATOR_OBJECT_TYPE, object); | 799 CmpObjectType(object, JS_GENERATOR_OBJECT_TYPE, object); |
| 909 Pop(object); | 800 Pop(object); |
| 910 Check(equal, kOperandIsNotAGeneratorObject); | 801 Check(equal, kOperandIsNotAGeneratorObject); |
| 911 } | 802 } |
| 912 } | 803 } |
| 913 | 804 |
| 914 void MacroAssembler::AssertReceiver(Register object) { | |
| 915 if (emit_debug_code()) { | |
| 916 test(object, Immediate(kSmiTagMask)); | |
| 917 Check(not_equal, kOperandIsASmiAndNotAReceiver); | |
| 918 Push(object); | |
| 919 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); | |
| 920 CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, object); | |
| 921 Pop(object); | |
| 922 Check(above_equal, kOperandIsNotAReceiver); | |
| 923 } | |
| 924 } | |
| 925 | |
| 926 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object) { | 805 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object) { |
| 927 if (emit_debug_code()) { | 806 if (emit_debug_code()) { |
| 928 Label done_checking; | 807 Label done_checking; |
| 929 AssertNotSmi(object); | 808 AssertNotSmi(object); |
| 930 cmp(object, isolate()->factory()->undefined_value()); | 809 cmp(object, isolate()->factory()->undefined_value()); |
| 931 j(equal, &done_checking); | 810 j(equal, &done_checking); |
| 932 cmp(FieldOperand(object, 0), | 811 cmp(FieldOperand(object, 0), |
| 933 Immediate(isolate()->factory()->allocation_site_map())); | 812 Immediate(isolate()->factory()->allocation_site_map())); |
| 934 Assert(equal, kExpectedUndefinedOrCell); | 813 Assert(equal, kExpectedUndefinedOrCell); |
| 935 bind(&done_checking); | 814 bind(&done_checking); |
| (...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1577 bit_index += kSmiTagSize + kSmiShiftSize; | 1456 bit_index += kSmiTagSize + kSmiShiftSize; |
| 1578 DCHECK(base::bits::IsPowerOfTwo32(kBitsPerByte)); | 1457 DCHECK(base::bits::IsPowerOfTwo32(kBitsPerByte)); |
| 1579 int byte_index = bit_index / kBitsPerByte; | 1458 int byte_index = bit_index / kBitsPerByte; |
| 1580 int byte_bit_index = bit_index & (kBitsPerByte - 1); | 1459 int byte_bit_index = bit_index & (kBitsPerByte - 1); |
| 1581 test_b(FieldOperand(object, field_offset + byte_index), | 1460 test_b(FieldOperand(object, field_offset + byte_index), |
| 1582 Immediate(1 << byte_bit_index)); | 1461 Immediate(1 << byte_bit_index)); |
| 1583 } | 1462 } |
| 1584 | 1463 |
| 1585 | 1464 |
| 1586 | 1465 |
| 1587 void MacroAssembler::NegativeZeroTest(Register result, | |
| 1588 Register op, | |
| 1589 Label* then_label) { | |
| 1590 Label ok; | |
| 1591 test(result, result); | |
| 1592 j(not_zero, &ok, Label::kNear); | |
| 1593 test(op, op); | |
| 1594 j(sign, then_label, Label::kNear); | |
| 1595 bind(&ok); | |
| 1596 } | |
| 1597 | |
| 1598 | |
| 1599 void MacroAssembler::NegativeZeroTest(Register result, | |
| 1600 Register op1, | |
| 1601 Register op2, | |
| 1602 Register scratch, | |
| 1603 Label* then_label) { | |
| 1604 Label ok; | |
| 1605 test(result, result); | |
| 1606 j(not_zero, &ok, Label::kNear); | |
| 1607 mov(scratch, op1); | |
| 1608 or_(scratch, op2); | |
| 1609 j(sign, then_label, Label::kNear); | |
| 1610 bind(&ok); | |
| 1611 } | |
| 1612 | |
| 1613 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) { | 1466 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) { |
| 1614 DCHECK(AllowThisStubCall(stub)); // Calls are not allowed in some stubs. | 1467 DCHECK(AllowThisStubCall(stub)); // Calls are not allowed in some stubs. |
| 1615 call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id); | 1468 call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id); |
| 1616 } | 1469 } |
| 1617 | 1470 |
| 1618 | 1471 |
| 1619 void MacroAssembler::TailCallStub(CodeStub* stub) { | 1472 void MacroAssembler::TailCallStub(CodeStub* stub) { |
| 1620 jmp(stub->GetCode(), RelocInfo::CODE_TARGET); | 1473 jmp(stub->GetCode(), RelocInfo::CODE_TARGET); |
| 1621 } | 1474 } |
| 1622 | 1475 |
| 1623 | 1476 |
| 1624 void MacroAssembler::StubReturn(int argc) { | |
| 1625 DCHECK(argc >= 1 && generating_stub()); | |
| 1626 ret((argc - 1) * kPointerSize); | |
| 1627 } | |
| 1628 | |
| 1629 | 1477 |
| 1630 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { | 1478 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { |
| 1631 return has_frame_ || !stub->SometimesSetsUpAFrame(); | 1479 return has_frame_ || !stub->SometimesSetsUpAFrame(); |
| 1632 } | 1480 } |
| 1633 | 1481 |
| 1634 void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments, | 1482 void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments, |
| 1635 SaveFPRegsMode save_doubles) { | 1483 SaveFPRegsMode save_doubles) { |
| 1636 // If the expected number of arguments of the runtime function is | 1484 // If the expected number of arguments of the runtime function is |
| 1637 // constant, we check that the actual number of arguments match the | 1485 // constant, we check that the actual number of arguments match the |
| 1638 // expectation. | 1486 // expectation. |
| (...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2055 mov(result, object); | 1903 mov(result, object); |
| 2056 } | 1904 } |
| 2057 | 1905 |
| 2058 | 1906 |
| 2059 void MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) { | 1907 void MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) { |
| 2060 cmp(reg, object); | 1908 cmp(reg, object); |
| 2061 } | 1909 } |
| 2062 | 1910 |
| 2063 void MacroAssembler::PushHeapObject(Handle<HeapObject> object) { Push(object); } | 1911 void MacroAssembler::PushHeapObject(Handle<HeapObject> object) { Push(object); } |
| 2064 | 1912 |
| 2065 void MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell, | |
| 2066 Register scratch) { | |
| 2067 mov(scratch, cell); | |
| 2068 cmp(value, FieldOperand(scratch, WeakCell::kValueOffset)); | |
| 2069 } | |
| 2070 | |
| 2071 | |
| 2072 void MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) { | 1913 void MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) { |
| 2073 mov(value, cell); | 1914 mov(value, cell); |
| 2074 mov(value, FieldOperand(value, WeakCell::kValueOffset)); | 1915 mov(value, FieldOperand(value, WeakCell::kValueOffset)); |
| 2075 } | 1916 } |
| 2076 | 1917 |
| 2077 | 1918 |
| 2078 void MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell, | 1919 void MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell, |
| 2079 Label* miss) { | 1920 Label* miss) { |
| 2080 GetWeakValue(value, cell); | 1921 GetWeakValue(value, cell); |
| 2081 JumpIfSmi(value, miss); | 1922 JumpIfSmi(value, miss); |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2244 bind(&skip); | 2085 bind(&skip); |
| 2245 } | 2086 } |
| 2246 } | 2087 } |
| 2247 | 2088 |
| 2248 | 2089 |
| 2249 void MacroAssembler::Assert(Condition cc, BailoutReason reason) { | 2090 void MacroAssembler::Assert(Condition cc, BailoutReason reason) { |
| 2250 if (emit_debug_code()) Check(cc, reason); | 2091 if (emit_debug_code()) Check(cc, reason); |
| 2251 } | 2092 } |
| 2252 | 2093 |
| 2253 | 2094 |
| 2254 void MacroAssembler::AssertFastElements(Register elements) { | |
| 2255 if (emit_debug_code()) { | |
| 2256 Factory* factory = isolate()->factory(); | |
| 2257 Label ok; | |
| 2258 cmp(FieldOperand(elements, HeapObject::kMapOffset), | |
| 2259 Immediate(factory->fixed_array_map())); | |
| 2260 j(equal, &ok); | |
| 2261 cmp(FieldOperand(elements, HeapObject::kMapOffset), | |
| 2262 Immediate(factory->fixed_double_array_map())); | |
| 2263 j(equal, &ok); | |
| 2264 cmp(FieldOperand(elements, HeapObject::kMapOffset), | |
| 2265 Immediate(factory->fixed_cow_array_map())); | |
| 2266 j(equal, &ok); | |
| 2267 Abort(kJSObjectWithFastElementsMapHasSlowElements); | |
| 2268 bind(&ok); | |
| 2269 } | |
| 2270 } | |
| 2271 | |
| 2272 | 2095 |
| 2273 void MacroAssembler::Check(Condition cc, BailoutReason reason) { | 2096 void MacroAssembler::Check(Condition cc, BailoutReason reason) { |
| 2274 Label L; | 2097 Label L; |
| 2275 j(cc, &L); | 2098 j(cc, &L); |
| 2276 Abort(reason); | 2099 Abort(reason); |
| 2277 // will not return here | 2100 // will not return here |
| 2278 bind(&L); | 2101 bind(&L); |
| 2279 } | 2102 } |
| 2280 | 2103 |
| 2281 | 2104 |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2756 mov(eax, dividend); | 2579 mov(eax, dividend); |
| 2757 shr(eax, 31); | 2580 shr(eax, 31); |
| 2758 add(edx, eax); | 2581 add(edx, eax); |
| 2759 } | 2582 } |
| 2760 | 2583 |
| 2761 | 2584 |
| 2762 } // namespace internal | 2585 } // namespace internal |
| 2763 } // namespace v8 | 2586 } // namespace v8 |
| 2764 | 2587 |
| 2765 #endif // V8_TARGET_ARCH_X87 | 2588 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |