Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: src/s390/codegen-s390.cc

Issue 1725243004: S390: Initial impl of S390 asm, masm, code-stubs,... (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Updated BUILD.gn + cpu-s390.cc to addr @jochen's comments. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/ppc/codegen-ppc.h" 5 #include "src/s390/codegen-s390.h"
6 6
7 #if V8_TARGET_ARCH_PPC 7 #if V8_TARGET_ARCH_S390
8 8
9 #include "src/codegen.h" 9 #include "src/codegen.h"
10 #include "src/macro-assembler.h" 10 #include "src/macro-assembler.h"
11 #include "src/ppc/simulator-ppc.h" 11 #include "src/s390/simulator-s390.h"
12 12
13 namespace v8 { 13 namespace v8 {
14 namespace internal { 14 namespace internal {
15 15
16
17 #define __ masm. 16 #define __ masm.
18 17
19
20 #if defined(USE_SIMULATOR) 18 #if defined(USE_SIMULATOR)
21 byte* fast_exp_ppc_machine_code = nullptr; 19 byte* fast_exp_s390_machine_code = nullptr;
22 double fast_exp_simulator(double x, Isolate* isolate) { 20 double fast_exp_simulator(double x, Isolate* isolate) {
23 return Simulator::current(isolate) 21 return Simulator::current(isolate)->CallFPReturnsDouble(
24 ->CallFPReturnsDouble(fast_exp_ppc_machine_code, x, 0); 22 fast_exp_s390_machine_code, x, 0);
25 } 23 }
26 #endif 24 #endif
27 25
28
29 UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) { 26 UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) {
30 size_t actual_size; 27 size_t actual_size;
31 byte* buffer = 28 byte* buffer =
32 static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true)); 29 static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
33 if (buffer == nullptr) return nullptr; 30 if (buffer == nullptr) return nullptr;
34 ExternalReference::InitializeMathExpData(); 31 ExternalReference::InitializeMathExpData();
35 32
36 MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size), 33 MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
37 CodeObjectRequired::kNo); 34 CodeObjectRequired::kNo);
38 35
39 { 36 {
40 DoubleRegister input = d1; 37 DoubleRegister input = d0;
41 DoubleRegister result = d2; 38 DoubleRegister result = d2;
42 DoubleRegister double_scratch1 = d3; 39 DoubleRegister double_scratch1 = d3;
43 DoubleRegister double_scratch2 = d4; 40 DoubleRegister double_scratch2 = d4;
44 Register temp1 = r7; 41 Register temp1 = r6;
45 Register temp2 = r8; 42 Register temp2 = r7;
46 Register temp3 = r9; 43 Register temp3 = r8;
47
48 // Called from C
49 __ function_descriptor();
50 44
51 __ Push(temp3, temp2, temp1); 45 __ Push(temp3, temp2, temp1);
52 MathExpGenerator::EmitMathExp(&masm, input, result, double_scratch1, 46 MathExpGenerator::EmitMathExp(&masm, input, result, double_scratch1,
53 double_scratch2, temp1, temp2, temp3); 47 double_scratch2, temp1, temp2, temp3);
54 __ Pop(temp3, temp2, temp1); 48 __ Pop(temp3, temp2, temp1);
55 __ fmr(d1, result); 49 __ ldr(d0, result);
56 __ Ret(); 50 __ Ret();
57 } 51 }
58 52
59 CodeDesc desc; 53 CodeDesc desc;
60 masm.GetCode(&desc); 54 masm.GetCode(&desc);
61 DCHECK(ABI_USES_FUNCTION_DESCRIPTORS || !RelocInfo::RequiresRelocation(desc)); 55 DCHECK(ABI_USES_FUNCTION_DESCRIPTORS || !RelocInfo::RequiresRelocation(desc));
62 56
63 Assembler::FlushICache(isolate, buffer, actual_size); 57 Assembler::FlushICache(isolate, buffer, actual_size);
64 base::OS::ProtectCode(buffer, actual_size); 58 base::OS::ProtectCode(buffer, actual_size);
65 59
66 #if !defined(USE_SIMULATOR) 60 #if !defined(USE_SIMULATOR)
67 return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer); 61 return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
68 #else 62 #else
69 fast_exp_ppc_machine_code = buffer; 63 fast_exp_s390_machine_code = buffer;
70 return &fast_exp_simulator; 64 return &fast_exp_simulator;
71 #endif 65 #endif
72 } 66 }
73 67
74
75 UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) { 68 UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
76 #if defined(USE_SIMULATOR) 69 #if defined(USE_SIMULATOR)
77 return nullptr; 70 return nullptr;
78 #else 71 #else
79 size_t actual_size; 72 size_t actual_size;
80 byte* buffer = 73 byte* buffer =
81 static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true)); 74 static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
82 if (buffer == nullptr) return nullptr; 75 if (buffer == nullptr) return nullptr;
83 76
84 MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size), 77 MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
85 CodeObjectRequired::kNo); 78 CodeObjectRequired::kNo);
86 79
87 // Called from C 80 __ MovFromFloatParameter(d0);
88 __ function_descriptor(); 81 __ sqdbr(d0, d0);
89 82 __ MovToFloatResult(d0);
90 __ MovFromFloatParameter(d1);
91 __ fsqrt(d1, d1);
92 __ MovToFloatResult(d1);
93 __ Ret(); 83 __ Ret();
94 84
95 CodeDesc desc; 85 CodeDesc desc;
96 masm.GetCode(&desc); 86 masm.GetCode(&desc);
97 DCHECK(ABI_USES_FUNCTION_DESCRIPTORS || !RelocInfo::RequiresRelocation(desc)); 87 DCHECK(ABI_USES_FUNCTION_DESCRIPTORS || !RelocInfo::RequiresRelocation(desc));
98 88
99 Assembler::FlushICache(isolate, buffer, actual_size); 89 Assembler::FlushICache(isolate, buffer, actual_size);
100 base::OS::ProtectCode(buffer, actual_size); 90 base::OS::ProtectCode(buffer, actual_size);
101 return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer); 91 return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
102 #endif 92 #endif
103 } 93 }
104 94
105 #undef __ 95 #undef __
106 96
107
108 // ------------------------------------------------------------------------- 97 // -------------------------------------------------------------------------
109 // Platform-specific RuntimeCallHelper functions. 98 // Platform-specific RuntimeCallHelper functions.
110 99
111 void StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const { 100 void StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const {
112 masm->EnterFrame(StackFrame::INTERNAL); 101 masm->EnterFrame(StackFrame::INTERNAL);
113 DCHECK(!masm->has_frame()); 102 DCHECK(!masm->has_frame());
114 masm->set_has_frame(true); 103 masm->set_has_frame(true);
115 } 104 }
116 105
117
118 void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { 106 void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const {
119 masm->LeaveFrame(StackFrame::INTERNAL); 107 masm->LeaveFrame(StackFrame::INTERNAL);
120 DCHECK(masm->has_frame()); 108 DCHECK(masm->has_frame());
121 masm->set_has_frame(false); 109 masm->set_has_frame(false);
122 } 110 }
123 111
124
125 // ------------------------------------------------------------------------- 112 // -------------------------------------------------------------------------
126 // Code generators 113 // Code generators
127 114
128 #define __ ACCESS_MASM(masm) 115 #define __ ACCESS_MASM(masm)
129 116
130 void ElementsTransitionGenerator::GenerateMapChangeElementsTransition( 117 void ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
131 MacroAssembler* masm, Register receiver, Register key, Register value, 118 MacroAssembler* masm, Register receiver, Register key, Register value,
132 Register target_map, AllocationSiteMode mode, 119 Register target_map, AllocationSiteMode mode,
133 Label* allocation_memento_found) { 120 Label* allocation_memento_found) {
134 Register scratch_elements = r7; 121 Register scratch_elements = r6;
135 DCHECK(!AreAliased(receiver, key, value, target_map, scratch_elements)); 122 DCHECK(!AreAliased(receiver, key, value, target_map, scratch_elements));
136 123
137 if (mode == TRACK_ALLOCATION_SITE) { 124 if (mode == TRACK_ALLOCATION_SITE) {
138 DCHECK(allocation_memento_found != NULL); 125 DCHECK(allocation_memento_found != NULL);
139 __ JumpIfJSArrayHasAllocationMemento(receiver, scratch_elements, 126 __ JumpIfJSArrayHasAllocationMemento(receiver, scratch_elements,
140 allocation_memento_found); 127 allocation_memento_found);
141 } 128 }
142 129
143 // Set transitioned map. 130 // Set transitioned map.
144 __ StoreP(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset), r0); 131 __ StoreP(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
145 __ RecordWriteField(receiver, HeapObject::kMapOffset, target_map, r11, 132 __ RecordWriteField(receiver, HeapObject::kMapOffset, target_map, r1,
146 kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET, 133 kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
147 OMIT_SMI_CHECK); 134 OMIT_SMI_CHECK);
148 } 135 }
149 136
150
151 void ElementsTransitionGenerator::GenerateSmiToDouble( 137 void ElementsTransitionGenerator::GenerateSmiToDouble(
152 MacroAssembler* masm, Register receiver, Register key, Register value, 138 MacroAssembler* masm, Register receiver, Register key, Register value,
153 Register target_map, AllocationSiteMode mode, Label* fail) { 139 Register target_map, AllocationSiteMode mode, Label* fail) {
154 // lr contains the return address 140 // lr contains the return address
155 Label loop, entry, convert_hole, only_change_map, done; 141 Label loop, entry, convert_hole, gc_required, only_change_map, done;
156 Register elements = r7; 142 Register elements = r6;
157 Register length = r8; 143 Register length = r7;
158 Register array = r9; 144 Register array = r8;
159 Register array_end = array; 145 Register array_end = array;
160 146
161 // target_map parameter can be clobbered. 147 // target_map parameter can be clobbered.
162 Register scratch1 = target_map; 148 Register scratch1 = target_map;
163 Register scratch2 = r10; 149 Register scratch2 = r1;
164 Register scratch3 = r11;
165 Register scratch4 = r14;
166 150
167 // Verify input registers don't conflict with locals. 151 // Verify input registers don't conflict with locals.
168 DCHECK(!AreAliased(receiver, key, value, target_map, elements, length, array, 152 DCHECK(!AreAliased(receiver, key, value, target_map, elements, length, array,
169 scratch2)); 153 scratch2));
170 154
171 if (mode == TRACK_ALLOCATION_SITE) { 155 if (mode == TRACK_ALLOCATION_SITE) {
172 __ JumpIfJSArrayHasAllocationMemento(receiver, elements, fail); 156 __ JumpIfJSArrayHasAllocationMemento(receiver, elements, fail);
173 } 157 }
174 158
175 // Check for empty arrays, which only require a map transition and no changes 159 // Check for empty arrays, which only require a map transition and no changes
176 // to the backing store. 160 // to the backing store.
177 __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 161 __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
178 __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex); 162 __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex);
179 __ beq(&only_change_map); 163 __ beq(&only_change_map, Label::kNear);
164
165 // Preserve lr and use r14 as a temporary register.
166 __ push(r14);
180 167
181 __ LoadP(length, FieldMemOperand(elements, FixedArray::kLengthOffset)); 168 __ LoadP(length, FieldMemOperand(elements, FixedArray::kLengthOffset));
182 // length: number of elements (smi-tagged) 169 // length: number of elements (smi-tagged)
183 170
184 // Allocate new FixedDoubleArray. 171 // Allocate new FixedDoubleArray.
185 __ SmiToDoubleArrayOffset(scratch3, length); 172 __ SmiToDoubleArrayOffset(r14, length);
186 __ addi(scratch3, scratch3, Operand(FixedDoubleArray::kHeaderSize)); 173 __ AddP(r14, Operand(FixedDoubleArray::kHeaderSize));
187 __ Allocate(scratch3, array, scratch4, scratch2, fail, DOUBLE_ALIGNMENT); 174 __ Allocate(r14, array, r9, scratch2, &gc_required, DOUBLE_ALIGNMENT);
188 // array: destination FixedDoubleArray, not tagged as heap object.
189 // elements: source FixedArray.
190 175
191 // Set destination FixedDoubleArray's length and map. 176 // Set destination FixedDoubleArray's length and map.
192 __ LoadRoot(scratch2, Heap::kFixedDoubleArrayMapRootIndex); 177 __ LoadRoot(scratch2, Heap::kFixedDoubleArrayMapRootIndex);
193 __ StoreP(length, MemOperand(array, FixedDoubleArray::kLengthOffset)); 178 __ StoreP(length, MemOperand(array, FixedDoubleArray::kLengthOffset));
194 // Update receiver's map. 179 // Update receiver's map.
195 __ StoreP(scratch2, MemOperand(array, HeapObject::kMapOffset)); 180 __ StoreP(scratch2, MemOperand(array, HeapObject::kMapOffset));
196 181
197 __ StoreP(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset), r0); 182 __ StoreP(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
198 __ RecordWriteField(receiver, HeapObject::kMapOffset, target_map, scratch2, 183 __ RecordWriteField(receiver, HeapObject::kMapOffset, target_map, scratch2,
199 kLRHasNotBeenSaved, kDontSaveFPRegs, OMIT_REMEMBERED_SET, 184 kLRHasBeenSaved, kDontSaveFPRegs, OMIT_REMEMBERED_SET,
200 OMIT_SMI_CHECK); 185 OMIT_SMI_CHECK);
201 // Replace receiver's backing store with newly created FixedDoubleArray. 186 // Replace receiver's backing store with newly created FixedDoubleArray.
202 __ addi(scratch1, array, Operand(kHeapObjectTag)); 187 __ AddP(scratch1, array, Operand(kHeapObjectTag));
203 __ StoreP(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset), r0); 188 __ StoreP(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset));
204 __ RecordWriteField(receiver, JSObject::kElementsOffset, scratch1, scratch2, 189 __ RecordWriteField(receiver, JSObject::kElementsOffset, scratch1, scratch2,
205 kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET, 190 kLRHasBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
206 OMIT_SMI_CHECK); 191 OMIT_SMI_CHECK);
207 192
208 // Prepare for conversion loop. 193 // Prepare for conversion loop.
209 __ addi(scratch1, elements, 194 __ AddP(target_map, elements,
210 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 195 Operand(FixedArray::kHeaderSize - kHeapObjectTag));
211 __ addi(scratch2, array, Operand(FixedDoubleArray::kHeaderSize)); 196 __ AddP(r9, array, Operand(FixedDoubleArray::kHeaderSize));
212 __ SmiToDoubleArrayOffset(array_end, length); 197 __ SmiToDoubleArrayOffset(array, length);
213 __ add(array_end, scratch2, array_end); 198 __ AddP(array_end, r9, array);
214 // Repurpose registers no longer in use. 199 // Repurpose registers no longer in use.
215 #if V8_TARGET_ARCH_PPC64 200 #if V8_TARGET_ARCH_S390X
216 Register hole_int64 = elements; 201 Register hole_int64 = elements;
217 __ mov(hole_int64, Operand(kHoleNanInt64));
218 #else 202 #else
219 Register hole_lower = elements; 203 Register hole_lower = elements;
220 Register hole_upper = length; 204 Register hole_upper = length;
221 __ mov(hole_lower, Operand(kHoleNanLower32));
222 __ mov(hole_upper, Operand(kHoleNanUpper32));
223 #endif 205 #endif
224 // scratch1: begin of source FixedArray element fields, not tagged 206 // scratch1: begin of source FixedArray element fields, not tagged
225 // hole_lower: kHoleNanLower32 OR hol_int64 207 // hole_lower: kHoleNanLower32 OR hol_int64
226 // hole_upper: kHoleNanUpper32 208 // hole_upper: kHoleNanUpper32
227 // array_end: end of destination FixedDoubleArray, not tagged 209 // array_end: end of destination FixedDoubleArray, not tagged
228 // scratch2: begin of FixedDoubleArray element fields, not tagged 210 // scratch2: begin of FixedDoubleArray element fields, not tagged
229 211
230 __ b(&entry); 212 __ b(&entry, Label::kNear);
231 213
232 __ bind(&only_change_map); 214 __ bind(&only_change_map);
233 __ StoreP(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset), r0); 215 __ StoreP(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
234 __ RecordWriteField(receiver, HeapObject::kMapOffset, target_map, scratch2, 216 __ RecordWriteField(receiver, HeapObject::kMapOffset, target_map, scratch2,
235 kLRHasNotBeenSaved, kDontSaveFPRegs, OMIT_REMEMBERED_SET, 217 kLRHasNotBeenSaved, kDontSaveFPRegs, OMIT_REMEMBERED_SET,
236 OMIT_SMI_CHECK); 218 OMIT_SMI_CHECK);
237 __ b(&done); 219 __ b(&done, Label::kNear);
220
221 // Call into runtime if GC is required.
222 __ bind(&gc_required);
223 __ pop(r14);
224 __ b(fail);
238 225
239 // Convert and copy elements. 226 // Convert and copy elements.
240 __ bind(&loop); 227 __ bind(&loop);
241 __ LoadP(scratch3, MemOperand(scratch1)); 228 __ LoadP(r14, MemOperand(scratch1));
242 __ addi(scratch1, scratch1, Operand(kPointerSize)); 229 __ la(scratch1, MemOperand(scratch1, kPointerSize));
243 // scratch3: current element 230 // r1: current element
244 __ UntagAndJumpIfNotSmi(scratch3, scratch3, &convert_hole); 231 __ UntagAndJumpIfNotSmi(r14, r14, &convert_hole);
245 232
246 // Normal smi, convert to double and store. 233 // Normal smi, convert to double and store.
247 __ ConvertIntToDouble(scratch3, d0); 234 __ ConvertIntToDouble(r14, d0);
248 __ stfd(d0, MemOperand(scratch2, 0)); 235 __ StoreDouble(d0, MemOperand(r9, 0));
249 __ addi(scratch2, scratch2, Operand(8)); 236 __ la(r9, MemOperand(r9, 8));
250 __ b(&entry); 237
238 __ b(&entry, Label::kNear);
251 239
252 // Hole found, store the-hole NaN. 240 // Hole found, store the-hole NaN.
253 __ bind(&convert_hole); 241 __ bind(&convert_hole);
254 if (FLAG_debug_code) { 242 if (FLAG_debug_code) {
255 __ LoadP(scratch3, MemOperand(scratch1, -kPointerSize)); 243 // Restore a "smi-untagged" heap object.
256 __ CompareRoot(scratch3, Heap::kTheHoleValueRootIndex); 244 __ LoadP(r1, MemOperand(r5, -kPointerSize));
245 __ CompareRoot(r1, Heap::kTheHoleValueRootIndex);
257 __ Assert(eq, kObjectFoundInSmiOnlyArray); 246 __ Assert(eq, kObjectFoundInSmiOnlyArray);
258 } 247 }
259 #if V8_TARGET_ARCH_PPC64 248 #if V8_TARGET_ARCH_S390X
260 __ std(hole_int64, MemOperand(scratch2, 0)); 249 __ stg(hole_int64, MemOperand(r9, 0));
261 #else 250 #else
262 __ stw(hole_upper, MemOperand(scratch2, Register::kExponentOffset)); 251 __ StoreW(hole_upper, MemOperand(r9, Register::kExponentOffset));
263 __ stw(hole_lower, MemOperand(scratch2, Register::kMantissaOffset)); 252 __ StoreW(hole_lower, MemOperand(r9, Register::kMantissaOffset));
264 #endif 253 #endif
265 __ addi(scratch2, scratch2, Operand(8)); 254 __ AddP(r9, Operand(8));
266 255
267 __ bind(&entry); 256 __ bind(&entry);
268 __ cmp(scratch2, array_end); 257 __ CmpP(r9, array_end);
269 __ blt(&loop); 258 __ blt(&loop);
270 259
260 __ pop(r14);
271 __ bind(&done); 261 __ bind(&done);
272 } 262 }
273 263
274
275 void ElementsTransitionGenerator::GenerateDoubleToObject( 264 void ElementsTransitionGenerator::GenerateDoubleToObject(
276 MacroAssembler* masm, Register receiver, Register key, Register value, 265 MacroAssembler* masm, Register receiver, Register key, Register value,
277 Register target_map, AllocationSiteMode mode, Label* fail) { 266 Register target_map, AllocationSiteMode mode, Label* fail) {
278 // Register lr contains the return address. 267 // Register lr contains the return address.
279 Label loop, convert_hole, gc_required, only_change_map; 268 Label loop, convert_hole, gc_required, only_change_map;
280 Register elements = r7; 269 Register elements = r6;
281 Register array = r9; 270 Register array = r8;
282 Register length = r8; 271 Register length = r7;
283 Register scratch = r10; 272 Register scratch = r1;
284 Register scratch3 = r11;
285 Register hole_value = r14;
286 273
287 // Verify input registers don't conflict with locals. 274 // Verify input registers don't conflict with locals.
288 DCHECK(!AreAliased(receiver, key, value, target_map, elements, array, length, 275 DCHECK(!AreAliased(receiver, key, value, target_map, elements, array, length,
289 scratch)); 276 scratch));
290 277
291 if (mode == TRACK_ALLOCATION_SITE) { 278 if (mode == TRACK_ALLOCATION_SITE) {
292 __ JumpIfJSArrayHasAllocationMemento(receiver, elements, fail); 279 __ JumpIfJSArrayHasAllocationMemento(receiver, elements, fail);
293 } 280 }
294 281
295 // Check for empty arrays, which only require a map transition and no changes 282 // Check for empty arrays, which only require a map transition and no changes
296 // to the backing store. 283 // to the backing store.
297 __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 284 __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
298 __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex); 285 __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex);
299 __ beq(&only_change_map); 286 __ beq(&only_change_map);
300 287
301 __ Push(target_map, receiver, key, value); 288 __ Push(target_map, receiver, key, value);
302 __ LoadP(length, FieldMemOperand(elements, FixedArray::kLengthOffset)); 289 __ LoadP(length, FieldMemOperand(elements, FixedArray::kLengthOffset));
303 // elements: source FixedDoubleArray 290 // elements: source FixedDoubleArray
304 // length: number of elements (smi-tagged) 291 // length: number of elements (smi-tagged)
305 292
306 // Allocate new FixedArray. 293 // Allocate new FixedArray.
307 // Re-use value and target_map registers, as they have been saved on the 294 // Re-use value and target_map registers, as they have been saved on the
308 // stack. 295 // stack.
309 Register array_size = value; 296 Register array_size = value;
310 Register allocate_scratch = target_map; 297 Register allocate_scratch = target_map;
311 __ li(array_size, Operand(FixedDoubleArray::kHeaderSize)); 298 __ LoadImmP(array_size, Operand(FixedDoubleArray::kHeaderSize));
312 __ SmiToPtrArrayOffset(r0, length); 299 __ SmiToPtrArrayOffset(r0, length);
313 __ add(array_size, array_size, r0); 300 __ AddP(array_size, r0);
314 __ Allocate(array_size, array, allocate_scratch, scratch, &gc_required, 301 __ Allocate(array_size, array, allocate_scratch, scratch, &gc_required,
315 NO_ALLOCATION_FLAGS); 302 NO_ALLOCATION_FLAGS);
316 // array: destination FixedArray, not tagged as heap object 303 // array: destination FixedArray, not tagged as heap object
317 // Set destination FixedDoubleArray's length and map. 304 // Set destination FixedDoubleArray's length and map.
318 __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex); 305 __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
319 __ StoreP(length, MemOperand(array, FixedDoubleArray::kLengthOffset)); 306 __ StoreP(length, MemOperand(array, FixedDoubleArray::kLengthOffset));
320 __ StoreP(scratch, MemOperand(array, HeapObject::kMapOffset)); 307 __ StoreP(scratch, MemOperand(array, HeapObject::kMapOffset));
321 __ addi(array, array, Operand(kHeapObjectTag)); 308 __ AddP(array, Operand(kHeapObjectTag));
322 309
323 // Prepare for conversion loop. 310 // Prepare for conversion loop.
324 Register src_elements = elements; 311 Register src_elements = elements;
325 Register dst_elements = target_map; 312 Register dst_elements = target_map;
326 Register dst_end = length; 313 Register dst_end = length;
327 Register heap_number_map = scratch; 314 Register heap_number_map = scratch;
328 __ addi(src_elements, elements, 315 __ AddP(src_elements,
329 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); 316 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
330 __ SmiToPtrArrayOffset(length, length); 317 __ SmiToPtrArrayOffset(length, length);
331 __ LoadRoot(hole_value, Heap::kTheHoleValueRootIndex); 318 __ LoadRoot(r9, Heap::kTheHoleValueRootIndex);
332 319
333 Label initialization_loop, loop_done; 320 Label initialization_loop, loop_done;
334 __ ShiftRightImm(r0, length, Operand(kPointerSizeLog2), SetRC); 321 __ ShiftRightP(r0, length, Operand(kPointerSizeLog2));
335 __ beq(&loop_done, cr0); 322 __ beq(&loop_done, Label::kNear /*, cr0*/);
336 323
337 // Allocating heap numbers in the loop below can fail and cause a jump to 324 // Allocating heap numbers in the loop below can fail and cause a jump to
338 // gc_required. We can't leave a partly initialized FixedArray behind, 325 // gc_required. We can't leave a partly initialized FixedArray behind,
339 // so pessimistically fill it with holes now. 326 // so pessimistically fill it with holes now.
340 __ mtctr(r0); 327 __ AddP(dst_elements, array,
341 __ addi(dst_elements, array,
342 Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize)); 328 Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize));
343 __ bind(&initialization_loop); 329 __ bind(&initialization_loop);
344 __ StorePU(hole_value, MemOperand(dst_elements, kPointerSize)); 330 __ StoreP(r9, MemOperand(dst_elements, kPointerSize));
345 __ bdnz(&initialization_loop); 331 __ lay(dst_elements, MemOperand(dst_elements, kPointerSize));
332 __ BranchOnCount(r0, &initialization_loop);
346 333
347 __ addi(dst_elements, array, 334 __ AddP(dst_elements, array,
348 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 335 Operand(FixedArray::kHeaderSize - kHeapObjectTag));
349 __ add(dst_end, dst_elements, length); 336 __ AddP(dst_end, dst_elements, length);
350 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 337 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
351 // Using offsetted addresses in src_elements to fully take advantage of 338 // Using offsetted addresses in src_elements to fully take advantage of
352 // post-indexing. 339 // post-indexing.
353 // dst_elements: begin of destination FixedArray element fields, not tagged 340 // dst_elements: begin of destination FixedArray element fields, not tagged
354 // src_elements: begin of source FixedDoubleArray element fields, 341 // src_elements: begin of source FixedDoubleArray element fields,
355 // not tagged, +4 342 // not tagged, +4
356 // dst_end: end of destination FixedArray, not tagged 343 // dst_end: end of destination FixedArray, not tagged
357 // array: destination FixedArray 344 // array: destination FixedArray
358 // hole_value: the-hole pointer 345 // r9: the-hole pointer
359 // heap_number_map: heap number map 346 // heap_number_map: heap number map
360 __ b(&loop); 347 __ b(&loop, Label::kNear);
361 348
362 // Call into runtime if GC is required. 349 // Call into runtime if GC is required.
363 __ bind(&gc_required); 350 __ bind(&gc_required);
364 __ Pop(target_map, receiver, key, value); 351 __ Pop(target_map, receiver, key, value);
365 __ b(fail); 352 __ b(fail);
366 353
367 // Replace the-hole NaN with the-hole pointer. 354 // Replace the-hole NaN with the-hole pointer.
368 __ bind(&convert_hole); 355 __ bind(&convert_hole);
369 __ StoreP(hole_value, MemOperand(dst_elements)); 356 __ StoreP(r9, MemOperand(dst_elements));
370 __ addi(dst_elements, dst_elements, Operand(kPointerSize)); 357 __ AddP(dst_elements, Operand(kPointerSize));
371 __ cmpl(dst_elements, dst_end); 358 __ CmpLogicalP(dst_elements, dst_end);
372 __ bge(&loop_done); 359 __ bge(&loop_done);
373 360
374 __ bind(&loop); 361 __ bind(&loop);
375 Register upper_bits = key; 362 Register upper_bits = key;
376 __ lwz(upper_bits, MemOperand(src_elements, Register::kExponentOffset)); 363 __ LoadlW(upper_bits, MemOperand(src_elements, Register::kExponentOffset));
377 __ addi(src_elements, src_elements, Operand(kDoubleSize)); 364 __ AddP(src_elements, Operand(kDoubleSize));
378 // upper_bits: current element's upper 32 bit 365 // upper_bits: current element's upper 32 bit
379 // src_elements: address of next element's upper 32 bit 366 // src_elements: address of next element's upper 32 bit
380 __ Cmpi(upper_bits, Operand(kHoleNanUpper32), r0); 367 __ Cmp32(upper_bits, Operand(kHoleNanUpper32));
381 __ beq(&convert_hole); 368 __ beq(&convert_hole, Label::kNear);
382 369
383 // Non-hole double, copy value into a heap number. 370 // Non-hole double, copy value into a heap number.
384 Register heap_number = receiver; 371 Register heap_number = receiver;
385 Register scratch2 = value; 372 Register scratch2 = value;
386 __ AllocateHeapNumber(heap_number, scratch2, scratch3, heap_number_map, 373 __ AllocateHeapNumber(heap_number, scratch2, r1, heap_number_map,
387 &gc_required); 374 &gc_required);
388 // heap_number: new heap number 375 // heap_number: new heap number
389 #if V8_TARGET_ARCH_PPC64 376 #if V8_TARGET_ARCH_S390X
390 __ ld(scratch2, MemOperand(src_elements, -kDoubleSize)); 377 __ lg(scratch2, MemOperand(src_elements, -kDoubleSize));
391 // subtract tag for std 378 // subtract tag for std
392 __ addi(upper_bits, heap_number, Operand(-kHeapObjectTag)); 379 __ AddP(upper_bits, heap_number, Operand(-kHeapObjectTag));
393 __ std(scratch2, MemOperand(upper_bits, HeapNumber::kValueOffset)); 380 __ stg(scratch2, MemOperand(upper_bits, HeapNumber::kValueOffset));
394 #else 381 #else
395 __ lwz(scratch2, 382 __ LoadlW(scratch2,
396 MemOperand(src_elements, Register::kMantissaOffset - kDoubleSize)); 383 MemOperand(src_elements, Register::kMantissaOffset - kDoubleSize));
397 __ lwz(upper_bits, 384 __ LoadlW(upper_bits,
398 MemOperand(src_elements, Register::kExponentOffset - kDoubleSize)); 385 MemOperand(src_elements, Register::kExponentOffset - kDoubleSize));
399 __ stw(scratch2, FieldMemOperand(heap_number, HeapNumber::kMantissaOffset)); 386 __ StoreW(scratch2,
400 __ stw(upper_bits, FieldMemOperand(heap_number, HeapNumber::kExponentOffset)); 387 FieldMemOperand(heap_number, HeapNumber::kMantissaOffset));
388 __ StoreW(upper_bits,
389 FieldMemOperand(heap_number, HeapNumber::kExponentOffset));
401 #endif 390 #endif
402 __ mr(scratch2, dst_elements); 391 __ LoadRR(scratch2, dst_elements);
403 __ StoreP(heap_number, MemOperand(dst_elements)); 392 __ StoreP(heap_number, MemOperand(dst_elements));
404 __ addi(dst_elements, dst_elements, Operand(kPointerSize)); 393 __ AddP(dst_elements, Operand(kPointerSize));
405 __ RecordWrite(array, scratch2, heap_number, kLRHasNotBeenSaved, 394 __ RecordWrite(array, scratch2, heap_number, kLRHasNotBeenSaved,
406 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 395 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
407 __ cmpl(dst_elements, dst_end); 396 __ CmpLogicalP(dst_elements, dst_end);
408 __ blt(&loop); 397 __ blt(&loop);
409 __ bind(&loop_done); 398 __ bind(&loop_done);
410 399
411 __ Pop(target_map, receiver, key, value); 400 __ Pop(target_map, receiver, key, value);
412 // Replace receiver's backing store with newly created and filled FixedArray. 401 // Replace receiver's backing store with newly created and filled FixedArray.
413 __ StoreP(array, FieldMemOperand(receiver, JSObject::kElementsOffset), r0); 402 __ StoreP(array, FieldMemOperand(receiver, JSObject::kElementsOffset));
414 __ RecordWriteField(receiver, JSObject::kElementsOffset, array, scratch, 403 __ RecordWriteField(receiver, JSObject::kElementsOffset, array, scratch,
415 kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET, 404 kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
416 OMIT_SMI_CHECK); 405 OMIT_SMI_CHECK);
417 406
418 __ bind(&only_change_map); 407 __ bind(&only_change_map);
419 // Update receiver's map. 408 // Update receiver's map.
420 __ StoreP(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset), r0); 409 __ StoreP(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
421 __ RecordWriteField(receiver, HeapObject::kMapOffset, target_map, scratch, 410 __ RecordWriteField(receiver, HeapObject::kMapOffset, target_map, scratch,
422 kLRHasNotBeenSaved, kDontSaveFPRegs, OMIT_REMEMBERED_SET, 411 kLRHasNotBeenSaved, kDontSaveFPRegs, OMIT_REMEMBERED_SET,
423 OMIT_SMI_CHECK); 412 OMIT_SMI_CHECK);
424 } 413 }
425 414
426
427 // assume ip can be used as a scratch register below 415 // assume ip can be used as a scratch register below
428 void StringCharLoadGenerator::Generate(MacroAssembler* masm, Register string, 416 void StringCharLoadGenerator::Generate(MacroAssembler* masm, Register string,
429 Register index, Register result, 417 Register index, Register result,
430 Label* call_runtime) { 418 Label* call_runtime) {
431 // Fetch the instance type of the receiver into result register. 419 // Fetch the instance type of the receiver into result register.
432 __ LoadP(result, FieldMemOperand(string, HeapObject::kMapOffset)); 420 __ LoadP(result, FieldMemOperand(string, HeapObject::kMapOffset));
433 __ lbz(result, FieldMemOperand(result, Map::kInstanceTypeOffset)); 421 __ LoadlB(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
434 422
435 // We need special handling for indirect strings. 423 // We need special handling for indirect strings.
436 Label check_sequential; 424 Label check_sequential;
437 __ andi(r0, result, Operand(kIsIndirectStringMask)); 425 __ mov(r0, Operand(kIsIndirectStringMask));
438 __ beq(&check_sequential, cr0); 426 __ AndP(r0, result);
427 __ beq(&check_sequential, Label::kNear /*, cr0*/);
439 428
440 // Dispatch on the indirect string shape: slice or cons. 429 // Dispatch on the indirect string shape: slice or cons.
441 Label cons_string; 430 Label cons_string;
442 __ mov(ip, Operand(kSlicedNotConsMask)); 431 __ mov(ip, Operand(kSlicedNotConsMask));
443 __ and_(r0, result, ip, SetRC); 432 __ LoadRR(r0, result);
444 __ beq(&cons_string, cr0); 433 __ AndP(r0, ip /*, SetRC*/); // Should be okay to remove RC
434 __ beq(&cons_string, Label::kNear /*, cr0*/);
445 435
446 // Handle slices. 436 // Handle slices.
447 Label indirect_string_loaded; 437 Label indirect_string_loaded;
448 __ LoadP(result, FieldMemOperand(string, SlicedString::kOffsetOffset)); 438 __ LoadP(result, FieldMemOperand(string, SlicedString::kOffsetOffset));
449 __ LoadP(string, FieldMemOperand(string, SlicedString::kParentOffset)); 439 __ LoadP(string, FieldMemOperand(string, SlicedString::kParentOffset));
450 __ SmiUntag(ip, result); 440 __ SmiUntag(ip, result);
451 __ add(index, index, ip); 441 __ AddP(index, ip);
452 __ b(&indirect_string_loaded); 442 __ b(&indirect_string_loaded, Label::kNear);
453 443
454 // Handle cons strings. 444 // Handle cons strings.
455 // Check whether the right hand side is the empty string (i.e. if 445 // Check whether the right hand side is the empty string (i.e. if
456 // this is really a flat string in a cons string). If that is not 446 // this is really a flat string in a cons string). If that is not
457 // the case we would rather go to the runtime system now to flatten 447 // the case we would rather go to the runtime system now to flatten
458 // the string. 448 // the string.
459 __ bind(&cons_string); 449 __ bind(&cons_string);
460 __ LoadP(result, FieldMemOperand(string, ConsString::kSecondOffset)); 450 __ LoadP(result, FieldMemOperand(string, ConsString::kSecondOffset));
461 __ CompareRoot(result, Heap::kempty_stringRootIndex); 451 __ CompareRoot(result, Heap::kempty_stringRootIndex);
462 __ bne(call_runtime); 452 __ bne(call_runtime);
463 // Get the first of the two strings and load its instance type. 453 // Get the first of the two strings and load its instance type.
464 __ LoadP(string, FieldMemOperand(string, ConsString::kFirstOffset)); 454 __ LoadP(string, FieldMemOperand(string, ConsString::kFirstOffset));
465 455
466 __ bind(&indirect_string_loaded); 456 __ bind(&indirect_string_loaded);
467 __ LoadP(result, FieldMemOperand(string, HeapObject::kMapOffset)); 457 __ LoadP(result, FieldMemOperand(string, HeapObject::kMapOffset));
468 __ lbz(result, FieldMemOperand(result, Map::kInstanceTypeOffset)); 458 __ LoadlB(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
469 459
470 // Distinguish sequential and external strings. Only these two string 460 // Distinguish sequential and external strings. Only these two string
471 // representations can reach here (slices and flat cons strings have been 461 // representations can reach here (slices and flat cons strings have been
472 // reduced to the underlying sequential or external string). 462 // reduced to the underlying sequential or external string).
473 Label external_string, check_encoding; 463 Label external_string, check_encoding;
474 __ bind(&check_sequential); 464 __ bind(&check_sequential);
475 STATIC_ASSERT(kSeqStringTag == 0); 465 STATIC_ASSERT(kSeqStringTag == 0);
476 __ andi(r0, result, Operand(kStringRepresentationMask)); 466 __ mov(r0, Operand(kStringRepresentationMask));
477 __ bne(&external_string, cr0); 467 __ AndP(r0, result);
468 __ bne(&external_string, Label::kNear);
478 469
479 // Prepare sequential strings 470 // Prepare sequential strings
480 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 471 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
481 __ addi(string, string, 472 __ AddP(string, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
482 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 473 __ b(&check_encoding, Label::kNear);
483 __ b(&check_encoding);
484 474
485 // Handle external strings. 475 // Handle external strings.
486 __ bind(&external_string); 476 __ bind(&external_string);
487 if (FLAG_debug_code) { 477 if (FLAG_debug_code) {
488 // Assert that we do not have a cons or slice (indirect strings) here. 478 // Assert that we do not have a cons or slice (indirect strings) here.
489 // Sequential strings have already been ruled out. 479 // Sequential strings have already been ruled out.
490 __ andi(r0, result, Operand(kIsIndirectStringMask)); 480 __ mov(r0, Operand(kIsIndirectStringMask));
481 __ AndP(r0, result);
491 __ Assert(eq, kExternalStringExpectedButNotFound, cr0); 482 __ Assert(eq, kExternalStringExpectedButNotFound, cr0);
492 } 483 }
493 // Rule out short external strings. 484 // Rule out short external strings.
494 STATIC_ASSERT(kShortExternalStringTag != 0); 485 STATIC_ASSERT(kShortExternalStringTag != 0);
495 __ andi(r0, result, Operand(kShortExternalStringMask)); 486 __ mov(r0, Operand(kShortExternalStringMask));
496 __ bne(call_runtime, cr0); 487 __ AndP(r0, result);
488 __ bne(call_runtime /*, cr0*/);
497 __ LoadP(string, 489 __ LoadP(string,
498 FieldMemOperand(string, ExternalString::kResourceDataOffset)); 490 FieldMemOperand(string, ExternalString::kResourceDataOffset));
499 491
500 Label one_byte, done; 492 Label one_byte, done;
501 __ bind(&check_encoding); 493 __ bind(&check_encoding);
502 STATIC_ASSERT(kTwoByteStringTag == 0); 494 STATIC_ASSERT(kTwoByteStringTag == 0);
503 __ andi(r0, result, Operand(kStringEncodingMask)); 495 __ mov(r0, Operand(kStringEncodingMask));
504 __ bne(&one_byte, cr0); 496 __ AndP(r0, result);
497 __ bne(&one_byte, Label::kNear);
505 // Two-byte string. 498 // Two-byte string.
506 __ ShiftLeftImm(result, index, Operand(1)); 499 __ ShiftLeftP(result, index, Operand(1));
507 __ lhzx(result, MemOperand(string, result)); 500 __ LoadLogicalHalfWordP(result, MemOperand(string, result));
508 __ b(&done); 501 __ b(&done, Label::kNear);
509 __ bind(&one_byte); 502 __ bind(&one_byte);
510 // One-byte string. 503 // One-byte string.
511 __ lbzx(result, MemOperand(string, index)); 504 __ LoadlB(result, MemOperand(string, index));
512 __ bind(&done); 505 __ bind(&done);
513 } 506 }
514 507
515
516 static MemOperand ExpConstant(int index, Register base) { 508 static MemOperand ExpConstant(int index, Register base) {
517 return MemOperand(base, index * kDoubleSize); 509 return MemOperand(base, index * kDoubleSize);
518 } 510 }
519 511
520
521 void MathExpGenerator::EmitMathExp(MacroAssembler* masm, DoubleRegister input, 512 void MathExpGenerator::EmitMathExp(MacroAssembler* masm, DoubleRegister input,
522 DoubleRegister result, 513 DoubleRegister result,
523 DoubleRegister double_scratch1, 514 DoubleRegister double_scratch1,
524 DoubleRegister double_scratch2, 515 DoubleRegister double_scratch2,
525 Register temp1, Register temp2, 516 Register temp1, Register temp2,
526 Register temp3) { 517 Register temp3) {
527 DCHECK(!input.is(result)); 518 DCHECK(!input.is(result));
528 DCHECK(!input.is(double_scratch1)); 519 DCHECK(!input.is(double_scratch1));
529 DCHECK(!input.is(double_scratch2)); 520 DCHECK(!input.is(double_scratch2));
530 DCHECK(!result.is(double_scratch1)); 521 DCHECK(!result.is(double_scratch1));
531 DCHECK(!result.is(double_scratch2)); 522 DCHECK(!result.is(double_scratch2));
532 DCHECK(!double_scratch1.is(double_scratch2)); 523 DCHECK(!double_scratch1.is(double_scratch2));
533 DCHECK(!temp1.is(temp2)); 524 DCHECK(!temp1.is(temp2));
534 DCHECK(!temp1.is(temp3)); 525 DCHECK(!temp1.is(temp3));
535 DCHECK(!temp2.is(temp3)); 526 DCHECK(!temp2.is(temp3));
536 DCHECK(ExternalReference::math_exp_constants(0).address() != NULL); 527 DCHECK(ExternalReference::math_exp_constants(0).address() != NULL);
537 DCHECK(!masm->serializer_enabled()); // External references not serializable. 528 DCHECK(!masm->serializer_enabled()); // External references not serializable.
538 529
539 Label zero, infinity, done; 530 Label zero, infinity, done;
540 531
541 __ mov(temp3, Operand(ExternalReference::math_exp_constants(0))); 532 __ mov(temp3, Operand(ExternalReference::math_exp_constants(0)));
542 533
543 __ lfd(double_scratch1, ExpConstant(0, temp3)); 534 __ LoadDouble(double_scratch1, ExpConstant(0, temp3));
544 __ fcmpu(double_scratch1, input); 535 __ cdbr(double_scratch1, input);
545 __ fmr(result, input); 536 __ ldr(result, input);
546 __ bunordered(&done); 537 __ bunordered(&done, Label::kNear);
547 __ bge(&zero); 538 __ bge(&zero, Label::kNear);
548 539
549 __ lfd(double_scratch2, ExpConstant(1, temp3)); 540 __ LoadDouble(double_scratch2, ExpConstant(1, temp3));
550 __ fcmpu(input, double_scratch2); 541 __ cdbr(input, double_scratch2);
551 __ bge(&infinity); 542 __ bge(&infinity, Label::kNear);
552 543
553 __ lfd(double_scratch1, ExpConstant(3, temp3)); 544 __ LoadDouble(double_scratch1, ExpConstant(3, temp3));
554 __ lfd(result, ExpConstant(4, temp3)); 545 __ LoadDouble(result, ExpConstant(4, temp3));
555 __ fmul(double_scratch1, double_scratch1, input); 546
556 __ fadd(double_scratch1, double_scratch1, result); 547 // Do not generate madbr, as intermediate result are not
557 __ MovDoubleLowToInt(temp2, double_scratch1); 548 // rounded properly
558 __ fsub(double_scratch1, double_scratch1, result); 549 __ mdbr(double_scratch1, input);
559 __ lfd(result, ExpConstant(6, temp3)); 550 __ adbr(double_scratch1, result);
560 __ lfd(double_scratch2, ExpConstant(5, temp3)); 551
561 __ fmul(double_scratch1, double_scratch1, double_scratch2); 552 // Move low word of double_scratch1 to temp2
562 __ fsub(double_scratch1, double_scratch1, input); 553 __ lgdr(temp2, double_scratch1);
563 __ fsub(result, result, double_scratch1); 554 __ nihf(temp2, Operand::Zero());
564 __ fmul(double_scratch2, double_scratch1, double_scratch1); 555
565 __ fmul(result, result, double_scratch2); 556 __ sdbr(double_scratch1, result);
566 __ lfd(double_scratch2, ExpConstant(7, temp3)); 557 __ LoadDouble(result, ExpConstant(6, temp3));
567 __ fmul(result, result, double_scratch2); 558 __ LoadDouble(double_scratch2, ExpConstant(5, temp3));
568 __ fsub(result, result, double_scratch1); 559 __ mdbr(double_scratch1, double_scratch2);
569 __ lfd(double_scratch2, ExpConstant(8, temp3)); 560 __ sdbr(double_scratch1, input);
570 __ fadd(result, result, double_scratch2); 561 __ sdbr(result, double_scratch1);
571 __ srwi(temp1, temp2, Operand(11)); 562 __ ldr(double_scratch2, double_scratch1);
572 __ andi(temp2, temp2, Operand(0x7ff)); 563 __ mdbr(double_scratch2, double_scratch2);
573 __ addi(temp1, temp1, Operand(0x3ff)); 564 __ mdbr(result, double_scratch2);
565 __ LoadDouble(double_scratch2, ExpConstant(7, temp3));
566 __ mdbr(result, double_scratch2);
567 __ sdbr(result, double_scratch1);
568 __ LoadDouble(double_scratch2, ExpConstant(8, temp3));
569 __ adbr(result, double_scratch2);
570 __ ShiftRight(temp1, temp2, Operand(11));
571 __ AndP(temp2, Operand(0x7ff));
572 __ AddP(temp1, Operand(0x3ff));
574 573
575 // Must not call ExpConstant() after overwriting temp3! 574 // Must not call ExpConstant() after overwriting temp3!
576 __ mov(temp3, Operand(ExternalReference::math_exp_log_table())); 575 __ mov(temp3, Operand(ExternalReference::math_exp_log_table()));
577 __ slwi(temp2, temp2, Operand(3)); 576 __ ShiftLeft(temp2, temp2, Operand(3));
578 #if V8_TARGET_ARCH_PPC64
579 __ ldx(temp2, MemOperand(temp3, temp2));
580 __ sldi(temp1, temp1, Operand(52));
581 __ orx(temp2, temp1, temp2);
582 __ MovInt64ToDouble(double_scratch1, temp2);
583 #else
584 __ add(ip, temp3, temp2);
585 __ lwz(temp3, MemOperand(ip, Register::kExponentOffset));
586 __ lwz(temp2, MemOperand(ip, Register::kMantissaOffset));
587 __ slwi(temp1, temp1, Operand(20));
588 __ orx(temp3, temp1, temp3);
589 __ MovInt64ToDouble(double_scratch1, temp3, temp2);
590 #endif
591 577
592 __ fmul(result, result, double_scratch1); 578 __ lg(temp2, MemOperand(temp2, temp3));
593 __ b(&done); 579 __ sllg(temp1, temp1, Operand(52));
580 __ ogr(temp2, temp1);
581 __ ldgr(double_scratch1, temp2);
582
583 __ mdbr(result, double_scratch1);
584 __ b(&done, Label::kNear);
594 585
595 __ bind(&zero); 586 __ bind(&zero);
596 __ fmr(result, kDoubleRegZero); 587 __ lzdr(kDoubleRegZero);
597 __ b(&done); 588 __ ldr(result, kDoubleRegZero);
589 __ b(&done, Label::kNear);
598 590
599 __ bind(&infinity); 591 __ bind(&infinity);
600 __ lfd(result, ExpConstant(2, temp3)); 592 __ LoadDouble(result, ExpConstant(2, temp3));
601 593
602 __ bind(&done); 594 __ bind(&done);
603 } 595 }
604 596
605 #undef __ 597 #undef __
606 598
607 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) { 599 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) {
608 USE(isolate); 600 USE(isolate);
609 DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength); 601 DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength);
610 // Since patcher is a large object, allocate it dynamically when needed, 602 // Since patcher is a large object, allocate it dynamically when needed,
611 // to avoid overloading the stack in stress conditions. 603 // to avoid overloading the stack in stress conditions.
612 // DONT_FLUSH is used because the CodeAgingHelper is initialized early in 604 // DONT_FLUSH is used because the CodeAgingHelper is initialized early in
613 // the process, before ARM simulator ICache is setup. 605 // the process, before ARM simulator ICache is setup.
614 base::SmartPointer<CodePatcher> patcher( 606 base::SmartPointer<CodePatcher> patcher(
615 new CodePatcher(isolate, young_sequence_.start(), 607 new CodePatcher(isolate, young_sequence_.start(),
616 young_sequence_.length() / Assembler::kInstrSize, 608 young_sequence_.length(), CodePatcher::DONT_FLUSH));
617 CodePatcher::DONT_FLUSH));
618 PredictableCodeSizeScope scope(patcher->masm(), young_sequence_.length()); 609 PredictableCodeSizeScope scope(patcher->masm(), young_sequence_.length());
619 patcher->masm()->PushFixedFrame(r4); 610 patcher->masm()->PushFixedFrame(r3);
620 patcher->masm()->addi(fp, sp, 611 patcher->masm()->la(
621 Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); 612 fp, MemOperand(sp, StandardFrameConstants::kFixedFrameSizeFromFp));
622 for (int i = 0; i < kNoCodeAgeSequenceNops; i++) {
623 patcher->masm()->nop();
624 }
625 } 613 }
626 614
627
628 #ifdef DEBUG 615 #ifdef DEBUG
629 bool CodeAgingHelper::IsOld(byte* candidate) const { 616 bool CodeAgingHelper::IsOld(byte* candidate) const {
630 return Assembler::IsNop(Assembler::instr_at(candidate)); 617 return Assembler::IsNop(Assembler::instr_at(candidate));
631 } 618 }
632 #endif 619 #endif
633 620
634
635 bool Code::IsYoungSequence(Isolate* isolate, byte* sequence) { 621 bool Code::IsYoungSequence(Isolate* isolate, byte* sequence) {
636 bool result = isolate->code_aging_helper()->IsYoung(sequence); 622 bool result = isolate->code_aging_helper()->IsYoung(sequence);
637 DCHECK(result || isolate->code_aging_helper()->IsOld(sequence)); 623 DCHECK(result || isolate->code_aging_helper()->IsOld(sequence));
638 return result; 624 return result;
639 } 625 }
640 626
641
642 void Code::GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age, 627 void Code::GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age,
643 MarkingParity* parity) { 628 MarkingParity* parity) {
644 if (IsYoungSequence(isolate, sequence)) { 629 if (IsYoungSequence(isolate, sequence)) {
645 *age = kNoAgeCodeAge; 630 *age = kNoAgeCodeAge;
646 *parity = NO_MARKING_PARITY; 631 *parity = NO_MARKING_PARITY;
647 } else { 632 } else {
648 Code* code = NULL; 633 Code* code = NULL;
649 Address target_address = 634 Address target_address =
650 Assembler::target_address_at(sequence + kCodeAgingTargetDelta, code); 635 Assembler::target_address_at(sequence + kCodeAgingTargetDelta, code);
651 Code* stub = GetCodeFromTargetAddress(target_address); 636 Code* stub = GetCodeFromTargetAddress(target_address);
652 GetCodeAgeAndParity(stub, age, parity); 637 GetCodeAgeAndParity(stub, age, parity);
653 } 638 }
654 } 639 }
655 640
656
657 void Code::PatchPlatformCodeAge(Isolate* isolate, byte* sequence, Code::Age age, 641 void Code::PatchPlatformCodeAge(Isolate* isolate, byte* sequence, Code::Age age,
658 MarkingParity parity) { 642 MarkingParity parity) {
659 uint32_t young_length = isolate->code_aging_helper()->young_sequence_length(); 643 uint32_t young_length = isolate->code_aging_helper()->young_sequence_length();
660 if (age == kNoAgeCodeAge) { 644 if (age == kNoAgeCodeAge) {
661 isolate->code_aging_helper()->CopyYoungSequenceTo(sequence); 645 isolate->code_aging_helper()->CopyYoungSequenceTo(sequence);
662 Assembler::FlushICache(isolate, sequence, young_length); 646 Assembler::FlushICache(isolate, sequence, young_length);
663 } else { 647 } else {
664 // FIXED_SEQUENCE 648 // FIXED_SEQUENCE
665 Code* stub = GetCodeAgeStub(isolate, age, parity); 649 Code* stub = GetCodeAgeStub(isolate, age, parity);
666 CodePatcher patcher(isolate, sequence, 650 CodePatcher patcher(isolate, sequence, young_length);
667 young_length / Assembler::kInstrSize);
668 Assembler::BlockTrampolinePoolScope block_trampoline_pool(patcher.masm());
669 intptr_t target = reinterpret_cast<intptr_t>(stub->instruction_start()); 651 intptr_t target = reinterpret_cast<intptr_t>(stub->instruction_start());
670 // Don't use Call -- we need to preserve ip and lr. 652 // We need to push lr on stack so that GenerateMakeCodeYoungAgainCommon
671 // GenerateMakeCodeYoungAgainCommon for the stub code. 653 // knows where to pick up the return address
654 //
655 // Since we can no longer guarentee ip will hold the branch address
656 // because of BRASL, use Call so that GenerateMakeCodeYoungAgainCommon
657 // can calculate the branch address offset
672 patcher.masm()->nop(); // marker to detect sequence (see IsOld) 658 patcher.masm()->nop(); // marker to detect sequence (see IsOld)
673 patcher.masm()->mov(r3, Operand(target)); 659 patcher.masm()->CleanseP(r14);
674 patcher.masm()->Jump(r3); 660 patcher.masm()->Push(r14);
675 for (int i = 0; i < kCodeAgingSequenceNops; i++) { 661 patcher.masm()->mov(r2, Operand(target));
676 patcher.masm()->nop(); 662 patcher.masm()->Call(r2);
663 for (int i = 0; i < kNoCodeAgeSequenceLength - kCodeAgingSequenceLength;
664 i += 2) {
665 // TODO(joransiu): Create nop function to pad
666 // (kNoCodeAgeSequenceLength - kCodeAgingSequenceLength) bytes.
667 patcher.masm()->nop(); // 2-byte nops().
677 } 668 }
678 } 669 }
679 } 670 }
671
680 } // namespace internal 672 } // namespace internal
681 } // namespace v8 673 } // namespace v8
682 674
683 #endif // V8_TARGET_ARCH_PPC 675 #endif // V8_TARGET_ARCH_S390
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698