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

Side by Side Diff: src/ppc/macro-assembler-ppc.cc

Issue 422063005: Contribution of PowerPC port. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Caught up to bleending edge (8/15) Created 6 years, 4 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 //
3 // Copyright IBM Corp. 2012, 2013. All rights reserved.
4 //
2 // Use of this source code is governed by a BSD-style license that can be 5 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 6 // found in the LICENSE file.
4 7
8 #include <assert.h> // For assert
5 #include <limits.h> // For LONG_MIN, LONG_MAX. 9 #include <limits.h> // For LONG_MIN, LONG_MAX.
6 10
7 #include "src/v8.h" 11 #include "src/v8.h"
8 12
9 #if V8_TARGET_ARCH_ARM 13 #if V8_TARGET_ARCH_PPC
10 14
11 #include "src/bootstrapper.h" 15 #include "src/bootstrapper.h"
12 #include "src/codegen.h" 16 #include "src/codegen.h"
13 #include "src/cpu-profiler.h" 17 #include "src/cpu-profiler.h"
14 #include "src/debug.h" 18 #include "src/debug.h"
15 #include "src/isolate-inl.h" 19 #include "src/isolate-inl.h"
16 #include "src/runtime.h" 20 #include "src/runtime.h"
17 21
18 namespace v8 { 22 namespace v8 {
19 namespace internal { 23 namespace internal {
20 24
21 MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size) 25 MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
22 : Assembler(arg_isolate, buffer, size), 26 : Assembler(arg_isolate, buffer, size),
23 generating_stub_(false), 27 generating_stub_(false),
24 has_frame_(false) { 28 has_frame_(false) {
25 if (isolate() != NULL) { 29 if (isolate() != NULL) {
26 code_object_ = Handle<Object>(isolate()->heap()->undefined_value(), 30 code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
27 isolate()); 31 isolate());
28 } 32 }
29 } 33 }
30 34
31 35
32 void MacroAssembler::Jump(Register target, Condition cond) { 36 void MacroAssembler::Jump(Register target, Condition cond) {
33 bx(target, cond); 37 DCHECK(cond == al);
38 mtctr(target);
39 bctr();
34 } 40 }
35 41
36 42
37 void MacroAssembler::Jump(intptr_t target, RelocInfo::Mode rmode, 43 void MacroAssembler::Jump(intptr_t target, RelocInfo::Mode rmode,
38 Condition cond) { 44 Condition cond, CRegister cr) {
39 DCHECK(RelocInfo::IsCodeTarget(rmode)); 45 Label skip;
40 mov(pc, Operand(target, rmode), LeaveCC, cond); 46
47 if (cond != al) b(NegateCondition(cond), &skip, cr);
48
49 DCHECK(rmode == RelocInfo::CODE_TARGET ||
50 rmode == RelocInfo::RUNTIME_ENTRY);
51
52 mov(r0, Operand(target, rmode));
53 mtctr(r0);
54 bctr();
55
56 bind(&skip);
57 // mov(pc, Operand(target, rmode), LeaveCC, cond);
41 } 58 }
42 59
43 60
44 void MacroAssembler::Jump(Address target, RelocInfo::Mode rmode, 61 void MacroAssembler::Jump(Address target, RelocInfo::Mode rmode,
45 Condition cond) { 62 Condition cond, CRegister cr) {
46 DCHECK(!RelocInfo::IsCodeTarget(rmode)); 63 DCHECK(!RelocInfo::IsCodeTarget(rmode));
47 Jump(reinterpret_cast<intptr_t>(target), rmode, cond); 64 Jump(reinterpret_cast<intptr_t>(target), rmode, cond, cr);
48 } 65 }
49 66
50 67
51 void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode, 68 void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode,
52 Condition cond) { 69 Condition cond) {
53 DCHECK(RelocInfo::IsCodeTarget(rmode)); 70 DCHECK(RelocInfo::IsCodeTarget(rmode));
54 // 'code' is always generated ARM code, never THUMB code 71 // 'code' is always generated ppc code, never THUMB code
55 AllowDeferredHandleDereference embedding_raw_address; 72 AllowDeferredHandleDereference embedding_raw_address;
56 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond); 73 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
57 } 74 }
58 75
59 76
60 int MacroAssembler::CallSize(Register target, Condition cond) { 77 int MacroAssembler::CallSize(Register target, Condition cond) {
61 return kInstrSize; 78 return 2 * kInstrSize;
62 } 79 }
63 80
64 81
65 void MacroAssembler::Call(Register target, Condition cond) { 82 void MacroAssembler::Call(Register target, Condition cond) {
66 // Block constant pool for the call instruction sequence. 83 BlockTrampolinePoolScope block_trampoline_pool(this);
67 BlockConstPoolScope block_const_pool(this);
68 Label start; 84 Label start;
69 bind(&start); 85 bind(&start);
70 blx(target, cond); 86 DCHECK(cond == al); // in prep of removal of condition
87
88 // Statement positions are expected to be recorded when the target
89 // address is loaded.
90 positions_recorder()->WriteRecordedPositions();
91
92 // branch via link register and set LK bit for return point
93 mtlr(target);
94 bclr(BA, SetLK);
95
71 DCHECK_EQ(CallSize(target, cond), SizeOfCodeGeneratedSince(&start)); 96 DCHECK_EQ(CallSize(target, cond), SizeOfCodeGeneratedSince(&start));
72 } 97 }
73 98
74 99
75 int MacroAssembler::CallSize( 100 int MacroAssembler::CallSize(
76 Address target, RelocInfo::Mode rmode, Condition cond) { 101 Address target, RelocInfo::Mode rmode, Condition cond) {
77 Instr mov_instr = cond | MOV | LeaveCC;
78 Operand mov_operand = Operand(reinterpret_cast<intptr_t>(target), rmode); 102 Operand mov_operand = Operand(reinterpret_cast<intptr_t>(target), rmode);
79 return kInstrSize + 103 return (2 + instructions_required_for_mov(mov_operand)) * kInstrSize;
80 mov_operand.instructions_required(this, mov_instr) * kInstrSize;
81 } 104 }
82 105
83 106
84 int MacroAssembler::CallStubSize( 107 int MacroAssembler::CallSizeNotPredictableCodeSize(
85 CodeStub* stub, TypeFeedbackId ast_id, Condition cond) { 108 Address target, RelocInfo::Mode rmode, Condition cond) {
86 return CallSize(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id, cond); 109 return (2 + kMovInstructionsNoConstantPool) * kInstrSize;
87 }
88
89
90 int MacroAssembler::CallSizeNotPredictableCodeSize(Isolate* isolate,
91 Address target,
92 RelocInfo::Mode rmode,
93 Condition cond) {
94 Instr mov_instr = cond | MOV | LeaveCC;
95 Operand mov_operand = Operand(reinterpret_cast<intptr_t>(target), rmode);
96 return kInstrSize +
97 mov_operand.instructions_required(NULL, mov_instr) * kInstrSize;
98 } 110 }
99 111
100 112
101 void MacroAssembler::Call(Address target, 113 void MacroAssembler::Call(Address target,
102 RelocInfo::Mode rmode, 114 RelocInfo::Mode rmode,
103 Condition cond, 115 Condition cond) {
104 TargetAddressStorageMode mode) { 116 BlockTrampolinePoolScope block_trampoline_pool(this);
105 // Block constant pool for the call instruction sequence. 117 DCHECK(cond == al);
106 BlockConstPoolScope block_const_pool(this);
107 Label start;
108 bind(&start);
109
110 bool old_predictable_code_size = predictable_code_size();
111 if (mode == NEVER_INLINE_TARGET_ADDRESS) {
112 set_predictable_code_size(true);
113 }
114 118
115 #ifdef DEBUG 119 #ifdef DEBUG
116 // Check the expected size before generating code to ensure we assume the same 120 // Check the expected size before generating code to ensure we assume the same
117 // constant pool availability (e.g., whether constant pool is full or not). 121 // constant pool availability (e.g., whether constant pool is full or not).
118 int expected_size = CallSize(target, rmode, cond); 122 int expected_size = CallSize(target, rmode, cond);
123 Label start;
124 bind(&start);
119 #endif 125 #endif
120 126
121 // Call sequence on V7 or later may be :
122 // movw ip, #... @ call address low 16
123 // movt ip, #... @ call address high 16
124 // blx ip
125 // @ return address
126 // Or for pre-V7 or values that may be back-patched
127 // to avoid ICache flushes:
128 // ldr ip, [pc, #...] @ call address
129 // blx ip
130 // @ return address
131
132 // Statement positions are expected to be recorded when the target 127 // Statement positions are expected to be recorded when the target
133 // address is loaded. The mov method will automatically record 128 // address is loaded.
134 // positions when pc is the target, since this is not the case here
135 // we have to do it explicitly.
136 positions_recorder()->WriteRecordedPositions(); 129 positions_recorder()->WriteRecordedPositions();
137 130
138 mov(ip, Operand(reinterpret_cast<int32_t>(target), rmode)); 131 // This can likely be optimized to make use of bc() with 24bit relative
139 blx(ip, cond); 132 //
133 // RecordRelocInfo(x.rmode_, x.imm_);
134 // bc( BA, .... offset, LKset);
135 //
136
137 mov(ip, Operand(reinterpret_cast<intptr_t>(target), rmode));
138 mtlr(ip);
139 bclr(BA, SetLK);
140 140
141 DCHECK_EQ(expected_size, SizeOfCodeGeneratedSince(&start)); 141 DCHECK_EQ(expected_size, SizeOfCodeGeneratedSince(&start));
142 if (mode == NEVER_INLINE_TARGET_ADDRESS) {
143 set_predictable_code_size(old_predictable_code_size);
144 }
145 } 142 }
146 143
147 144
148 int MacroAssembler::CallSize(Handle<Code> code, 145 int MacroAssembler::CallSize(Handle<Code> code,
149 RelocInfo::Mode rmode, 146 RelocInfo::Mode rmode,
150 TypeFeedbackId ast_id, 147 TypeFeedbackId ast_id,
151 Condition cond) { 148 Condition cond) {
152 AllowDeferredHandleDereference using_raw_address; 149 AllowDeferredHandleDereference using_raw_address;
153 return CallSize(reinterpret_cast<Address>(code.location()), rmode, cond); 150 return CallSize(reinterpret_cast<Address>(code.location()), rmode, cond);
154 } 151 }
155 152
156 153
157 void MacroAssembler::Call(Handle<Code> code, 154 void MacroAssembler::Call(Handle<Code> code,
158 RelocInfo::Mode rmode, 155 RelocInfo::Mode rmode,
159 TypeFeedbackId ast_id, 156 TypeFeedbackId ast_id,
160 Condition cond, 157 Condition cond) {
161 TargetAddressStorageMode mode) { 158 BlockTrampolinePoolScope block_trampoline_pool(this);
159 DCHECK(RelocInfo::IsCodeTarget(rmode));
160
161 #ifdef DEBUG
162 // Check the expected size before generating code to ensure we assume the same
163 // constant pool availability (e.g., whether constant pool is full or not).
164 int expected_size = CallSize(code, rmode, ast_id, cond);
162 Label start; 165 Label start;
163 bind(&start); 166 bind(&start);
164 DCHECK(RelocInfo::IsCodeTarget(rmode)); 167 #endif
168
165 if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) { 169 if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) {
166 SetRecordedAstId(ast_id); 170 SetRecordedAstId(ast_id);
167 rmode = RelocInfo::CODE_TARGET_WITH_ID; 171 rmode = RelocInfo::CODE_TARGET_WITH_ID;
168 } 172 }
169 // 'code' is always generated ARM code, never THUMB code 173 AllowDeferredHandleDereference using_raw_address;
170 AllowDeferredHandleDereference embedding_raw_address; 174 Call(reinterpret_cast<Address>(code.location()), rmode, cond);
171 Call(reinterpret_cast<Address>(code.location()), rmode, cond, mode); 175 DCHECK_EQ(expected_size, SizeOfCodeGeneratedSince(&start));
172 } 176 }
173 177
174 178
175 void MacroAssembler::Ret(Condition cond) { 179 void MacroAssembler::Ret(Condition cond) {
176 bx(lr, cond); 180 DCHECK(cond == al);
181 blr();
177 } 182 }
178 183
179 184
180 void MacroAssembler::Drop(int count, Condition cond) { 185 void MacroAssembler::Drop(int count, Condition cond) {
186 DCHECK(cond == al);
181 if (count > 0) { 187 if (count > 0) {
182 add(sp, sp, Operand(count * kPointerSize), LeaveCC, cond); 188 Add(sp, sp, count * kPointerSize, r0);
183 } 189 }
184 } 190 }
185 191
186 192
187 void MacroAssembler::Ret(int drop, Condition cond) { 193 void MacroAssembler::Ret(int drop, Condition cond) {
188 Drop(drop, cond); 194 Drop(drop, cond);
189 Ret(cond); 195 Ret(cond);
190 } 196 }
191 197
192 198
193 void MacroAssembler::Swap(Register reg1,
194 Register reg2,
195 Register scratch,
196 Condition cond) {
197 if (scratch.is(no_reg)) {
198 eor(reg1, reg1, Operand(reg2), LeaveCC, cond);
199 eor(reg2, reg2, Operand(reg1), LeaveCC, cond);
200 eor(reg1, reg1, Operand(reg2), LeaveCC, cond);
201 } else {
202 mov(scratch, reg1, LeaveCC, cond);
203 mov(reg1, reg2, LeaveCC, cond);
204 mov(reg2, scratch, LeaveCC, cond);
205 }
206 }
207
208
209 void MacroAssembler::Call(Label* target) { 199 void MacroAssembler::Call(Label* target) {
210 bl(target); 200 b(target, SetLK);
211 } 201 }
212 202
213 203
214 void MacroAssembler::Push(Handle<Object> handle) { 204 void MacroAssembler::Push(Handle<Object> handle) {
215 mov(ip, Operand(handle)); 205 mov(ip, Operand(handle));
216 push(ip); 206 push(ip);
217 } 207 }
218 208
219 209
220 void MacroAssembler::Move(Register dst, Handle<Object> value) { 210 void MacroAssembler::Move(Register dst, Handle<Object> value) {
221 AllowDeferredHandleDereference smi_check; 211 AllowDeferredHandleDereference smi_check;
222 if (value->IsSmi()) { 212 if (value->IsSmi()) {
223 mov(dst, Operand(value)); 213 LoadSmiLiteral(dst, reinterpret_cast<Smi *>(*value));
224 } else { 214 } else {
225 DCHECK(value->IsHeapObject()); 215 DCHECK(value->IsHeapObject());
226 if (isolate()->heap()->InNewSpace(*value)) { 216 if (isolate()->heap()->InNewSpace(*value)) {
227 Handle<Cell> cell = isolate()->factory()->NewCell(value); 217 Handle<Cell> cell = isolate()->factory()->NewCell(value);
228 mov(dst, Operand(cell)); 218 mov(dst, Operand(cell));
229 ldr(dst, FieldMemOperand(dst, Cell::kValueOffset)); 219 LoadP(dst, FieldMemOperand(dst, Cell::kValueOffset));
230 } else { 220 } else {
231 mov(dst, Operand(value)); 221 mov(dst, Operand(value));
232 } 222 }
233 } 223 }
234 } 224 }
235 225
236 226
237 void MacroAssembler::Move(Register dst, Register src, Condition cond) { 227 void MacroAssembler::Move(Register dst, Register src, Condition cond) {
228 DCHECK(cond == al);
238 if (!dst.is(src)) { 229 if (!dst.is(src)) {
239 mov(dst, src, LeaveCC, cond); 230 mr(dst, src);
240 } 231 }
241 } 232 }
242 233
243 234
244 void MacroAssembler::Move(DwVfpRegister dst, DwVfpRegister src) { 235 void MacroAssembler::Move(DoubleRegister dst, DoubleRegister src) {
245 if (!dst.is(src)) { 236 if (!dst.is(src)) {
246 vmov(dst, src); 237 fmr(dst, src);
247 } 238 }
248 } 239 }
249 240
250 241
251 void MacroAssembler::Mls(Register dst, Register src1, Register src2, 242 void MacroAssembler::MultiPush(RegList regs) {
252 Register srcA, Condition cond) { 243 int16_t num_to_push = NumberOfBitsSet(regs);
253 if (CpuFeatures::IsSupported(MLS)) { 244 int16_t stack_offset = num_to_push * kPointerSize;
254 CpuFeatureScope scope(this, MLS); 245
255 mls(dst, src1, src2, srcA, cond); 246 subi(sp, sp, Operand(stack_offset));
256 } else { 247 for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
257 DCHECK(!srcA.is(ip)); 248 if ((regs & (1 << i)) != 0) {
258 mul(ip, src1, src2, LeaveCC, cond); 249 stack_offset -= kPointerSize;
259 sub(dst, srcA, ip, LeaveCC, cond); 250 StoreP(ToRegister(i), MemOperand(sp, stack_offset));
251 }
260 } 252 }
261 } 253 }
262 254
263 255
264 void MacroAssembler::And(Register dst, Register src1, const Operand& src2, 256 void MacroAssembler::MultiPop(RegList regs) {
265 Condition cond) { 257 int16_t stack_offset = 0;
266 if (!src2.is_reg() && 258
267 !src2.must_output_reloc_info(this) && 259 for (int16_t i = 0; i < kNumRegisters; i++) {
268 src2.immediate() == 0) { 260 if ((regs & (1 << i)) != 0) {
269 mov(dst, Operand::Zero(), LeaveCC, cond); 261 LoadP(ToRegister(i), MemOperand(sp, stack_offset));
270 } else if (!(src2.instructions_required(this) == 1) && 262 stack_offset += kPointerSize;
271 !src2.must_output_reloc_info(this) && 263 }
272 CpuFeatures::IsSupported(ARMv7) &&
273 IsPowerOf2(src2.immediate() + 1)) {
274 ubfx(dst, src1, 0,
275 WhichPowerOf2(static_cast<uint32_t>(src2.immediate()) + 1), cond);
276 } else {
277 and_(dst, src1, src2, LeaveCC, cond);
278 } 264 }
279 } 265 addi(sp, sp, Operand(stack_offset));
280
281
282 void MacroAssembler::Ubfx(Register dst, Register src1, int lsb, int width,
283 Condition cond) {
284 DCHECK(lsb < 32);
285 if (!CpuFeatures::IsSupported(ARMv7) || predictable_code_size()) {
286 int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
287 and_(dst, src1, Operand(mask), LeaveCC, cond);
288 if (lsb != 0) {
289 mov(dst, Operand(dst, LSR, lsb), LeaveCC, cond);
290 }
291 } else {
292 ubfx(dst, src1, lsb, width, cond);
293 }
294 }
295
296
297 void MacroAssembler::Sbfx(Register dst, Register src1, int lsb, int width,
298 Condition cond) {
299 DCHECK(lsb < 32);
300 if (!CpuFeatures::IsSupported(ARMv7) || predictable_code_size()) {
301 int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
302 and_(dst, src1, Operand(mask), LeaveCC, cond);
303 int shift_up = 32 - lsb - width;
304 int shift_down = lsb + shift_up;
305 if (shift_up != 0) {
306 mov(dst, Operand(dst, LSL, shift_up), LeaveCC, cond);
307 }
308 if (shift_down != 0) {
309 mov(dst, Operand(dst, ASR, shift_down), LeaveCC, cond);
310 }
311 } else {
312 sbfx(dst, src1, lsb, width, cond);
313 }
314 }
315
316
317 void MacroAssembler::Bfi(Register dst,
318 Register src,
319 Register scratch,
320 int lsb,
321 int width,
322 Condition cond) {
323 DCHECK(0 <= lsb && lsb < 32);
324 DCHECK(0 <= width && width < 32);
325 DCHECK(lsb + width < 32);
326 DCHECK(!scratch.is(dst));
327 if (width == 0) return;
328 if (!CpuFeatures::IsSupported(ARMv7) || predictable_code_size()) {
329 int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
330 bic(dst, dst, Operand(mask));
331 and_(scratch, src, Operand((1 << width) - 1));
332 mov(scratch, Operand(scratch, LSL, lsb));
333 orr(dst, dst, scratch);
334 } else {
335 bfi(dst, src, lsb, width, cond);
336 }
337 }
338
339
340 void MacroAssembler::Bfc(Register dst, Register src, int lsb, int width,
341 Condition cond) {
342 DCHECK(lsb < 32);
343 if (!CpuFeatures::IsSupported(ARMv7) || predictable_code_size()) {
344 int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
345 bic(dst, src, Operand(mask));
346 } else {
347 Move(dst, src, cond);
348 bfc(dst, lsb, width, cond);
349 }
350 }
351
352
353 void MacroAssembler::Usat(Register dst, int satpos, const Operand& src,
354 Condition cond) {
355 if (!CpuFeatures::IsSupported(ARMv7) || predictable_code_size()) {
356 DCHECK(!dst.is(pc) && !src.rm().is(pc));
357 DCHECK((satpos >= 0) && (satpos <= 31));
358
359 // These asserts are required to ensure compatibility with the ARMv7
360 // implementation.
361 DCHECK((src.shift_op() == ASR) || (src.shift_op() == LSL));
362 DCHECK(src.rs().is(no_reg));
363
364 Label done;
365 int satval = (1 << satpos) - 1;
366
367 if (cond != al) {
368 b(NegateCondition(cond), &done); // Skip saturate if !condition.
369 }
370 if (!(src.is_reg() && dst.is(src.rm()))) {
371 mov(dst, src);
372 }
373 tst(dst, Operand(~satval));
374 b(eq, &done);
375 mov(dst, Operand::Zero(), LeaveCC, mi); // 0 if negative.
376 mov(dst, Operand(satval), LeaveCC, pl); // satval if positive.
377 bind(&done);
378 } else {
379 usat(dst, satpos, src, cond);
380 }
381 }
382
383
384 void MacroAssembler::Load(Register dst,
385 const MemOperand& src,
386 Representation r) {
387 DCHECK(!r.IsDouble());
388 if (r.IsInteger8()) {
389 ldrsb(dst, src);
390 } else if (r.IsUInteger8()) {
391 ldrb(dst, src);
392 } else if (r.IsInteger16()) {
393 ldrsh(dst, src);
394 } else if (r.IsUInteger16()) {
395 ldrh(dst, src);
396 } else {
397 ldr(dst, src);
398 }
399 }
400
401
402 void MacroAssembler::Store(Register src,
403 const MemOperand& dst,
404 Representation r) {
405 DCHECK(!r.IsDouble());
406 if (r.IsInteger8() || r.IsUInteger8()) {
407 strb(src, dst);
408 } else if (r.IsInteger16() || r.IsUInteger16()) {
409 strh(src, dst);
410 } else {
411 if (r.IsHeapObject()) {
412 AssertNotSmi(src);
413 } else if (r.IsSmi()) {
414 AssertSmi(src);
415 }
416 str(src, dst);
417 }
418 } 266 }
419 267
420 268
421 void MacroAssembler::LoadRoot(Register destination, 269 void MacroAssembler::LoadRoot(Register destination,
422 Heap::RootListIndex index, 270 Heap::RootListIndex index,
423 Condition cond) { 271 Condition cond) {
424 if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) && 272 DCHECK(cond == al);
425 isolate()->heap()->RootCanBeTreatedAsConstant(index) && 273 LoadP(destination, MemOperand(kRootRegister,
426 !predictable_code_size()) { 274 index << kPointerSizeLog2), r0);
427 // The CPU supports fast immediate values, and this root will never
428 // change. We will load it as a relocatable immediate value.
429 Handle<Object> root(&isolate()->heap()->roots_array_start()[index]);
430 mov(destination, Operand(root), LeaveCC, cond);
431 return;
432 }
433 ldr(destination, MemOperand(kRootRegister, index << kPointerSizeLog2), cond);
434 } 275 }
435 276
436 277
437 void MacroAssembler::StoreRoot(Register source, 278 void MacroAssembler::StoreRoot(Register source,
438 Heap::RootListIndex index, 279 Heap::RootListIndex index,
439 Condition cond) { 280 Condition cond) {
440 str(source, MemOperand(kRootRegister, index << kPointerSizeLog2), cond); 281 DCHECK(cond == al);
282 StoreP(source, MemOperand(kRootRegister, index << kPointerSizeLog2), r0);
441 } 283 }
442 284
443 285
444 void MacroAssembler::InNewSpace(Register object, 286 void MacroAssembler::InNewSpace(Register object,
445 Register scratch, 287 Register scratch,
446 Condition cond, 288 Condition cond,
447 Label* branch) { 289 Label* branch) {
290 // N.B. scratch may be same register as object
448 DCHECK(cond == eq || cond == ne); 291 DCHECK(cond == eq || cond == ne);
449 and_(scratch, object, Operand(ExternalReference::new_space_mask(isolate()))); 292 mov(r0, Operand(ExternalReference::new_space_mask(isolate())));
450 cmp(scratch, Operand(ExternalReference::new_space_start(isolate()))); 293 and_(scratch, object, r0);
294 mov(r0, Operand(ExternalReference::new_space_start(isolate())));
295 cmp(scratch, r0);
451 b(cond, branch); 296 b(cond, branch);
452 } 297 }
453 298
454 299
455 void MacroAssembler::RecordWriteField( 300 void MacroAssembler::RecordWriteField(
456 Register object, 301 Register object,
457 int offset, 302 int offset,
458 Register value, 303 Register value,
459 Register dst, 304 Register dst,
460 LinkRegisterStatus lr_status, 305 LinkRegisterStatus lr_status,
461 SaveFPRegsMode save_fp, 306 SaveFPRegsMode save_fp,
462 RememberedSetAction remembered_set_action, 307 RememberedSetAction remembered_set_action,
463 SmiCheck smi_check, 308 SmiCheck smi_check,
464 PointersToHereCheck pointers_to_here_check_for_value) { 309 PointersToHereCheck pointers_to_here_check_for_value) {
465 // First, check if a write barrier is even needed. The tests below 310 // First, check if a write barrier is even needed. The tests below
466 // catch stores of Smis. 311 // catch stores of Smis.
467 Label done; 312 Label done;
468 313
469 // Skip barrier if writing a smi. 314 // Skip barrier if writing a smi.
470 if (smi_check == INLINE_SMI_CHECK) { 315 if (smi_check == INLINE_SMI_CHECK) {
471 JumpIfSmi(value, &done); 316 JumpIfSmi(value, &done);
472 } 317 }
473 318
474 // Although the object register is tagged, the offset is relative to the start 319 // Although the object register is tagged, the offset is relative to the start
475 // of the object, so so offset must be a multiple of kPointerSize. 320 // of the object, so so offset must be a multiple of kPointerSize.
476 DCHECK(IsAligned(offset, kPointerSize)); 321 DCHECK(IsAligned(offset, kPointerSize));
477 322
478 add(dst, object, Operand(offset - kHeapObjectTag)); 323 Add(dst, object, offset - kHeapObjectTag, r0);
479 if (emit_debug_code()) { 324 if (emit_debug_code()) {
480 Label ok; 325 Label ok;
481 tst(dst, Operand((1 << kPointerSizeLog2) - 1)); 326 andi(r0, dst, Operand((1 << kPointerSizeLog2) - 1));
482 b(eq, &ok); 327 beq(&ok, cr0);
483 stop("Unaligned cell in write barrier"); 328 stop("Unaligned cell in write barrier");
484 bind(&ok); 329 bind(&ok);
485 } 330 }
486 331
487 RecordWrite(object, 332 RecordWrite(object,
488 dst, 333 dst,
489 value, 334 value,
490 lr_status, 335 lr_status,
491 save_fp, 336 save_fp,
492 remembered_set_action, 337 remembered_set_action,
493 OMIT_SMI_CHECK, 338 OMIT_SMI_CHECK,
494 pointers_to_here_check_for_value); 339 pointers_to_here_check_for_value);
495 340
496 bind(&done); 341 bind(&done);
497 342
498 // Clobber clobbered input registers when running with the debug-code flag 343 // Clobber clobbered input registers when running with the debug-code flag
499 // turned on to provoke errors. 344 // turned on to provoke errors.
500 if (emit_debug_code()) { 345 if (emit_debug_code()) {
501 mov(value, Operand(BitCast<int32_t>(kZapValue + 4))); 346 mov(value, Operand(BitCast<intptr_t>(kZapValue + 4)));
502 mov(dst, Operand(BitCast<int32_t>(kZapValue + 8))); 347 mov(dst, Operand(BitCast<intptr_t>(kZapValue + 8)));
503 } 348 }
504 } 349 }
505 350
506 351
507 // Will clobber 4 registers: object, map, dst, ip. The 352 // Will clobber 4 registers: object, map, dst, ip. The
508 // register 'object' contains a heap object pointer. 353 // register 'object' contains a heap object pointer.
509 void MacroAssembler::RecordWriteForMap(Register object, 354 void MacroAssembler::RecordWriteForMap(Register object,
510 Register map, 355 Register map,
511 Register dst, 356 Register dst,
512 LinkRegisterStatus lr_status, 357 LinkRegisterStatus lr_status,
513 SaveFPRegsMode fp_mode) { 358 SaveFPRegsMode fp_mode) {
514 if (emit_debug_code()) { 359 if (emit_debug_code()) {
515 ldr(dst, FieldMemOperand(map, HeapObject::kMapOffset)); 360 LoadP(dst, FieldMemOperand(map, HeapObject::kMapOffset));
516 cmp(dst, Operand(isolate()->factory()->meta_map())); 361 Cmpi(dst, Operand(isolate()->factory()->meta_map()), r0);
517 Check(eq, kWrongAddressOrValuePassedToRecordWrite); 362 Check(eq, kWrongAddressOrValuePassedToRecordWrite);
518 } 363 }
519 364
520 if (!FLAG_incremental_marking) { 365 if (!FLAG_incremental_marking) {
521 return; 366 return;
522 } 367 }
523 368
524 if (emit_debug_code()) { 369 if (emit_debug_code()) {
525 ldr(ip, FieldMemOperand(object, HeapObject::kMapOffset)); 370 LoadP(ip, FieldMemOperand(object, HeapObject::kMapOffset));
526 cmp(ip, map); 371 cmp(ip, map);
527 Check(eq, kWrongAddressOrValuePassedToRecordWrite); 372 Check(eq, kWrongAddressOrValuePassedToRecordWrite);
528 } 373 }
529 374
530 Label done; 375 Label done;
531 376
532 // A single check of the map's pages interesting flag suffices, since it is 377 // A single check of the map's pages interesting flag suffices, since it is
533 // only set during incremental collection, and then it's also guaranteed that 378 // only set during incremental collection, and then it's also guaranteed that
534 // the from object's page's interesting flag is also set. This optimization 379 // the from object's page's interesting flag is also set. This optimization
535 // relies on the fact that maps can never be in new space. 380 // relies on the fact that maps can never be in new space.
536 CheckPageFlag(map, 381 CheckPageFlag(map,
537 map, // Used as scratch. 382 map, // Used as scratch.
538 MemoryChunk::kPointersToHereAreInterestingMask, 383 MemoryChunk::kPointersToHereAreInterestingMask,
539 eq, 384 eq,
540 &done); 385 &done);
541 386
542 add(dst, object, Operand(HeapObject::kMapOffset - kHeapObjectTag)); 387 addi(dst, object, Operand(HeapObject::kMapOffset - kHeapObjectTag));
543 if (emit_debug_code()) { 388 if (emit_debug_code()) {
544 Label ok; 389 Label ok;
545 tst(dst, Operand((1 << kPointerSizeLog2) - 1)); 390 andi(r0, dst, Operand((1 << kPointerSizeLog2) - 1));
546 b(eq, &ok); 391 beq(&ok, cr0);
547 stop("Unaligned cell in write barrier"); 392 stop("Unaligned cell in write barrier");
548 bind(&ok); 393 bind(&ok);
549 } 394 }
550 395
551 // Record the actual write. 396 // Record the actual write.
552 if (lr_status == kLRHasNotBeenSaved) { 397 if (lr_status == kLRHasNotBeenSaved) {
553 push(lr); 398 mflr(r0);
399 push(r0);
554 } 400 }
555 RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET, 401 RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET,
556 fp_mode); 402 fp_mode);
557 CallStub(&stub); 403 CallStub(&stub);
558 if (lr_status == kLRHasNotBeenSaved) { 404 if (lr_status == kLRHasNotBeenSaved) {
559 pop(lr); 405 pop(r0);
406 mtlr(r0);
560 } 407 }
561 408
562 bind(&done); 409 bind(&done);
563 410
564 // Count number of write barriers in generated code. 411 // Count number of write barriers in generated code.
565 isolate()->counters()->write_barriers_static()->Increment(); 412 isolate()->counters()->write_barriers_static()->Increment();
566 IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1, ip, dst); 413 IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1, ip, dst);
567 414
568 // Clobber clobbered registers when running with the debug-code flag 415 // Clobber clobbered registers when running with the debug-code flag
569 // turned on to provoke errors. 416 // turned on to provoke errors.
570 if (emit_debug_code()) { 417 if (emit_debug_code()) {
571 mov(dst, Operand(BitCast<int32_t>(kZapValue + 12))); 418 mov(dst, Operand(BitCast<intptr_t>(kZapValue + 12)));
572 mov(map, Operand(BitCast<int32_t>(kZapValue + 16))); 419 mov(map, Operand(BitCast<intptr_t>(kZapValue + 16)));
573 } 420 }
574 } 421 }
575 422
576 423
577 // Will clobber 4 registers: object, address, scratch, ip. The 424 // Will clobber 4 registers: object, address, scratch, ip. The
578 // register 'object' contains a heap object pointer. The heap object 425 // register 'object' contains a heap object pointer. The heap object
579 // tag is shifted away. 426 // tag is shifted away.
580 void MacroAssembler::RecordWrite( 427 void MacroAssembler::RecordWrite(
581 Register object, 428 Register object,
582 Register address, 429 Register address,
583 Register value, 430 Register value,
584 LinkRegisterStatus lr_status, 431 LinkRegisterStatus lr_status,
585 SaveFPRegsMode fp_mode, 432 SaveFPRegsMode fp_mode,
586 RememberedSetAction remembered_set_action, 433 RememberedSetAction remembered_set_action,
587 SmiCheck smi_check, 434 SmiCheck smi_check,
588 PointersToHereCheck pointers_to_here_check_for_value) { 435 PointersToHereCheck pointers_to_here_check_for_value) {
589 DCHECK(!object.is(value)); 436 DCHECK(!object.is(value));
590 if (emit_debug_code()) { 437 if (emit_debug_code()) {
591 ldr(ip, MemOperand(address)); 438 LoadP(ip, MemOperand(address));
592 cmp(ip, value); 439 cmp(ip, value);
593 Check(eq, kWrongAddressOrValuePassedToRecordWrite); 440 Check(eq, kWrongAddressOrValuePassedToRecordWrite);
594 } 441 }
595 442
596 if (remembered_set_action == OMIT_REMEMBERED_SET && 443 if (remembered_set_action == OMIT_REMEMBERED_SET &&
597 !FLAG_incremental_marking) { 444 !FLAG_incremental_marking) {
598 return; 445 return;
599 } 446 }
600 447
601 // First, check if a write barrier is even needed. The tests below 448 // First, check if a write barrier is even needed. The tests below
(...skipping 12 matching lines...) Expand all
614 &done); 461 &done);
615 } 462 }
616 CheckPageFlag(object, 463 CheckPageFlag(object,
617 value, // Used as scratch. 464 value, // Used as scratch.
618 MemoryChunk::kPointersFromHereAreInterestingMask, 465 MemoryChunk::kPointersFromHereAreInterestingMask,
619 eq, 466 eq,
620 &done); 467 &done);
621 468
622 // Record the actual write. 469 // Record the actual write.
623 if (lr_status == kLRHasNotBeenSaved) { 470 if (lr_status == kLRHasNotBeenSaved) {
624 push(lr); 471 mflr(r0);
472 push(r0);
625 } 473 }
626 RecordWriteStub stub(isolate(), object, value, address, remembered_set_action, 474 RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
627 fp_mode); 475 fp_mode);
628 CallStub(&stub); 476 CallStub(&stub);
629 if (lr_status == kLRHasNotBeenSaved) { 477 if (lr_status == kLRHasNotBeenSaved) {
630 pop(lr); 478 pop(r0);
479 mtlr(r0);
631 } 480 }
632 481
633 bind(&done); 482 bind(&done);
634 483
635 // Count number of write barriers in generated code. 484 // Count number of write barriers in generated code.
636 isolate()->counters()->write_barriers_static()->Increment(); 485 isolate()->counters()->write_barriers_static()->Increment();
637 IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1, ip, 486 IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1, ip,
638 value); 487 value);
639 488
640 // Clobber clobbered registers when running with the debug-code flag 489 // Clobber clobbered registers when running with the debug-code flag
641 // turned on to provoke errors. 490 // turned on to provoke errors.
642 if (emit_debug_code()) { 491 if (emit_debug_code()) {
643 mov(address, Operand(BitCast<int32_t>(kZapValue + 12))); 492 mov(address, Operand(BitCast<intptr_t>(kZapValue + 12)));
644 mov(value, Operand(BitCast<int32_t>(kZapValue + 16))); 493 mov(value, Operand(BitCast<intptr_t>(kZapValue + 16)));
645 } 494 }
646 } 495 }
647 496
648 497
649 void MacroAssembler::RememberedSetHelper(Register object, // For debug tests. 498 void MacroAssembler::RememberedSetHelper(Register object, // For debug tests.
650 Register address, 499 Register address,
651 Register scratch, 500 Register scratch,
652 SaveFPRegsMode fp_mode, 501 SaveFPRegsMode fp_mode,
653 RememberedSetFinalAction and_then) { 502 RememberedSetFinalAction and_then) {
654 Label done; 503 Label done;
655 if (emit_debug_code()) { 504 if (emit_debug_code()) {
656 Label ok; 505 Label ok;
657 JumpIfNotInNewSpace(object, scratch, &ok); 506 JumpIfNotInNewSpace(object, scratch, &ok);
658 stop("Remembered set pointer is in new space"); 507 stop("Remembered set pointer is in new space");
659 bind(&ok); 508 bind(&ok);
660 } 509 }
661 // Load store buffer top. 510 // Load store buffer top.
662 ExternalReference store_buffer = 511 ExternalReference store_buffer =
663 ExternalReference::store_buffer_top(isolate()); 512 ExternalReference::store_buffer_top(isolate());
664 mov(ip, Operand(store_buffer)); 513 mov(ip, Operand(store_buffer));
665 ldr(scratch, MemOperand(ip)); 514 LoadP(scratch, MemOperand(ip));
666 // Store pointer to buffer and increment buffer top. 515 // Store pointer to buffer and increment buffer top.
667 str(address, MemOperand(scratch, kPointerSize, PostIndex)); 516 StoreP(address, MemOperand(scratch));
517 addi(scratch, scratch, Operand(kPointerSize));
668 // Write back new top of buffer. 518 // Write back new top of buffer.
669 str(scratch, MemOperand(ip)); 519 StoreP(scratch, MemOperand(ip));
670 // Call stub on end of buffer. 520 // Call stub on end of buffer.
671 // Check for end of buffer. 521 // Check for end of buffer.
672 tst(scratch, Operand(StoreBuffer::kStoreBufferOverflowBit)); 522 mov(r0, Operand(StoreBuffer::kStoreBufferOverflowBit));
523 and_(r0, scratch, r0, SetRC);
524
673 if (and_then == kFallThroughAtEnd) { 525 if (and_then == kFallThroughAtEnd) {
674 b(eq, &done); 526 beq(&done, cr0);
675 } else { 527 } else {
676 DCHECK(and_then == kReturnAtEnd); 528 DCHECK(and_then == kReturnAtEnd);
677 Ret(eq); 529 beq(&done, cr0);
678 } 530 }
679 push(lr); 531 mflr(r0);
532 push(r0);
680 StoreBufferOverflowStub store_buffer_overflow = 533 StoreBufferOverflowStub store_buffer_overflow =
681 StoreBufferOverflowStub(isolate(), fp_mode); 534 StoreBufferOverflowStub(isolate(), fp_mode);
682 CallStub(&store_buffer_overflow); 535 CallStub(&store_buffer_overflow);
683 pop(lr); 536 pop(r0);
537 mtlr(r0);
684 bind(&done); 538 bind(&done);
685 if (and_then == kReturnAtEnd) { 539 if (and_then == kReturnAtEnd) {
686 Ret(); 540 Ret();
687 } 541 }
688 } 542 }
689 543
690 544
691 void MacroAssembler::PushFixedFrame(Register marker_reg) { 545 void MacroAssembler::PushFixedFrame(Register marker_reg) {
692 DCHECK(!marker_reg.is_valid() || marker_reg.code() < cp.code()); 546 mflr(r0);
693 stm(db_w, sp, (marker_reg.is_valid() ? marker_reg.bit() : 0) | 547 #if V8_OOL_CONSTANT_POOL
694 cp.bit() | 548 if (marker_reg.is_valid()) {
695 (FLAG_enable_ool_constant_pool ? pp.bit() : 0) | 549 Push(r0, fp, kConstantPoolRegister, cp, marker_reg);
696 fp.bit() | 550 } else {
697 lr.bit()); 551 Push(r0, fp, kConstantPoolRegister, cp);
552 }
553 #else
554 if (marker_reg.is_valid()) {
555 Push(r0, fp, cp, marker_reg);
556 } else {
557 Push(r0, fp, cp);
558 }
559 #endif
698 } 560 }
699 561
700 562
701 void MacroAssembler::PopFixedFrame(Register marker_reg) { 563 void MacroAssembler::PopFixedFrame(Register marker_reg) {
702 DCHECK(!marker_reg.is_valid() || marker_reg.code() < cp.code()); 564 #if V8_OOL_CONSTANT_POOL
703 ldm(ia_w, sp, (marker_reg.is_valid() ? marker_reg.bit() : 0) | 565 if (marker_reg.is_valid()) {
704 cp.bit() | 566 Pop(r0, fp, kConstantPoolRegister, cp, marker_reg);
705 (FLAG_enable_ool_constant_pool ? pp.bit() : 0) | 567 } else {
706 fp.bit() | 568 Pop(r0, fp, kConstantPoolRegister, cp);
707 lr.bit()); 569 }
570 #else
571 if (marker_reg.is_valid()) {
572 Pop(r0, fp, cp, marker_reg);
573 } else {
574 Pop(r0, fp, cp);
575 }
576 #endif
577 mtlr(r0);
708 } 578 }
709 579
710 580
711 // Push and pop all registers that can hold pointers. 581 // Push and pop all registers that can hold pointers.
712 void MacroAssembler::PushSafepointRegisters() { 582 void MacroAssembler::PushSafepointRegisters() {
713 // Safepoints expect a block of contiguous register values starting with r0:
714 DCHECK(((1 << kNumSafepointSavedRegisters) - 1) == kSafepointSavedRegisters);
715 // Safepoints expect a block of kNumSafepointRegisters values on the 583 // Safepoints expect a block of kNumSafepointRegisters values on the
716 // stack, so adjust the stack for unsaved registers. 584 // stack, so adjust the stack for unsaved registers.
717 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; 585 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
718 DCHECK(num_unsaved >= 0); 586 DCHECK(num_unsaved >= 0);
719 sub(sp, sp, Operand(num_unsaved * kPointerSize)); 587 if (num_unsaved > 0) {
720 stm(db_w, sp, kSafepointSavedRegisters); 588 subi(sp, sp, Operand(num_unsaved * kPointerSize));
589 }
590 MultiPush(kSafepointSavedRegisters);
721 } 591 }
722 592
723 593
724 void MacroAssembler::PopSafepointRegisters() { 594 void MacroAssembler::PopSafepointRegisters() {
725 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; 595 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
726 ldm(ia_w, sp, kSafepointSavedRegisters); 596 MultiPop(kSafepointSavedRegisters);
727 add(sp, sp, Operand(num_unsaved * kPointerSize)); 597 if (num_unsaved > 0) {
598 addi(sp, sp, Operand(num_unsaved * kPointerSize));
599 }
728 } 600 }
729 601
730 602
731 void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) { 603 void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) {
732 str(src, SafepointRegisterSlot(dst)); 604 StoreP(src, SafepointRegisterSlot(dst));
733 } 605 }
734 606
735 607
736 void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) { 608 void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
737 ldr(dst, SafepointRegisterSlot(src)); 609 LoadP(dst, SafepointRegisterSlot(src));
738 } 610 }
739 611
740 612
741 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) { 613 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
742 // The registers are pushed starting with the highest encoding, 614 // The registers are pushed starting with the highest encoding,
743 // which means that lowest encodings are closest to the stack pointer. 615 // which means that lowest encodings are closest to the stack pointer.
744 DCHECK(reg_code >= 0 && reg_code < kNumSafepointRegisters); 616 RegList regs = kSafepointSavedRegisters;
745 return reg_code; 617 int index = 0;
618
619 DCHECK(reg_code >= 0 && reg_code < kNumRegisters);
620
621 for (int16_t i = 0; i < reg_code; i++) {
622 if ((regs & (1 << i)) != 0) {
623 index++;
624 }
625 }
626
627 return index;
746 } 628 }
747 629
748 630
749 MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) { 631 MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
750 return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) * kPointerSize); 632 return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
751 } 633 }
752 634
753 635
754 MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) { 636 MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
755 // Number of d-regs not known at snapshot time.
756 DCHECK(!serializer_enabled());
757 // General purpose registers are pushed last on the stack. 637 // General purpose registers are pushed last on the stack.
758 int doubles_size = DwVfpRegister::NumAllocatableRegisters() * kDoubleSize; 638 int doubles_size = DoubleRegister::NumAllocatableRegisters() * kDoubleSize;
759 int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize; 639 int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
760 return MemOperand(sp, doubles_size + register_offset); 640 return MemOperand(sp, doubles_size + register_offset);
761 } 641 }
762 642
763 643
764 void MacroAssembler::Ldrd(Register dst1, Register dst2, 644 void MacroAssembler::CanonicalizeNaN(const DoubleRegister dst,
765 const MemOperand& src, Condition cond) { 645 const DoubleRegister src) {
766 DCHECK(src.rm().is(no_reg)); 646 Label done;
767 DCHECK(!dst1.is(lr)); // r14. 647
768 648 // Test for NaN
769 // V8 does not use this addressing mode, so the fallback code 649 fcmpu(src, src);
770 // below doesn't support it yet. 650
771 DCHECK((src.am() != PreIndex) && (src.am() != NegPreIndex)); 651 if (dst.is(src)) {
772 652 bordered(&done);
773 // Generate two ldr instructions if ldrd is not available.
774 if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size() &&
775 (dst1.code() % 2 == 0) && (dst1.code() + 1 == dst2.code())) {
776 CpuFeatureScope scope(this, ARMv7);
777 ldrd(dst1, dst2, src, cond);
778 } else { 653 } else {
779 if ((src.am() == Offset) || (src.am() == NegOffset)) { 654 Label is_nan;
780 MemOperand src2(src); 655 bunordered(&is_nan);
781 src2.set_offset(src2.offset() + 4); 656 fmr(dst, src);
782 if (dst1.is(src.rn())) { 657 b(&done);
783 ldr(dst2, src2, cond); 658 bind(&is_nan);
784 ldr(dst1, src, cond); 659 }
785 } else { 660
786 ldr(dst1, src, cond); 661 // Replace with canonical NaN.
787 ldr(dst2, src2, cond); 662 double nan_value = FixedDoubleArray::canonical_not_the_hole_nan_as_double();
788 } 663 LoadDoubleLiteral(dst, nan_value, r0);
789 } else { // PostIndex or NegPostIndex. 664
790 DCHECK((src.am() == PostIndex) || (src.am() == NegPostIndex)); 665 bind(&done);
791 if (dst1.is(src.rn())) { 666 }
792 ldr(dst2, MemOperand(src.rn(), 4, Offset), cond); 667
793 ldr(dst1, src, cond); 668
794 } else { 669 void MacroAssembler::ConvertIntToDouble(Register src,
795 MemOperand src2(src); 670 DoubleRegister double_dst) {
796 src2.set_offset(src2.offset() - 4); 671 MovIntToDouble(double_dst, src, r0);
797 ldr(dst1, MemOperand(src.rn(), 4, PostIndex), cond); 672 fcfid(double_dst, double_dst);
798 ldr(dst2, src2, cond); 673 }
799 } 674
800 } 675
801 } 676 void MacroAssembler::ConvertUnsignedIntToDouble(Register src,
802 } 677 DoubleRegister double_dst) {
803 678 MovUnsignedIntToDouble(double_dst, src, r0);
804 679 fcfid(double_dst, double_dst);
805 void MacroAssembler::Strd(Register src1, Register src2, 680 }
806 const MemOperand& dst, Condition cond) { 681
807 DCHECK(dst.rm().is(no_reg)); 682
808 DCHECK(!src1.is(lr)); // r14. 683 void MacroAssembler::ConvertIntToFloat(const DoubleRegister dst,
809 684 const Register src,
810 // V8 does not use this addressing mode, so the fallback code 685 const Register int_scratch) {
811 // below doesn't support it yet. 686 MovIntToDouble(dst, src, int_scratch);
812 DCHECK((dst.am() != PreIndex) && (dst.am() != NegPreIndex)); 687 fcfid(dst, dst);
813 688 frsp(dst, dst);
814 // Generate two str instructions if strd is not available. 689 }
815 if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size() && 690
816 (src1.code() % 2 == 0) && (src1.code() + 1 == src2.code())) { 691
817 CpuFeatureScope scope(this, ARMv7); 692 void MacroAssembler::ConvertDoubleToInt64(const DoubleRegister double_input,
818 strd(src1, src2, dst, cond); 693 #if !V8_TARGET_ARCH_PPC64
694 const Register dst_hi,
695 #endif
696 const Register dst,
697 const DoubleRegister double_dst,
698 FPRoundingMode rounding_mode) {
699 if (rounding_mode == kRoundToZero) {
700 fctidz(double_dst, double_input);
819 } else { 701 } else {
820 MemOperand dst2(dst); 702 SetRoundingMode(rounding_mode);
821 if ((dst.am() == Offset) || (dst.am() == NegOffset)) { 703 fctid(double_dst, double_input);
822 dst2.set_offset(dst2.offset() + 4); 704 ResetRoundingMode();
823 str(src1, dst, cond); 705 }
824 str(src2, dst2, cond); 706
825 } else { // PostIndex or NegPostIndex. 707 MovDoubleToInt64(
826 DCHECK((dst.am() == PostIndex) || (dst.am() == NegPostIndex)); 708 #if !V8_TARGET_ARCH_PPC64
827 dst2.set_offset(dst2.offset() - 4); 709 dst_hi,
828 str(src1, MemOperand(dst.rn(), 4, PostIndex), cond); 710 #endif
829 str(src2, dst2, cond); 711 dst, double_dst);
830 } 712 }
831 } 713
832 } 714
833 715 #if V8_OOL_CONSTANT_POOL
834
835 void MacroAssembler::VFPEnsureFPSCRState(Register scratch) {
836 // If needed, restore wanted bits of FPSCR.
837 Label fpscr_done;
838 vmrs(scratch);
839 if (emit_debug_code()) {
840 Label rounding_mode_correct;
841 tst(scratch, Operand(kVFPRoundingModeMask));
842 b(eq, &rounding_mode_correct);
843 // Don't call Assert here, since Runtime_Abort could re-enter here.
844 stop("Default rounding mode not set");
845 bind(&rounding_mode_correct);
846 }
847 tst(scratch, Operand(kVFPDefaultNaNModeControlBit));
848 b(ne, &fpscr_done);
849 orr(scratch, scratch, Operand(kVFPDefaultNaNModeControlBit));
850 vmsr(scratch);
851 bind(&fpscr_done);
852 }
853
854
855 void MacroAssembler::VFPCanonicalizeNaN(const DwVfpRegister dst,
856 const DwVfpRegister src,
857 const Condition cond) {
858 vsub(dst, src, kDoubleRegZero, cond);
859 }
860
861
862 void MacroAssembler::VFPCompareAndSetFlags(const DwVfpRegister src1,
863 const DwVfpRegister src2,
864 const Condition cond) {
865 // Compare and move FPSCR flags to the normal condition flags.
866 VFPCompareAndLoadFlags(src1, src2, pc, cond);
867 }
868
869 void MacroAssembler::VFPCompareAndSetFlags(const DwVfpRegister src1,
870 const double src2,
871 const Condition cond) {
872 // Compare and move FPSCR flags to the normal condition flags.
873 VFPCompareAndLoadFlags(src1, src2, pc, cond);
874 }
875
876
877 void MacroAssembler::VFPCompareAndLoadFlags(const DwVfpRegister src1,
878 const DwVfpRegister src2,
879 const Register fpscr_flags,
880 const Condition cond) {
881 // Compare and load FPSCR.
882 vcmp(src1, src2, cond);
883 vmrs(fpscr_flags, cond);
884 }
885
886 void MacroAssembler::VFPCompareAndLoadFlags(const DwVfpRegister src1,
887 const double src2,
888 const Register fpscr_flags,
889 const Condition cond) {
890 // Compare and load FPSCR.
891 vcmp(src1, src2, cond);
892 vmrs(fpscr_flags, cond);
893 }
894
895 void MacroAssembler::Vmov(const DwVfpRegister dst,
896 const double imm,
897 const Register scratch) {
898 static const DoubleRepresentation minus_zero(-0.0);
899 static const DoubleRepresentation zero(0.0);
900 DoubleRepresentation value_rep(imm);
901 // Handle special values first.
902 if (value_rep == zero) {
903 vmov(dst, kDoubleRegZero);
904 } else if (value_rep == minus_zero) {
905 vneg(dst, kDoubleRegZero);
906 } else {
907 vmov(dst, imm, scratch);
908 }
909 }
910
911
912 void MacroAssembler::VmovHigh(Register dst, DwVfpRegister src) {
913 if (src.code() < 16) {
914 const LowDwVfpRegister loc = LowDwVfpRegister::from_code(src.code());
915 vmov(dst, loc.high());
916 } else {
917 vmov(dst, VmovIndexHi, src);
918 }
919 }
920
921
922 void MacroAssembler::VmovHigh(DwVfpRegister dst, Register src) {
923 if (dst.code() < 16) {
924 const LowDwVfpRegister loc = LowDwVfpRegister::from_code(dst.code());
925 vmov(loc.high(), src);
926 } else {
927 vmov(dst, VmovIndexHi, src);
928 }
929 }
930
931
932 void MacroAssembler::VmovLow(Register dst, DwVfpRegister src) {
933 if (src.code() < 16) {
934 const LowDwVfpRegister loc = LowDwVfpRegister::from_code(src.code());
935 vmov(dst, loc.low());
936 } else {
937 vmov(dst, VmovIndexLo, src);
938 }
939 }
940
941
942 void MacroAssembler::VmovLow(DwVfpRegister dst, Register src) {
943 if (dst.code() < 16) {
944 const LowDwVfpRegister loc = LowDwVfpRegister::from_code(dst.code());
945 vmov(loc.low(), src);
946 } else {
947 vmov(dst, VmovIndexLo, src);
948 }
949 }
950
951
952 void MacroAssembler::LoadConstantPoolPointerRegister() { 716 void MacroAssembler::LoadConstantPoolPointerRegister() {
953 if (FLAG_enable_ool_constant_pool) { 717 ConstantPoolUnavailableScope constant_pool_unavailable(this);
954 int constant_pool_offset = Code::kConstantPoolOffset - Code::kHeaderSize - 718
955 pc_offset() - Instruction::kPCReadOffset; 719 // CheckBuffer() is called too frequently. This will pre-grow
956 DCHECK(ImmediateFitsAddrMode2Instruction(constant_pool_offset)); 720 // the buffer if needed to avoid spliting the relocation and instructions
957 ldr(pp, MemOperand(pc, constant_pool_offset)); 721 EnsureSpaceFor(kMovInstructionsNoConstantPool * kInstrSize);
958 } 722
959 } 723 uintptr_t code_start = reinterpret_cast<uintptr_t>(pc_) - pc_offset();
724 int constant_pool_offset = Code::kConstantPoolOffset - Code::kHeaderSize;
725 mov(kConstantPoolRegister,
726 Operand(code_start, RelocInfo::INTERNAL_REFERENCE));
727 LoadP(kConstantPoolRegister,
728 MemOperand(kConstantPoolRegister, constant_pool_offset));
729 }
730 #endif
960 731
961 732
962 void MacroAssembler::StubPrologue() { 733 void MacroAssembler::StubPrologue() {
963 PushFixedFrame(); 734 PushFixedFrame();
964 Push(Smi::FromInt(StackFrame::STUB)); 735 Push(Smi::FromInt(StackFrame::STUB));
965 // Adjust FP to point to saved FP. 736 // Adjust FP to point to saved FP.
966 add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); 737 addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
967 if (FLAG_enable_ool_constant_pool) { 738 #if V8_OOL_CONSTANT_POOL
968 LoadConstantPoolPointerRegister(); 739 LoadConstantPoolPointerRegister();
969 set_constant_pool_available(true); 740 set_constant_pool_available(true);
970 } 741 #endif
971 } 742 }
972 743
973 744
974 void MacroAssembler::Prologue(bool code_pre_aging) { 745 void MacroAssembler::Prologue(bool code_pre_aging) {
975 { PredictableCodeSizeScope predictible_code_size_scope( 746 { PredictableCodeSizeScope predictible_code_size_scope(
976 this, kNoCodeAgeSequenceLength); 747 this, kNoCodeAgeSequenceLength);
977 // The following three instructions must remain together and unmodified 748 Assembler::BlockTrampolinePoolScope block_trampoline_pool(this);
749 // The following instructions must remain together and unmodified
978 // for code aging to work properly. 750 // for code aging to work properly.
979 if (code_pre_aging) { 751 if (code_pre_aging) {
980 // Pre-age the code. 752 // Pre-age the code.
753 // This matches the code found in PatchPlatformCodeAge()
981 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); 754 Code* stub = Code::GetPreAgedCodeAgeStub(isolate());
982 add(r0, pc, Operand(-8)); 755 intptr_t target = reinterpret_cast<intptr_t>(stub->instruction_start());
983 ldr(pc, MemOperand(pc, -4)); 756 mflr(ip);
984 emit_code_stub_address(stub); 757 mov(r3, Operand(target));
758 Call(r3);
759 for (int i = 0; i < kCodeAgingSequenceNops; i++) {
760 nop();
761 }
985 } else { 762 } else {
986 PushFixedFrame(r1); 763 // This matches the code found in GetNoCodeAgeSequence()
987 nop(ip.code()); 764 PushFixedFrame(r4);
988 // Adjust FP to point to saved FP. 765 // Adjust fp to point to saved fp.
989 add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); 766 addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
767 for (int i = 0; i < kNoCodeAgeSequenceNops; i++) {
768 nop();
769 }
990 } 770 }
991 } 771 }
992 if (FLAG_enable_ool_constant_pool) { 772 #if V8_OOL_CONSTANT_POOL
993 LoadConstantPoolPointerRegister(); 773 LoadConstantPoolPointerRegister();
994 set_constant_pool_available(true); 774 set_constant_pool_available(true);
995 } 775 #endif
996 } 776 }
997 777
998 778
999 void MacroAssembler::EnterFrame(StackFrame::Type type, 779 void MacroAssembler::EnterFrame(StackFrame::Type type,
1000 bool load_constant_pool) { 780 bool load_constant_pool) {
1001 // r0-r3: preserved
1002 PushFixedFrame(); 781 PushFixedFrame();
1003 if (FLAG_enable_ool_constant_pool && load_constant_pool) { 782 #if V8_OOL_CONSTANT_POOL
783 if (load_constant_pool) {
1004 LoadConstantPoolPointerRegister(); 784 LoadConstantPoolPointerRegister();
1005 } 785 }
1006 mov(ip, Operand(Smi::FromInt(type))); 786 #endif
1007 push(ip); 787 LoadSmiLiteral(r0, Smi::FromInt(type));
1008 mov(ip, Operand(CodeObject())); 788 push(r0);
1009 push(ip); 789 mov(r0, Operand(CodeObject()));
790 push(r0);
1010 // Adjust FP to point to saved FP. 791 // Adjust FP to point to saved FP.
1011 add(fp, sp, 792 addi(fp, sp,
1012 Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize)); 793 Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize));
1013 } 794 }
1014 795
1015 796
1016 int MacroAssembler::LeaveFrame(StackFrame::Type type) { 797 int MacroAssembler::LeaveFrame(StackFrame::Type type) {
1017 // r0: preserved 798 // r3: preserved
1018 // r1: preserved 799 // r4: preserved
1019 // r2: preserved 800 // r5: preserved
1020 801
1021 // Drop the execution stack down to the frame pointer and restore 802 // Drop the execution stack down to the frame pointer and restore
1022 // the caller frame pointer, return address and constant pool pointer 803 // the caller frame pointer, return address and constant pool pointer.
1023 // (if FLAG_enable_ool_constant_pool).
1024 int frame_ends; 804 int frame_ends;
1025 if (FLAG_enable_ool_constant_pool) { 805 #if V8_OOL_CONSTANT_POOL
1026 add(sp, fp, Operand(StandardFrameConstants::kConstantPoolOffset)); 806 addi(sp, fp, Operand(StandardFrameConstants::kConstantPoolOffset));
1027 frame_ends = pc_offset(); 807 frame_ends = pc_offset();
1028 ldm(ia_w, sp, pp.bit() | fp.bit() | lr.bit()); 808 Pop(r0, fp, kConstantPoolRegister);
1029 } else { 809 #else
1030 mov(sp, fp); 810 mr(sp, fp);
1031 frame_ends = pc_offset(); 811 frame_ends = pc_offset();
1032 ldm(ia_w, sp, fp.bit() | lr.bit()); 812 Pop(r0, fp);
1033 } 813 #endif
814 mtlr(r0);
1034 return frame_ends; 815 return frame_ends;
1035 } 816 }
1036 817
1037 818
819 // ExitFrame layout (probably wrongish.. needs updating)
820 //
821 // SP -> previousSP
822 // LK reserved
823 // code
824 // sp_on_exit (for debug?)
825 // oldSP->prev SP
826 // LK
827 // <parameters on stack>
828
829 // Prior to calling EnterExitFrame, we've got a bunch of parameters
830 // on the stack that we need to wrap a real frame around.. so first
831 // we reserve a slot for LK and push the previous SP which is captured
832 // in the fp register (r31)
833 // Then - we buy a new frame
834
1038 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { 835 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) {
1039 // Set up the frame structure on the stack. 836 // Set up the frame structure on the stack.
1040 DCHECK_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); 837 DCHECK_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement);
1041 DCHECK_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); 838 DCHECK_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset);
1042 DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); 839 DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
1043 Push(lr, fp); 840 DCHECK(stack_space > 0);
1044 mov(fp, Operand(sp)); // Set up new frame pointer. 841
842 // This is an opportunity to build a frame to wrap
843 // all of the pushes that have happened inside of V8
844 // since we were called from C code
845
846 // replicate ARM frame - TODO make this more closely follow PPC ABI
847 mflr(r0);
848 Push(r0, fp);
849 mr(fp, sp);
1045 // Reserve room for saved entry sp and code object. 850 // Reserve room for saved entry sp and code object.
1046 sub(sp, sp, Operand(ExitFrameConstants::kFrameSize)); 851 subi(sp, sp, Operand(ExitFrameConstants::kFrameSize));
852
1047 if (emit_debug_code()) { 853 if (emit_debug_code()) {
1048 mov(ip, Operand::Zero()); 854 li(r8, Operand::Zero());
1049 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); 855 StoreP(r8, MemOperand(fp, ExitFrameConstants::kSPOffset));
1050 } 856 }
1051 if (FLAG_enable_ool_constant_pool) { 857 #if V8_OOL_CONSTANT_POOL
1052 str(pp, MemOperand(fp, ExitFrameConstants::kConstantPoolOffset)); 858 StoreP(kConstantPoolRegister,
1053 } 859 MemOperand(fp, ExitFrameConstants::kConstantPoolOffset));
1054 mov(ip, Operand(CodeObject())); 860 #endif
1055 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); 861 mov(r8, Operand(CodeObject()));
862 StoreP(r8, MemOperand(fp, ExitFrameConstants::kCodeOffset));
1056 863
1057 // Save the frame pointer and the context in top. 864 // Save the frame pointer and the context in top.
1058 mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); 865 mov(r8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
1059 str(fp, MemOperand(ip)); 866 StoreP(fp, MemOperand(r8));
1060 mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); 867 mov(r8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
1061 str(cp, MemOperand(ip)); 868 StoreP(cp, MemOperand(r8));
1062 869
1063 // Optionally save all double registers. 870 // Optionally save all volatile double registers.
1064 if (save_doubles) { 871 if (save_doubles) {
1065 SaveFPRegs(sp, ip); 872 SaveFPRegs(sp, 0, DoubleRegister::kNumVolatileRegisters);
1066 // Note that d0 will be accessible at 873 // Note that d0 will be accessible at
1067 // fp - ExitFrameConstants::kFrameSize - 874 // fp - ExitFrameConstants::kFrameSize -
1068 // DwVfpRegister::kMaxNumRegisters * kDoubleSize, 875 // kNumVolatileRegisters * kDoubleSize,
1069 // since the sp slot, code slot and constant pool slot (if 876 // since the sp slot and code slot were pushed after the fp.
1070 // FLAG_enable_ool_constant_pool) were pushed after the fp. 877 }
1071 } 878
1072 879 addi(sp, sp, Operand(-stack_space * kPointerSize));
1073 // Reserve place for the return address and stack space and align the frame 880
1074 // preparing for calling the runtime function. 881 // Allocate and align the frame preparing for calling the runtime
1075 const int frame_alignment = MacroAssembler::ActivationFrameAlignment(); 882 // function.
1076 sub(sp, sp, Operand((stack_space + 1) * kPointerSize)); 883 const int frame_alignment = ActivationFrameAlignment();
1077 if (frame_alignment > 0) { 884 if (frame_alignment > kPointerSize) {
1078 DCHECK(IsPowerOf2(frame_alignment)); 885 DCHECK(IsPowerOf2(frame_alignment));
1079 and_(sp, sp, Operand(-frame_alignment)); 886 ClearRightImm(sp, sp, Operand(WhichPowerOf2(frame_alignment)));
1080 } 887 }
888 li(r0, Operand::Zero());
889 StorePU(r0, MemOperand(sp, -kNumRequiredStackFrameSlots * kPointerSize));
1081 890
1082 // Set the exit frame sp value to point just before the return address 891 // Set the exit frame sp value to point just before the return address
1083 // location. 892 // location.
1084 add(ip, sp, Operand(kPointerSize)); 893 addi(r8, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize));
1085 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); 894 StoreP(r8, MemOperand(fp, ExitFrameConstants::kSPOffset));
1086 } 895 }
1087 896
1088 897
1089 void MacroAssembler::InitializeNewString(Register string, 898 void MacroAssembler::InitializeNewString(Register string,
1090 Register length, 899 Register length,
1091 Heap::RootListIndex map_index, 900 Heap::RootListIndex map_index,
1092 Register scratch1, 901 Register scratch1,
1093 Register scratch2) { 902 Register scratch2) {
1094 SmiTag(scratch1, length); 903 SmiTag(scratch1, length);
1095 LoadRoot(scratch2, map_index); 904 LoadRoot(scratch2, map_index);
1096 str(scratch1, FieldMemOperand(string, String::kLengthOffset)); 905 StoreP(scratch1, FieldMemOperand(string, String::kLengthOffset), r0);
1097 mov(scratch1, Operand(String::kEmptyHashField)); 906 li(scratch1, Operand(String::kEmptyHashField));
1098 str(scratch2, FieldMemOperand(string, HeapObject::kMapOffset)); 907 StoreP(scratch2, FieldMemOperand(string, HeapObject::kMapOffset), r0);
1099 str(scratch1, FieldMemOperand(string, String::kHashFieldOffset)); 908 StoreP(scratch1, FieldMemOperand(string, String::kHashFieldSlot), r0);
1100 } 909 }
1101 910
1102 911
1103 int MacroAssembler::ActivationFrameAlignment() { 912 int MacroAssembler::ActivationFrameAlignment() {
1104 #if V8_HOST_ARCH_ARM 913 #if !defined(USE_SIMULATOR)
1105 // Running on the real platform. Use the alignment as mandated by the local 914 // Running on the real platform. Use the alignment as mandated by the local
1106 // environment. 915 // environment.
1107 // Note: This will break if we ever start generating snapshots on one ARM 916 // Note: This will break if we ever start generating snapshots on one PPC
1108 // platform for another ARM platform with a different alignment. 917 // platform for another PPC platform with a different alignment.
1109 return base::OS::ActivationFrameAlignment(); 918 return base::OS::ActivationFrameAlignment();
1110 #else // V8_HOST_ARCH_ARM 919 #else // Simulated
1111 // If we are using the simulator then we should always align to the expected 920 // If we are using the simulator then we should always align to the expected
1112 // alignment. As the simulator is used to generate snapshots we do not know 921 // alignment. As the simulator is used to generate snapshots we do not know
1113 // if the target platform will need alignment, so this is controlled from a 922 // if the target platform will need alignment, so this is controlled from a
1114 // flag. 923 // flag.
1115 return FLAG_sim_stack_alignment; 924 return FLAG_sim_stack_alignment;
1116 #endif // V8_HOST_ARCH_ARM 925 #endif
1117 } 926 }
1118 927
1119 928
1120 void MacroAssembler::LeaveExitFrame(bool save_doubles, 929 void MacroAssembler::LeaveExitFrame(bool save_doubles,
1121 Register argument_count, 930 Register argument_count,
1122 bool restore_context) { 931 bool restore_context) {
932 #if V8_OOL_CONSTANT_POOL
1123 ConstantPoolUnavailableScope constant_pool_unavailable(this); 933 ConstantPoolUnavailableScope constant_pool_unavailable(this);
1124 934 #endif
1125 // Optionally restore all double registers. 935 // Optionally restore all double registers.
1126 if (save_doubles) { 936 if (save_doubles) {
1127 // Calculate the stack location of the saved doubles and restore them. 937 // Calculate the stack location of the saved doubles and restore them.
1128 const int offset = ExitFrameConstants::kFrameSize; 938 const int kNumRegs = DoubleRegister::kNumVolatileRegisters;
1129 sub(r3, fp, 939 const int offset = (ExitFrameConstants::kFrameSize +
1130 Operand(offset + DwVfpRegister::kMaxNumRegisters * kDoubleSize)); 940 kNumRegs * kDoubleSize);
1131 RestoreFPRegs(r3, ip); 941 addi(r6, fp, Operand(-offset));
942 RestoreFPRegs(r6, 0, kNumRegs);
1132 } 943 }
1133 944
1134 // Clear top frame. 945 // Clear top frame.
1135 mov(r3, Operand::Zero()); 946 li(r6, Operand::Zero());
1136 mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); 947 mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
1137 str(r3, MemOperand(ip)); 948 StoreP(r6, MemOperand(ip));
1138 949
1139 // Restore current context from top and clear it in debug mode. 950 // Restore current context from top and clear it in debug mode.
1140 if (restore_context) { 951 if (restore_context) {
1141 mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); 952 mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
1142 ldr(cp, MemOperand(ip)); 953 LoadP(cp, MemOperand(ip));
1143 } 954 }
1144 #ifdef DEBUG 955 #ifdef DEBUG
1145 mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); 956 mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
1146 str(r3, MemOperand(ip)); 957 StoreP(r6, MemOperand(ip));
1147 #endif 958 #endif
1148 959
1149 // Tear down the exit frame, pop the arguments, and return. 960 // Tear down the exit frame, pop the arguments, and return.
1150 if (FLAG_enable_ool_constant_pool) { 961 #if V8_OOL_CONSTANT_POOL
1151 ldr(pp, MemOperand(fp, ExitFrameConstants::kConstantPoolOffset)); 962 LoadP(kConstantPoolRegister,
1152 } 963 MemOperand(fp, ExitFrameConstants::kConstantPoolOffset));
1153 mov(sp, Operand(fp)); 964 #endif
1154 ldm(ia_w, sp, fp.bit() | lr.bit()); 965 mr(sp, fp);
966 pop(fp);
967 pop(r0);
968 mtlr(r0);
969
1155 if (argument_count.is_valid()) { 970 if (argument_count.is_valid()) {
1156 add(sp, sp, Operand(argument_count, LSL, kPointerSizeLog2)); 971 ShiftLeftImm(argument_count, argument_count, Operand(kPointerSizeLog2));
972 add(sp, sp, argument_count);
1157 } 973 }
1158 } 974 }
1159 975
1160 976
1161 void MacroAssembler::MovFromFloatResult(const DwVfpRegister dst) { 977 void MacroAssembler::MovFromFloatResult(const DoubleRegister dst) {
1162 if (use_eabi_hardfloat()) { 978 Move(dst, d1);
1163 Move(dst, d0);
1164 } else {
1165 vmov(dst, r0, r1);
1166 }
1167 } 979 }
1168 980
1169 981
1170 // On ARM this is just a synonym to make the purpose clear. 982 void MacroAssembler::MovFromFloatParameter(const DoubleRegister dst) {
1171 void MacroAssembler::MovFromFloatParameter(DwVfpRegister dst) { 983 Move(dst, d1);
1172 MovFromFloatResult(dst);
1173 } 984 }
1174 985
1175 986
1176 void MacroAssembler::InvokePrologue(const ParameterCount& expected, 987 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
1177 const ParameterCount& actual, 988 const ParameterCount& actual,
1178 Handle<Code> code_constant, 989 Handle<Code> code_constant,
1179 Register code_reg, 990 Register code_reg,
1180 Label* done, 991 Label* done,
1181 bool* definitely_mismatches, 992 bool* definitely_mismatches,
1182 InvokeFlag flag, 993 InvokeFlag flag,
1183 const CallWrapper& call_wrapper) { 994 const CallWrapper& call_wrapper) {
1184 bool definitely_matches = false; 995 bool definitely_matches = false;
1185 *definitely_mismatches = false; 996 *definitely_mismatches = false;
1186 Label regular_invoke; 997 Label regular_invoke;
1187 998
1188 // Check whether the expected and actual arguments count match. If not, 999 // Check whether the expected and actual arguments count match. If not,
1189 // setup registers according to contract with ArgumentsAdaptorTrampoline: 1000 // setup registers according to contract with ArgumentsAdaptorTrampoline:
1190 // r0: actual arguments count 1001 // r3: actual arguments count
1191 // r1: function (passed through to callee) 1002 // r4: function (passed through to callee)
1192 // r2: expected arguments count 1003 // r5: expected arguments count
1193 1004
1194 // The code below is made a lot easier because the calling code already sets 1005 // The code below is made a lot easier because the calling code already sets
1195 // up actual and expected registers according to the contract if values are 1006 // up actual and expected registers according to the contract if values are
1196 // passed in registers. 1007 // passed in registers.
1197 DCHECK(actual.is_immediate() || actual.reg().is(r0)); 1008
1198 DCHECK(expected.is_immediate() || expected.reg().is(r2)); 1009 // roohack - remove these 3 checks temporarily
1199 DCHECK((!code_constant.is_null() && code_reg.is(no_reg)) || code_reg.is(r3)); 1010 // DCHECK(actual.is_immediate() || actual.reg().is(r3));
1011 // DCHECK(expected.is_immediate() || expected.reg().is(r5));
1012 // DCHECK((!code_constant.is_null() && code_reg.is(no_reg))
1013 // || code_reg.is(r6));
1200 1014
1201 if (expected.is_immediate()) { 1015 if (expected.is_immediate()) {
1202 DCHECK(actual.is_immediate()); 1016 DCHECK(actual.is_immediate());
1203 if (expected.immediate() == actual.immediate()) { 1017 if (expected.immediate() == actual.immediate()) {
1204 definitely_matches = true; 1018 definitely_matches = true;
1205 } else { 1019 } else {
1206 mov(r0, Operand(actual.immediate())); 1020 mov(r3, Operand(actual.immediate()));
1207 const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel; 1021 const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
1208 if (expected.immediate() == sentinel) { 1022 if (expected.immediate() == sentinel) {
1209 // Don't worry about adapting arguments for builtins that 1023 // Don't worry about adapting arguments for builtins that
1210 // don't want that done. Skip adaption code by making it look 1024 // don't want that done. Skip adaption code by making it look
1211 // like we have a match between expected and actual number of 1025 // like we have a match between expected and actual number of
1212 // arguments. 1026 // arguments.
1213 definitely_matches = true; 1027 definitely_matches = true;
1214 } else { 1028 } else {
1215 *definitely_mismatches = true; 1029 *definitely_mismatches = true;
1216 mov(r2, Operand(expected.immediate())); 1030 mov(r5, Operand(expected.immediate()));
1217 } 1031 }
1218 } 1032 }
1219 } else { 1033 } else {
1220 if (actual.is_immediate()) { 1034 if (actual.is_immediate()) {
1221 cmp(expected.reg(), Operand(actual.immediate())); 1035 cmpi(expected.reg(), Operand(actual.immediate()));
1222 b(eq, &regular_invoke); 1036 beq(&regular_invoke);
1223 mov(r0, Operand(actual.immediate())); 1037 mov(r3, Operand(actual.immediate()));
1224 } else { 1038 } else {
1225 cmp(expected.reg(), Operand(actual.reg())); 1039 cmp(expected.reg(), actual.reg());
1226 b(eq, &regular_invoke); 1040 beq(&regular_invoke);
1227 } 1041 }
1228 } 1042 }
1229 1043
1230 if (!definitely_matches) { 1044 if (!definitely_matches) {
1231 if (!code_constant.is_null()) { 1045 if (!code_constant.is_null()) {
1232 mov(r3, Operand(code_constant)); 1046 mov(r6, Operand(code_constant));
1233 add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); 1047 addi(r6, r6, Operand(Code::kHeaderSize - kHeapObjectTag));
1234 } 1048 }
1235 1049
1236 Handle<Code> adaptor = 1050 Handle<Code> adaptor =
1237 isolate()->builtins()->ArgumentsAdaptorTrampoline(); 1051 isolate()->builtins()->ArgumentsAdaptorTrampoline();
1238 if (flag == CALL_FUNCTION) { 1052 if (flag == CALL_FUNCTION) {
1239 call_wrapper.BeforeCall(CallSize(adaptor)); 1053 call_wrapper.BeforeCall(CallSize(adaptor));
1240 Call(adaptor); 1054 Call(adaptor);
1241 call_wrapper.AfterCall(); 1055 call_wrapper.AfterCall();
1242 if (!*definitely_mismatches) { 1056 if (!*definitely_mismatches) {
1243 b(done); 1057 b(done);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1280 } 1094 }
1281 1095
1282 1096
1283 void MacroAssembler::InvokeFunction(Register fun, 1097 void MacroAssembler::InvokeFunction(Register fun,
1284 const ParameterCount& actual, 1098 const ParameterCount& actual,
1285 InvokeFlag flag, 1099 InvokeFlag flag,
1286 const CallWrapper& call_wrapper) { 1100 const CallWrapper& call_wrapper) {
1287 // You can't call a function without a valid frame. 1101 // You can't call a function without a valid frame.
1288 DCHECK(flag == JUMP_FUNCTION || has_frame()); 1102 DCHECK(flag == JUMP_FUNCTION || has_frame());
1289 1103
1290 // Contract with called JS functions requires that function is passed in r1. 1104 // Contract with called JS functions requires that function is passed in r4.
1291 DCHECK(fun.is(r1)); 1105 DCHECK(fun.is(r4));
1292 1106
1293 Register expected_reg = r2; 1107 Register expected_reg = r5;
1294 Register code_reg = r3; 1108 Register code_reg = r6;
1295 1109
1296 ldr(code_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 1110 LoadP(code_reg, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
1297 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 1111 LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
1298 ldr(expected_reg, 1112 LoadWordArith(expected_reg,
1299 FieldMemOperand(code_reg, 1113 FieldMemOperand(code_reg,
1300 SharedFunctionInfo::kFormalParameterCountOffset)); 1114 SharedFunctionInfo::kFormalParameterCountOffset));
1115 #if !defined(V8_TARGET_ARCH_PPC64)
1301 SmiUntag(expected_reg); 1116 SmiUntag(expected_reg);
1302 ldr(code_reg, 1117 #endif
1303 FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); 1118 LoadP(code_reg,
1119 FieldMemOperand(r4, JSFunction::kCodeEntryOffset));
1304 1120
1305 ParameterCount expected(expected_reg); 1121 ParameterCount expected(expected_reg);
1306 InvokeCode(code_reg, expected, actual, flag, call_wrapper); 1122 InvokeCode(code_reg, expected, actual, flag, call_wrapper);
1307 } 1123 }
1308 1124
1309 1125
1310 void MacroAssembler::InvokeFunction(Register function, 1126 void MacroAssembler::InvokeFunction(Register function,
1311 const ParameterCount& expected, 1127 const ParameterCount& expected,
1312 const ParameterCount& actual, 1128 const ParameterCount& actual,
1313 InvokeFlag flag, 1129 InvokeFlag flag,
1314 const CallWrapper& call_wrapper) { 1130 const CallWrapper& call_wrapper) {
1315 // You can't call a function without a valid frame. 1131 // You can't call a function without a valid frame.
1316 DCHECK(flag == JUMP_FUNCTION || has_frame()); 1132 DCHECK(flag == JUMP_FUNCTION || has_frame());
1317 1133
1318 // Contract with called JS functions requires that function is passed in r1. 1134 // Contract with called JS functions requires that function is passed in r4.
1319 DCHECK(function.is(r1)); 1135 DCHECK(function.is(r4));
1320 1136
1321 // Get the function and setup the context. 1137 // Get the function and setup the context.
1322 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 1138 LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
1323 1139
1324 // We call indirectly through the code field in the function to 1140 // We call indirectly through the code field in the function to
1325 // allow recompilation to take effect without changing any of the 1141 // allow recompilation to take effect without changing any of the
1326 // call sites. 1142 // call sites.
1327 ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); 1143 LoadP(r6, FieldMemOperand(r4, JSFunction::kCodeEntryOffset));
1328 InvokeCode(r3, expected, actual, flag, call_wrapper); 1144 InvokeCode(r6, expected, actual, flag, call_wrapper);
1329 } 1145 }
1330 1146
1331 1147
1332 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, 1148 void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
1333 const ParameterCount& expected, 1149 const ParameterCount& expected,
1334 const ParameterCount& actual, 1150 const ParameterCount& actual,
1335 InvokeFlag flag, 1151 InvokeFlag flag,
1336 const CallWrapper& call_wrapper) { 1152 const CallWrapper& call_wrapper) {
1337 Move(r1, function); 1153 Move(r4, function);
1338 InvokeFunction(r1, expected, actual, flag, call_wrapper); 1154 InvokeFunction(r4, expected, actual, flag, call_wrapper);
1339 } 1155 }
1340 1156
1341 1157
1342 void MacroAssembler::IsObjectJSObjectType(Register heap_object, 1158 void MacroAssembler::IsObjectJSObjectType(Register heap_object,
1343 Register map, 1159 Register map,
1344 Register scratch, 1160 Register scratch,
1345 Label* fail) { 1161 Label* fail) {
1346 ldr(map, FieldMemOperand(heap_object, HeapObject::kMapOffset)); 1162 LoadP(map, FieldMemOperand(heap_object, HeapObject::kMapOffset));
1347 IsInstanceJSObjectType(map, scratch, fail); 1163 IsInstanceJSObjectType(map, scratch, fail);
1348 } 1164 }
1349 1165
1350 1166
1351 void MacroAssembler::IsInstanceJSObjectType(Register map, 1167 void MacroAssembler::IsInstanceJSObjectType(Register map,
1352 Register scratch, 1168 Register scratch,
1353 Label* fail) { 1169 Label* fail) {
1354 ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); 1170 lbz(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
1355 cmp(scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 1171 cmpi(scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
1356 b(lt, fail); 1172 blt(fail);
1357 cmp(scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); 1173 cmpi(scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
1358 b(gt, fail); 1174 bgt(fail);
1359 } 1175 }
1360 1176
1361 1177
1362 void MacroAssembler::IsObjectJSStringType(Register object, 1178 void MacroAssembler::IsObjectJSStringType(Register object,
1363 Register scratch, 1179 Register scratch,
1364 Label* fail) { 1180 Label* fail) {
1365 DCHECK(kNotStringTag != 0); 1181 DCHECK(kNotStringTag != 0);
1366 1182
1367 ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); 1183 LoadP(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
1368 ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); 1184 lbz(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
1369 tst(scratch, Operand(kIsNotStringMask)); 1185 andi(r0, scratch, Operand(kIsNotStringMask));
1370 b(ne, fail); 1186 bne(fail, cr0);
1371 } 1187 }
1372 1188
1373 1189
1374 void MacroAssembler::IsObjectNameType(Register object, 1190 void MacroAssembler::IsObjectNameType(Register object,
1375 Register scratch, 1191 Register scratch,
1376 Label* fail) { 1192 Label* fail) {
1377 ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); 1193 LoadP(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
1378 ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); 1194 lbz(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
1379 cmp(scratch, Operand(LAST_NAME_TYPE)); 1195 cmpi(scratch, Operand(LAST_NAME_TYPE));
1380 b(hi, fail); 1196 bgt(fail);
1381 } 1197 }
1382 1198
1383 1199
1384 void MacroAssembler::DebugBreak() { 1200 void MacroAssembler::DebugBreak() {
1385 mov(r0, Operand::Zero()); 1201 li(r3, Operand::Zero());
1386 mov(r1, Operand(ExternalReference(Runtime::kDebugBreak, isolate()))); 1202 mov(r4, Operand(ExternalReference(Runtime::kDebugBreak, isolate())));
1387 CEntryStub ces(isolate(), 1); 1203 CEntryStub ces(isolate(), 1);
1388 DCHECK(AllowThisStubCall(&ces)); 1204 DCHECK(AllowThisStubCall(&ces));
1389 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); 1205 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
1390 } 1206 }
1391 1207
1392 1208
1393 void MacroAssembler::PushTryHandler(StackHandler::Kind kind, 1209 void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
1394 int handler_index) { 1210 int handler_index) {
1395 // Adjust this code if not the case. 1211 // Adjust this code if not the case.
1396 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); 1212 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
1397 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); 1213 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
1398 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); 1214 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
1399 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); 1215 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
1400 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); 1216 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
1401 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); 1217 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
1402 1218
1403 // For the JSEntry handler, we must preserve r0-r4, r5-r6 are available. 1219 // For the JSEntry handler, we must preserve r1-r7, r0,r8-r15 are available.
1404 // We will build up the handler from the bottom by pushing on the stack. 1220 // We want the stack to look like
1405 // Set up the code object (r5) and the state (r6) for pushing. 1221 // sp -> NextOffset
1222 // CodeObject
1223 // state
1224 // context
1225 // frame pointer
1226
1227 // Link the current handler as the next handler.
1228 mov(r8, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
1229 LoadP(r0, MemOperand(r8));
1230 StorePU(r0, MemOperand(sp, -StackHandlerConstants::kSize));
1231 // Set this new handler as the current one.
1232 StoreP(sp, MemOperand(r8));
1233
1234 if (kind == StackHandler::JS_ENTRY) {
1235 li(r8, Operand::Zero()); // NULL frame pointer.
1236 StoreP(r8, MemOperand(sp, StackHandlerConstants::kFPOffset));
1237 LoadSmiLiteral(r8, Smi::FromInt(0)); // Indicates no context.
1238 StoreP(r8, MemOperand(sp, StackHandlerConstants::kContextOffset));
1239 } else {
1240 // still not sure if fp is right
1241 StoreP(fp, MemOperand(sp, StackHandlerConstants::kFPOffset));
1242 StoreP(cp, MemOperand(sp, StackHandlerConstants::kContextOffset));
1243 }
1406 unsigned state = 1244 unsigned state =
1407 StackHandler::IndexField::encode(handler_index) | 1245 StackHandler::IndexField::encode(handler_index) |
1408 StackHandler::KindField::encode(kind); 1246 StackHandler::KindField::encode(kind);
1409 mov(r5, Operand(CodeObject())); 1247 LoadIntLiteral(r8, state);
1410 mov(r6, Operand(state)); 1248 StoreP(r8, MemOperand(sp, StackHandlerConstants::kStateOffset));
1411 1249 mov(r8, Operand(CodeObject()));
1412 // Push the frame pointer, context, state, and code object. 1250 StoreP(r8, MemOperand(sp, StackHandlerConstants::kCodeOffset));
1413 if (kind == StackHandler::JS_ENTRY) {
1414 mov(cp, Operand(Smi::FromInt(0))); // Indicates no context.
1415 mov(ip, Operand::Zero()); // NULL frame pointer.
1416 stm(db_w, sp, r5.bit() | r6.bit() | cp.bit() | ip.bit());
1417 } else {
1418 stm(db_w, sp, r5.bit() | r6.bit() | cp.bit() | fp.bit());
1419 }
1420
1421 // Link the current handler as the next handler.
1422 mov(r6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
1423 ldr(r5, MemOperand(r6));
1424 push(r5);
1425 // Set this new handler as the current one.
1426 str(sp, MemOperand(r6));
1427 } 1251 }
1428 1252
1429 1253
1430 void MacroAssembler::PopTryHandler() { 1254 void MacroAssembler::PopTryHandler() {
1431 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 1255 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
1432 pop(r1); 1256 pop(r4);
1433 mov(ip, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); 1257 mov(ip, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
1434 add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); 1258 addi(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
1435 str(r1, MemOperand(ip)); 1259 StoreP(r4, MemOperand(ip));
1436 } 1260 }
1437 1261
1438 1262
1263 // PPC - make use of ip as a temporary register
1439 void MacroAssembler::JumpToHandlerEntry() { 1264 void MacroAssembler::JumpToHandlerEntry() {
1440 // Compute the handler entry address and jump to it. The handler table is 1265 // Compute the handler entry address and jump to it. The handler table is
1441 // a fixed array of (smi-tagged) code offsets. 1266 // a fixed array of (smi-tagged) code offsets.
1442 // r0 = exception, r1 = code object, r2 = state. 1267 // r3 = exception, r4 = code object, r5 = state.
1443 1268 #if V8_OOL_CONSTANT_POOL
1444 ConstantPoolUnavailableScope constant_pool_unavailable(this); 1269 ConstantPoolUnavailableScope constant_pool_unavailable(this);
1445 if (FLAG_enable_ool_constant_pool) { 1270 LoadP(kConstantPoolRegister, FieldMemOperand(r4, Code::kConstantPoolOffset));
1446 ldr(pp, FieldMemOperand(r1, Code::kConstantPoolOffset)); // Constant pool. 1271 #endif
1447 } 1272 LoadP(r6, FieldMemOperand(r4, Code::kHandlerTableOffset)); // Handler table.
1448 ldr(r3, FieldMemOperand(r1, Code::kHandlerTableOffset)); // Handler table. 1273 addi(r6, r6, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
1449 add(r3, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 1274 srwi(r5, r5, Operand(StackHandler::kKindWidth)); // Handler index.
1450 mov(r2, Operand(r2, LSR, StackHandler::kKindWidth)); // Handler index. 1275 slwi(ip, r5, Operand(kPointerSizeLog2));
1451 ldr(r2, MemOperand(r3, r2, LSL, kPointerSizeLog2)); // Smi-tagged offset. 1276 add(ip, r6, ip);
1452 add(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start. 1277 LoadP(r5, MemOperand(ip)); // Smi-tagged offset.
1453 add(pc, r1, Operand::SmiUntag(r2)); // Jump 1278 addi(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start.
1279 SmiUntag(ip, r5);
1280 add(r0, r4, ip);
1281 mtctr(r0);
1282 bctr();
1454 } 1283 }
1455 1284
1456 1285
1457 void MacroAssembler::Throw(Register value) { 1286 void MacroAssembler::Throw(Register value) {
1458 // Adjust this code if not the case. 1287 // Adjust this code if not the case.
1459 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); 1288 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
1460 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 1289 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
1461 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); 1290 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
1462 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); 1291 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
1463 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); 1292 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
1464 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); 1293 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
1294 Label skip;
1465 1295
1466 // The exception is expected in r0. 1296 // The exception is expected in r3.
1467 if (!value.is(r0)) { 1297 if (!value.is(r3)) {
1468 mov(r0, value); 1298 mr(r3, value);
1469 } 1299 }
1470 // Drop the stack pointer to the top of the top handler. 1300 // Drop the stack pointer to the top of the top handler.
1471 mov(r3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); 1301 mov(r6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
1472 ldr(sp, MemOperand(r3)); 1302 LoadP(sp, MemOperand(r6));
1473 // Restore the next handler. 1303 // Restore the next handler.
1474 pop(r2); 1304 pop(r5);
1475 str(r2, MemOperand(r3)); 1305 StoreP(r5, MemOperand(r6));
1476 1306
1477 // Get the code object (r1) and state (r2). Restore the context and frame 1307 // Get the code object (r4) and state (r5). Restore the context and frame
1478 // pointer. 1308 // pointer.
1479 ldm(ia_w, sp, r1.bit() | r2.bit() | cp.bit() | fp.bit()); 1309 pop(r4);
1310 pop(r5);
1311 pop(cp);
1312 pop(fp);
1480 1313
1481 // If the handler is a JS frame, restore the context to the frame. 1314 // If the handler is a JS frame, restore the context to the frame.
1482 // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp 1315 // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
1483 // or cp. 1316 // or cp.
1484 tst(cp, cp); 1317 cmpi(cp, Operand::Zero());
1485 str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); 1318 beq(&skip);
1319 StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1320 bind(&skip);
1486 1321
1487 JumpToHandlerEntry(); 1322 JumpToHandlerEntry();
1488 } 1323 }
1489 1324
1490 1325
1491 void MacroAssembler::ThrowUncatchable(Register value) { 1326 void MacroAssembler::ThrowUncatchable(Register value) {
1492 // Adjust this code if not the case. 1327 // Adjust this code if not the case.
1493 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); 1328 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
1494 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); 1329 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
1495 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); 1330 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
1496 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); 1331 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
1497 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); 1332 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
1498 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); 1333 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
1499 1334
1500 // The exception is expected in r0. 1335 // The exception is expected in r3.
1501 if (!value.is(r0)) { 1336 if (!value.is(r3)) {
1502 mov(r0, value); 1337 mr(r3, value);
1503 } 1338 }
1504 // Drop the stack pointer to the top of the top stack handler. 1339 // Drop the stack pointer to the top of the top stack handler.
1505 mov(r3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); 1340 mov(r6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
1506 ldr(sp, MemOperand(r3)); 1341 LoadP(sp, MemOperand(r6));
1507 1342
1508 // Unwind the handlers until the ENTRY handler is found. 1343 // Unwind the handlers until the ENTRY handler is found.
1509 Label fetch_next, check_kind; 1344 Label fetch_next, check_kind;
1510 jmp(&check_kind); 1345 b(&check_kind);
1511 bind(&fetch_next); 1346 bind(&fetch_next);
1512 ldr(sp, MemOperand(sp, StackHandlerConstants::kNextOffset)); 1347 LoadP(sp, MemOperand(sp, StackHandlerConstants::kNextOffset));
1513 1348
1514 bind(&check_kind); 1349 bind(&check_kind);
1515 STATIC_ASSERT(StackHandler::JS_ENTRY == 0); 1350 STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
1516 ldr(r2, MemOperand(sp, StackHandlerConstants::kStateOffset)); 1351 LoadP(r5, MemOperand(sp, StackHandlerConstants::kStateOffset));
1517 tst(r2, Operand(StackHandler::KindField::kMask)); 1352 andi(r0, r5, Operand(StackHandler::KindField::kMask));
1518 b(ne, &fetch_next); 1353 bne(&fetch_next, cr0);
1519 1354
1520 // Set the top handler address to next handler past the top ENTRY handler. 1355 // Set the top handler address to next handler past the top ENTRY handler.
1521 pop(r2); 1356 pop(r5);
1522 str(r2, MemOperand(r3)); 1357 StoreP(r5, MemOperand(r6));
1523 // Get the code object (r1) and state (r2). Clear the context and frame 1358 // Get the code object (r4) and state (r5). Clear the context and frame
1524 // pointer (0 was saved in the handler). 1359 // pointer (0 was saved in the handler).
1525 ldm(ia_w, sp, r1.bit() | r2.bit() | cp.bit() | fp.bit()); 1360 pop(r4);
1361 pop(r5);
1362 pop(cp);
1363 pop(fp);
1526 1364
1527 JumpToHandlerEntry(); 1365 JumpToHandlerEntry();
1528 } 1366 }
1529 1367
1530 1368
1531 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, 1369 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
1532 Register scratch, 1370 Register scratch,
1533 Label* miss) { 1371 Label* miss) {
1534 Label same_contexts; 1372 Label same_contexts;
1535 1373
1536 DCHECK(!holder_reg.is(scratch)); 1374 DCHECK(!holder_reg.is(scratch));
1537 DCHECK(!holder_reg.is(ip)); 1375 DCHECK(!holder_reg.is(ip));
1538 DCHECK(!scratch.is(ip)); 1376 DCHECK(!scratch.is(ip));
1539 1377
1540 // Load current lexical context from the stack frame. 1378 // Load current lexical context from the stack frame.
1541 ldr(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1379 LoadP(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset));
1542 // In debug mode, make sure the lexical context is set. 1380 // In debug mode, make sure the lexical context is set.
1543 #ifdef DEBUG 1381 #ifdef DEBUG
1544 cmp(scratch, Operand::Zero()); 1382 cmpi(scratch, Operand::Zero());
1545 Check(ne, kWeShouldNotHaveAnEmptyLexicalContext); 1383 Check(ne, kWeShouldNotHaveAnEmptyLexicalContext);
1546 #endif 1384 #endif
1547 1385
1548 // Load the native context of the current context. 1386 // Load the native context of the current context.
1549 int offset = 1387 int offset =
1550 Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize; 1388 Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
1551 ldr(scratch, FieldMemOperand(scratch, offset)); 1389 LoadP(scratch, FieldMemOperand(scratch, offset));
1552 ldr(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); 1390 LoadP(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset));
1553 1391
1554 // Check the context is a native context. 1392 // Check the context is a native context.
1555 if (emit_debug_code()) { 1393 if (emit_debug_code()) {
1556 // Cannot use ip as a temporary in this verification code. Due to the fact 1394 // Cannot use ip as a temporary in this verification code. Due to the fact
1557 // that ip is clobbered as part of cmp with an object Operand. 1395 // that ip is clobbered as part of cmp with an object Operand.
1558 push(holder_reg); // Temporarily save holder on the stack. 1396 push(holder_reg); // Temporarily save holder on the stack.
1559 // Read the first word and compare to the native_context_map. 1397 // Read the first word and compare to the native_context_map.
1560 ldr(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset)); 1398 LoadP(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
1561 LoadRoot(ip, Heap::kNativeContextMapRootIndex); 1399 LoadRoot(ip, Heap::kNativeContextMapRootIndex);
1562 cmp(holder_reg, ip); 1400 cmp(holder_reg, ip);
1563 Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext); 1401 Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext);
1564 pop(holder_reg); // Restore holder. 1402 pop(holder_reg); // Restore holder.
1565 } 1403 }
1566 1404
1567 // Check if both contexts are the same. 1405 // Check if both contexts are the same.
1568 ldr(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); 1406 LoadP(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
1569 cmp(scratch, Operand(ip)); 1407 cmp(scratch, ip);
1570 b(eq, &same_contexts); 1408 beq(&same_contexts);
1571 1409
1572 // Check the context is a native context. 1410 // Check the context is a native context.
1573 if (emit_debug_code()) { 1411 if (emit_debug_code()) {
1574 // Cannot use ip as a temporary in this verification code. Due to the fact 1412 // Cannot use ip as a temporary in this verification code. Due to the fact
1575 // that ip is clobbered as part of cmp with an object Operand. 1413 // that ip is clobbered as part of cmp with an object Operand.
1576 push(holder_reg); // Temporarily save holder on the stack. 1414 push(holder_reg); // Temporarily save holder on the stack.
1577 mov(holder_reg, ip); // Move ip to its holding place. 1415 mr(holder_reg, ip); // Move ip to its holding place.
1578 LoadRoot(ip, Heap::kNullValueRootIndex); 1416 LoadRoot(ip, Heap::kNullValueRootIndex);
1579 cmp(holder_reg, ip); 1417 cmp(holder_reg, ip);
1580 Check(ne, kJSGlobalProxyContextShouldNotBeNull); 1418 Check(ne, kJSGlobalProxyContextShouldNotBeNull);
1581 1419
1582 ldr(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset)); 1420 LoadP(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
1583 LoadRoot(ip, Heap::kNativeContextMapRootIndex); 1421 LoadRoot(ip, Heap::kNativeContextMapRootIndex);
1584 cmp(holder_reg, ip); 1422 cmp(holder_reg, ip);
1585 Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext); 1423 Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext);
1586 // Restore ip is not needed. ip is reloaded below. 1424 // Restore ip is not needed. ip is reloaded below.
1587 pop(holder_reg); // Restore holder. 1425 pop(holder_reg); // Restore holder.
1588 // Restore ip to holder's context. 1426 // Restore ip to holder's context.
1589 ldr(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); 1427 LoadP(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
1590 } 1428 }
1591 1429
1592 // Check that the security token in the calling global object is 1430 // Check that the security token in the calling global object is
1593 // compatible with the security token in the receiving global 1431 // compatible with the security token in the receiving global
1594 // object. 1432 // object.
1595 int token_offset = Context::kHeaderSize + 1433 int token_offset = Context::kHeaderSize +
1596 Context::SECURITY_TOKEN_INDEX * kPointerSize; 1434 Context::SECURITY_TOKEN_INDEX * kPointerSize;
1597 1435
1598 ldr(scratch, FieldMemOperand(scratch, token_offset)); 1436 LoadP(scratch, FieldMemOperand(scratch, token_offset));
1599 ldr(ip, FieldMemOperand(ip, token_offset)); 1437 LoadP(ip, FieldMemOperand(ip, token_offset));
1600 cmp(scratch, Operand(ip)); 1438 cmp(scratch, ip);
1601 b(ne, miss); 1439 bne(miss);
1602 1440
1603 bind(&same_contexts); 1441 bind(&same_contexts);
1604 } 1442 }
1605 1443
1606 1444
1607 // Compute the hash code from the untagged key. This must be kept in sync with 1445 // Compute the hash code from the untagged key. This must be kept in sync with
1608 // ComputeIntegerHash in utils.h and KeyedLoadGenericStub in 1446 // ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
1609 // code-stub-hydrogen.cc 1447 // code-stub-hydrogen.cc
1610 void MacroAssembler::GetNumberHash(Register t0, Register scratch) { 1448 void MacroAssembler::GetNumberHash(Register t0, Register scratch) {
1611 // First of all we assign the hash seed to scratch. 1449 // First of all we assign the hash seed to scratch.
1612 LoadRoot(scratch, Heap::kHashSeedRootIndex); 1450 LoadRoot(scratch, Heap::kHashSeedRootIndex);
1613 SmiUntag(scratch); 1451 SmiUntag(scratch);
1614 1452
1615 // Xor original key with a seed. 1453 // Xor original key with a seed.
1616 eor(t0, t0, Operand(scratch)); 1454 xor_(t0, t0, scratch);
1617 1455
1618 // Compute the hash code from the untagged key. This must be kept in sync 1456 // Compute the hash code from the untagged key. This must be kept in sync
1619 // with ComputeIntegerHash in utils.h. 1457 // with ComputeIntegerHash in utils.h.
1620 // 1458 //
1621 // hash = ~hash + (hash << 15); 1459 // hash = ~hash + (hash << 15);
1622 mvn(scratch, Operand(t0)); 1460 notx(scratch, t0);
1623 add(t0, scratch, Operand(t0, LSL, 15)); 1461 slwi(t0, t0, Operand(15));
1462 add(t0, scratch, t0);
1624 // hash = hash ^ (hash >> 12); 1463 // hash = hash ^ (hash >> 12);
1625 eor(t0, t0, Operand(t0, LSR, 12)); 1464 srwi(scratch, t0, Operand(12));
1465 xor_(t0, t0, scratch);
1626 // hash = hash + (hash << 2); 1466 // hash = hash + (hash << 2);
1627 add(t0, t0, Operand(t0, LSL, 2)); 1467 slwi(scratch, t0, Operand(2));
1468 add(t0, t0, scratch);
1628 // hash = hash ^ (hash >> 4); 1469 // hash = hash ^ (hash >> 4);
1629 eor(t0, t0, Operand(t0, LSR, 4)); 1470 srwi(scratch, t0, Operand(4));
1471 xor_(t0, t0, scratch);
1630 // hash = hash * 2057; 1472 // hash = hash * 2057;
1631 mov(scratch, Operand(t0, LSL, 11)); 1473 mr(r0, t0);
1632 add(t0, t0, Operand(t0, LSL, 3)); 1474 slwi(scratch, t0, Operand(3));
1475 add(t0, t0, scratch);
1476 slwi(scratch, r0, Operand(11));
1633 add(t0, t0, scratch); 1477 add(t0, t0, scratch);
1634 // hash = hash ^ (hash >> 16); 1478 // hash = hash ^ (hash >> 16);
1635 eor(t0, t0, Operand(t0, LSR, 16)); 1479 srwi(scratch, t0, Operand(16));
1480 xor_(t0, t0, scratch);
1636 } 1481 }
1637 1482
1638 1483
1639 void MacroAssembler::LoadFromNumberDictionary(Label* miss, 1484 void MacroAssembler::LoadFromNumberDictionary(Label* miss,
1640 Register elements, 1485 Register elements,
1641 Register key, 1486 Register key,
1642 Register result, 1487 Register result,
1643 Register t0, 1488 Register t0,
1644 Register t1, 1489 Register t1,
1645 Register t2) { 1490 Register t2) {
(...skipping 15 matching lines...) Expand all
1661 // t0 - holds the untagged key on entry and holds the hash once computed. 1506 // t0 - holds the untagged key on entry and holds the hash once computed.
1662 // 1507 //
1663 // t1 - used to hold the capacity mask of the dictionary 1508 // t1 - used to hold the capacity mask of the dictionary
1664 // 1509 //
1665 // t2 - used for the index into the dictionary. 1510 // t2 - used for the index into the dictionary.
1666 Label done; 1511 Label done;
1667 1512
1668 GetNumberHash(t0, t1); 1513 GetNumberHash(t0, t1);
1669 1514
1670 // Compute the capacity mask. 1515 // Compute the capacity mask.
1671 ldr(t1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset)); 1516 LoadP(t1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset));
1672 SmiUntag(t1); 1517 SmiUntag(t1);
1673 sub(t1, t1, Operand(1)); 1518 subi(t1, t1, Operand(1));
1674 1519
1675 // Generate an unrolled loop that performs a few probes before giving up. 1520 // Generate an unrolled loop that performs a few probes before giving up.
1676 for (int i = 0; i < kNumberDictionaryProbes; i++) { 1521 for (int i = 0; i < kNumberDictionaryProbes; i++) {
1677 // Use t2 for index calculations and keep the hash intact in t0. 1522 // Use t2 for index calculations and keep the hash intact in t0.
1678 mov(t2, t0); 1523 mr(t2, t0);
1679 // Compute the masked index: (hash + i + i * i) & mask. 1524 // Compute the masked index: (hash + i + i * i) & mask.
1680 if (i > 0) { 1525 if (i > 0) {
1681 add(t2, t2, Operand(SeededNumberDictionary::GetProbeOffset(i))); 1526 addi(t2, t2, Operand(SeededNumberDictionary::GetProbeOffset(i)));
1682 } 1527 }
1683 and_(t2, t2, Operand(t1)); 1528 and_(t2, t2, t1);
1684 1529
1685 // Scale the index by multiplying by the element size. 1530 // Scale the index by multiplying by the element size.
1686 DCHECK(SeededNumberDictionary::kEntrySize == 3); 1531 DCHECK(SeededNumberDictionary::kEntrySize == 3);
1687 add(t2, t2, Operand(t2, LSL, 1)); // t2 = t2 * 3 1532 slwi(ip, t2, Operand(1));
1533 add(t2, t2, ip); // t2 = t2 * 3
1688 1534
1689 // Check if the key is identical to the name. 1535 // Check if the key is identical to the name.
1690 add(t2, elements, Operand(t2, LSL, kPointerSizeLog2)); 1536 slwi(t2, t2, Operand(kPointerSizeLog2));
1691 ldr(ip, FieldMemOperand(t2, SeededNumberDictionary::kElementsStartOffset)); 1537 add(t2, elements, t2);
1692 cmp(key, Operand(ip)); 1538 LoadP(ip,
1539 FieldMemOperand(t2, SeededNumberDictionary::kElementsStartOffset));
1540 cmp(key, ip);
1693 if (i != kNumberDictionaryProbes - 1) { 1541 if (i != kNumberDictionaryProbes - 1) {
1694 b(eq, &done); 1542 beq(&done);
1695 } else { 1543 } else {
1696 b(ne, miss); 1544 bne(miss);
1697 } 1545 }
1698 } 1546 }
1699 1547
1700 bind(&done); 1548 bind(&done);
1701 // Check that the value is a normal property. 1549 // Check that the value is a normal property.
1702 // t2: elements + (index * kPointerSize) 1550 // t2: elements + (index * kPointerSize)
1703 const int kDetailsOffset = 1551 const int kDetailsOffset =
1704 SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; 1552 SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
1705 ldr(t1, FieldMemOperand(t2, kDetailsOffset)); 1553 LoadP(t1, FieldMemOperand(t2, kDetailsOffset));
1706 tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask))); 1554 LoadSmiLiteral(ip, Smi::FromInt(PropertyDetails::TypeField::kMask));
1707 b(ne, miss); 1555 and_(r0, t1, ip, SetRC);
1556 bne(miss, cr0);
1708 1557
1709 // Get the value at the masked, scaled index and return. 1558 // Get the value at the masked, scaled index and return.
1710 const int kValueOffset = 1559 const int kValueOffset =
1711 SeededNumberDictionary::kElementsStartOffset + kPointerSize; 1560 SeededNumberDictionary::kElementsStartOffset + kPointerSize;
1712 ldr(result, FieldMemOperand(t2, kValueOffset)); 1561 LoadP(result, FieldMemOperand(t2, kValueOffset));
1713 } 1562 }
1714 1563
1715 1564
1716 void MacroAssembler::Allocate(int object_size, 1565 void MacroAssembler::Allocate(int object_size,
1717 Register result, 1566 Register result,
1718 Register scratch1, 1567 Register scratch1,
1719 Register scratch2, 1568 Register scratch2,
1720 Label* gc_required, 1569 Label* gc_required,
1721 AllocationFlags flags) { 1570 AllocationFlags flags) {
1722 DCHECK(object_size <= Page::kMaxRegularHeapObjectSize); 1571 DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
1723 if (!FLAG_inline_new) { 1572 if (!FLAG_inline_new) {
1724 if (emit_debug_code()) { 1573 if (emit_debug_code()) {
1725 // Trash the registers to simulate an allocation failure. 1574 // Trash the registers to simulate an allocation failure.
1726 mov(result, Operand(0x7091)); 1575 li(result, Operand(0x7091));
1727 mov(scratch1, Operand(0x7191)); 1576 li(scratch1, Operand(0x7191));
1728 mov(scratch2, Operand(0x7291)); 1577 li(scratch2, Operand(0x7291));
1729 } 1578 }
1730 jmp(gc_required); 1579 b(gc_required);
1731 return; 1580 return;
1732 } 1581 }
1733 1582
1734 DCHECK(!result.is(scratch1)); 1583 DCHECK(!result.is(scratch1));
1735 DCHECK(!result.is(scratch2)); 1584 DCHECK(!result.is(scratch2));
1736 DCHECK(!scratch1.is(scratch2)); 1585 DCHECK(!scratch1.is(scratch2));
1737 DCHECK(!scratch1.is(ip)); 1586 DCHECK(!scratch1.is(ip));
1738 DCHECK(!scratch2.is(ip)); 1587 DCHECK(!scratch2.is(ip));
1739 1588
1740 // Make object size into bytes. 1589 // Make object size into bytes.
1741 if ((flags & SIZE_IN_WORDS) != 0) { 1590 if ((flags & SIZE_IN_WORDS) != 0) {
1742 object_size *= kPointerSize; 1591 object_size *= kPointerSize;
1743 } 1592 }
1744 DCHECK_EQ(0, object_size & kObjectAlignmentMask); 1593 DCHECK_EQ(0, static_cast<int>(object_size & kObjectAlignmentMask));
1745 1594
1746 // Check relative positions of allocation top and limit addresses. 1595 // Check relative positions of allocation top and limit addresses.
1747 // The values must be adjacent in memory to allow the use of LDM.
1748 // Also, assert that the registers are numbered such that the values
1749 // are loaded in the correct order.
1750 ExternalReference allocation_top = 1596 ExternalReference allocation_top =
1751 AllocationUtils::GetAllocationTopReference(isolate(), flags); 1597 AllocationUtils::GetAllocationTopReference(isolate(), flags);
1752 ExternalReference allocation_limit = 1598 ExternalReference allocation_limit =
1753 AllocationUtils::GetAllocationLimitReference(isolate(), flags); 1599 AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1754 1600
1755 intptr_t top = 1601 intptr_t top =
1756 reinterpret_cast<intptr_t>(allocation_top.address()); 1602 reinterpret_cast<intptr_t>(allocation_top.address());
1757 intptr_t limit = 1603 intptr_t limit =
1758 reinterpret_cast<intptr_t>(allocation_limit.address()); 1604 reinterpret_cast<intptr_t>(allocation_limit.address());
1759 DCHECK((limit - top) == kPointerSize); 1605 DCHECK((limit - top) == kPointerSize);
1760 DCHECK(result.code() < ip.code());
1761 1606
1762 // Set up allocation top address register. 1607 // Set up allocation top address register.
1763 Register topaddr = scratch1; 1608 Register topaddr = scratch1;
1764 mov(topaddr, Operand(allocation_top)); 1609 mov(topaddr, Operand(allocation_top));
1765 1610
1766 // This code stores a temporary value in ip. This is OK, as the code below 1611 // This code stores a temporary value in ip. This is OK, as the code below
1767 // does not need ip for implicit literal generation. 1612 // does not need ip for implicit literal generation.
1768 if ((flags & RESULT_CONTAINS_TOP) == 0) { 1613 if ((flags & RESULT_CONTAINS_TOP) == 0) {
1769 // Load allocation top into result and allocation limit into ip. 1614 // Load allocation top into result and allocation limit into ip.
1770 ldm(ia, topaddr, result.bit() | ip.bit()); 1615 LoadP(result, MemOperand(topaddr));
1616 LoadP(ip, MemOperand(topaddr, kPointerSize));
1771 } else { 1617 } else {
1772 if (emit_debug_code()) { 1618 if (emit_debug_code()) {
1773 // Assert that result actually contains top on entry. ip is used 1619 // Assert that result actually contains top on entry. ip is used
1774 // immediately below so this use of ip does not cause difference with 1620 // immediately below so this use of ip does not cause difference with
1775 // respect to register content between debug and release mode. 1621 // respect to register content between debug and release mode.
1776 ldr(ip, MemOperand(topaddr)); 1622 LoadP(ip, MemOperand(topaddr));
1777 cmp(result, ip); 1623 cmp(result, ip);
1778 Check(eq, kUnexpectedAllocationTop); 1624 Check(eq, kUnexpectedAllocationTop);
1779 } 1625 }
1780 // Load allocation limit into ip. Result already contains allocation top. 1626 // Load allocation limit into ip. Result already contains allocation top.
1781 ldr(ip, MemOperand(topaddr, limit - top)); 1627 LoadP(ip, MemOperand(topaddr, limit - top), r0);
1782 } 1628 }
1783 1629
1784 if ((flags & DOUBLE_ALIGNMENT) != 0) { 1630 if ((flags & DOUBLE_ALIGNMENT) != 0) {
1785 // Align the next allocation. Storing the filler map without checking top is 1631 // Align the next allocation. Storing the filler map without checking top is
1786 // safe in new-space because the limit of the heap is aligned there. 1632 // safe in new-space because the limit of the heap is aligned there.
1787 DCHECK((flags & PRETENURE_OLD_POINTER_SPACE) == 0); 1633 DCHECK((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
1634 #if V8_TARGET_ARCH_PPC64
1635 STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
1636 #else
1788 STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment); 1637 STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
1789 and_(scratch2, result, Operand(kDoubleAlignmentMask), SetCC); 1638 andi(scratch2, result, Operand(kDoubleAlignmentMask));
1790 Label aligned; 1639 Label aligned;
1791 b(eq, &aligned); 1640 beq(&aligned, cr0);
1792 if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { 1641 if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
1793 cmp(result, Operand(ip)); 1642 cmpl(result, ip);
1794 b(hs, gc_required); 1643 bge(gc_required);
1795 } 1644 }
1796 mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); 1645 mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map()));
1797 str(scratch2, MemOperand(result, kDoubleSize / 2, PostIndex)); 1646 stw(scratch2, MemOperand(result));
1647 addi(result, result, Operand(kDoubleSize / 2));
1798 bind(&aligned); 1648 bind(&aligned);
1649 #endif
1799 } 1650 }
1800 1651
1801 // Calculate new top and bail out if new space is exhausted. Use result 1652 // Calculate new top and bail out if new space is exhausted. Use result
1802 // to calculate the new top. We must preserve the ip register at this 1653 // to calculate the new top.
1803 // point, so we cannot just use add(). 1654 li(r0, Operand(-1));
1804 DCHECK(object_size > 0); 1655 if (is_int16(object_size)) {
1805 Register source = result; 1656 addic(scratch2, result, Operand(object_size));
1806 Condition cond = al; 1657 } else {
1807 int shift = 0; 1658 mov(scratch2, Operand(object_size));
1808 while (object_size != 0) { 1659 addc(scratch2, result, scratch2);
1809 if (((object_size >> shift) & 0x03) == 0) {
1810 shift += 2;
1811 } else {
1812 int bits = object_size & (0xff << shift);
1813 object_size -= bits;
1814 shift += 8;
1815 Operand bits_operand(bits);
1816 DCHECK(bits_operand.instructions_required(this) == 1);
1817 add(scratch2, source, bits_operand, SetCC, cond);
1818 source = scratch2;
1819 cond = cc;
1820 }
1821 } 1660 }
1822 b(cs, gc_required); 1661 addze(r0, r0, LeaveOE, SetRC);
1823 cmp(scratch2, Operand(ip)); 1662 beq(gc_required, cr0);
1824 b(hi, gc_required); 1663 cmpl(scratch2, ip);
1825 str(scratch2, MemOperand(topaddr)); 1664 bgt(gc_required);
1665 StoreP(scratch2, MemOperand(topaddr));
1826 1666
1827 // Tag object if requested. 1667 // Tag object if requested.
1828 if ((flags & TAG_OBJECT) != 0) { 1668 if ((flags & TAG_OBJECT) != 0) {
1829 add(result, result, Operand(kHeapObjectTag)); 1669 addi(result, result, Operand(kHeapObjectTag));
1830 } 1670 }
1831 } 1671 }
1832 1672
1833 1673
1834 void MacroAssembler::Allocate(Register object_size, 1674 void MacroAssembler::Allocate(Register object_size,
1835 Register result, 1675 Register result,
1836 Register scratch1, 1676 Register scratch1,
1837 Register scratch2, 1677 Register scratch2,
1838 Label* gc_required, 1678 Label* gc_required,
1839 AllocationFlags flags) { 1679 AllocationFlags flags) {
1840 if (!FLAG_inline_new) { 1680 if (!FLAG_inline_new) {
1841 if (emit_debug_code()) { 1681 if (emit_debug_code()) {
1842 // Trash the registers to simulate an allocation failure. 1682 // Trash the registers to simulate an allocation failure.
1843 mov(result, Operand(0x7091)); 1683 li(result, Operand(0x7091));
1844 mov(scratch1, Operand(0x7191)); 1684 li(scratch1, Operand(0x7191));
1845 mov(scratch2, Operand(0x7291)); 1685 li(scratch2, Operand(0x7291));
1846 } 1686 }
1847 jmp(gc_required); 1687 b(gc_required);
1848 return; 1688 return;
1849 } 1689 }
1850 1690
1851 // Assert that the register arguments are different and that none of 1691 // Assert that the register arguments are different and that none of
1852 // them are ip. ip is used explicitly in the code generated below. 1692 // them are ip. ip is used explicitly in the code generated below.
1853 DCHECK(!result.is(scratch1)); 1693 DCHECK(!result.is(scratch1));
1854 DCHECK(!result.is(scratch2)); 1694 DCHECK(!result.is(scratch2));
1855 DCHECK(!scratch1.is(scratch2)); 1695 DCHECK(!scratch1.is(scratch2));
1856 DCHECK(!object_size.is(ip)); 1696 DCHECK(!object_size.is(ip));
1857 DCHECK(!result.is(ip)); 1697 DCHECK(!result.is(ip));
1858 DCHECK(!scratch1.is(ip)); 1698 DCHECK(!scratch1.is(ip));
1859 DCHECK(!scratch2.is(ip)); 1699 DCHECK(!scratch2.is(ip));
1860 1700
1861 // Check relative positions of allocation top and limit addresses. 1701 // Check relative positions of allocation top and limit addresses.
1862 // The values must be adjacent in memory to allow the use of LDM.
1863 // Also, assert that the registers are numbered such that the values
1864 // are loaded in the correct order.
1865 ExternalReference allocation_top = 1702 ExternalReference allocation_top =
1866 AllocationUtils::GetAllocationTopReference(isolate(), flags); 1703 AllocationUtils::GetAllocationTopReference(isolate(), flags);
1867 ExternalReference allocation_limit = 1704 ExternalReference allocation_limit =
1868 AllocationUtils::GetAllocationLimitReference(isolate(), flags); 1705 AllocationUtils::GetAllocationLimitReference(isolate(), flags);
1869 intptr_t top = 1706 intptr_t top =
1870 reinterpret_cast<intptr_t>(allocation_top.address()); 1707 reinterpret_cast<intptr_t>(allocation_top.address());
1871 intptr_t limit = 1708 intptr_t limit =
1872 reinterpret_cast<intptr_t>(allocation_limit.address()); 1709 reinterpret_cast<intptr_t>(allocation_limit.address());
1873 DCHECK((limit - top) == kPointerSize); 1710 DCHECK((limit - top) == kPointerSize);
1874 DCHECK(result.code() < ip.code());
1875 1711
1876 // Set up allocation top address. 1712 // Set up allocation top address.
1877 Register topaddr = scratch1; 1713 Register topaddr = scratch1;
1878 mov(topaddr, Operand(allocation_top)); 1714 mov(topaddr, Operand(allocation_top));
1879 1715
1880 // This code stores a temporary value in ip. This is OK, as the code below 1716 // This code stores a temporary value in ip. This is OK, as the code below
1881 // does not need ip for implicit literal generation. 1717 // does not need ip for implicit literal generation.
1882 if ((flags & RESULT_CONTAINS_TOP) == 0) { 1718 if ((flags & RESULT_CONTAINS_TOP) == 0) {
1883 // Load allocation top into result and allocation limit into ip. 1719 // Load allocation top into result and allocation limit into ip.
1884 ldm(ia, topaddr, result.bit() | ip.bit()); 1720 LoadP(result, MemOperand(topaddr));
1721 LoadP(ip, MemOperand(topaddr, kPointerSize));
1885 } else { 1722 } else {
1886 if (emit_debug_code()) { 1723 if (emit_debug_code()) {
1887 // Assert that result actually contains top on entry. ip is used 1724 // Assert that result actually contains top on entry. ip is used
1888 // immediately below so this use of ip does not cause difference with 1725 // immediately below so this use of ip does not cause difference with
1889 // respect to register content between debug and release mode. 1726 // respect to register content between debug and release mode.
1890 ldr(ip, MemOperand(topaddr)); 1727 LoadP(ip, MemOperand(topaddr));
1891 cmp(result, ip); 1728 cmp(result, ip);
1892 Check(eq, kUnexpectedAllocationTop); 1729 Check(eq, kUnexpectedAllocationTop);
1893 } 1730 }
1894 // Load allocation limit into ip. Result already contains allocation top. 1731 // Load allocation limit into ip. Result already contains allocation top.
1895 ldr(ip, MemOperand(topaddr, limit - top)); 1732 LoadP(ip, MemOperand(topaddr, limit - top));
1896 } 1733 }
1897 1734
1898 if ((flags & DOUBLE_ALIGNMENT) != 0) { 1735 if ((flags & DOUBLE_ALIGNMENT) != 0) {
1899 // Align the next allocation. Storing the filler map without checking top is 1736 // Align the next allocation. Storing the filler map without checking top is
1900 // safe in new-space because the limit of the heap is aligned there. 1737 // safe in new-space because the limit of the heap is aligned there.
1901 DCHECK((flags & PRETENURE_OLD_POINTER_SPACE) == 0); 1738 DCHECK((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
1902 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); 1739 #if V8_TARGET_ARCH_PPC64
1903 and_(scratch2, result, Operand(kDoubleAlignmentMask), SetCC); 1740 STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
1741 #else
1742 STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
1743 andi(scratch2, result, Operand(kDoubleAlignmentMask));
1904 Label aligned; 1744 Label aligned;
1905 b(eq, &aligned); 1745 beq(&aligned, cr0);
1906 if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { 1746 if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
1907 cmp(result, Operand(ip)); 1747 cmpl(result, ip);
1908 b(hs, gc_required); 1748 bge(gc_required);
1909 } 1749 }
1910 mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); 1750 mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map()));
1911 str(scratch2, MemOperand(result, kDoubleSize / 2, PostIndex)); 1751 stw(scratch2, MemOperand(result));
1752 addi(result, result, Operand(kDoubleSize / 2));
1912 bind(&aligned); 1753 bind(&aligned);
1754 #endif
1913 } 1755 }
1914 1756
1915 // Calculate new top and bail out if new space is exhausted. Use result 1757 // Calculate new top and bail out if new space is exhausted. Use result
1916 // to calculate the new top. Object size may be in words so a shift is 1758 // to calculate the new top. Object size may be in words so a shift is
1917 // required to get the number of bytes. 1759 // required to get the number of bytes.
1760 li(r0, Operand(-1));
1918 if ((flags & SIZE_IN_WORDS) != 0) { 1761 if ((flags & SIZE_IN_WORDS) != 0) {
1919 add(scratch2, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC); 1762 ShiftLeftImm(scratch2, object_size, Operand(kPointerSizeLog2));
1763 addc(scratch2, result, scratch2);
1920 } else { 1764 } else {
1921 add(scratch2, result, Operand(object_size), SetCC); 1765 addc(scratch2, result, object_size);
1922 } 1766 }
1923 b(cs, gc_required); 1767 addze(r0, r0, LeaveOE, SetRC);
1924 cmp(scratch2, Operand(ip)); 1768 beq(gc_required, cr0);
1925 b(hi, gc_required); 1769 cmpl(scratch2, ip);
1770 bgt(gc_required);
1926 1771
1927 // Update allocation top. result temporarily holds the new top. 1772 // Update allocation top. result temporarily holds the new top.
1928 if (emit_debug_code()) { 1773 if (emit_debug_code()) {
1929 tst(scratch2, Operand(kObjectAlignmentMask)); 1774 andi(r0, scratch2, Operand(kObjectAlignmentMask));
1930 Check(eq, kUnalignedAllocationInNewSpace); 1775 Check(eq, kUnalignedAllocationInNewSpace, cr0);
1931 } 1776 }
1932 str(scratch2, MemOperand(topaddr)); 1777 StoreP(scratch2, MemOperand(topaddr));
1933 1778
1934 // Tag object if requested. 1779 // Tag object if requested.
1935 if ((flags & TAG_OBJECT) != 0) { 1780 if ((flags & TAG_OBJECT) != 0) {
1936 add(result, result, Operand(kHeapObjectTag)); 1781 addi(result, result, Operand(kHeapObjectTag));
1937 } 1782 }
1938 } 1783 }
1939 1784
1940 1785
1941 void MacroAssembler::UndoAllocationInNewSpace(Register object, 1786 void MacroAssembler::UndoAllocationInNewSpace(Register object,
1942 Register scratch) { 1787 Register scratch) {
1943 ExternalReference new_space_allocation_top = 1788 ExternalReference new_space_allocation_top =
1944 ExternalReference::new_space_allocation_top_address(isolate()); 1789 ExternalReference::new_space_allocation_top_address(isolate());
1945 1790
1946 // Make sure the object has no tag before resetting top. 1791 // Make sure the object has no tag before resetting top.
1947 and_(object, object, Operand(~kHeapObjectTagMask)); 1792 mov(r0, Operand(~kHeapObjectTagMask));
1793 and_(object, object, r0);
1794 // was.. and_(object, object, Operand(~kHeapObjectTagMask));
1948 #ifdef DEBUG 1795 #ifdef DEBUG
1949 // Check that the object un-allocated is below the current top. 1796 // Check that the object un-allocated is below the current top.
1950 mov(scratch, Operand(new_space_allocation_top)); 1797 mov(scratch, Operand(new_space_allocation_top));
1951 ldr(scratch, MemOperand(scratch)); 1798 LoadP(scratch, MemOperand(scratch));
1952 cmp(object, scratch); 1799 cmp(object, scratch);
1953 Check(lt, kUndoAllocationOfNonAllocatedMemory); 1800 Check(lt, kUndoAllocationOfNonAllocatedMemory);
1954 #endif 1801 #endif
1955 // Write the address of the object to un-allocate as the current top. 1802 // Write the address of the object to un-allocate as the current top.
1956 mov(scratch, Operand(new_space_allocation_top)); 1803 mov(scratch, Operand(new_space_allocation_top));
1957 str(object, MemOperand(scratch)); 1804 StoreP(object, MemOperand(scratch));
1958 } 1805 }
1959 1806
1960 1807
1961 void MacroAssembler::AllocateTwoByteString(Register result, 1808 void MacroAssembler::AllocateTwoByteString(Register result,
1962 Register length, 1809 Register length,
1963 Register scratch1, 1810 Register scratch1,
1964 Register scratch2, 1811 Register scratch2,
1965 Register scratch3, 1812 Register scratch3,
1966 Label* gc_required) { 1813 Label* gc_required) {
1967 // Calculate the number of bytes needed for the characters in the string while 1814 // Calculate the number of bytes needed for the characters in the string while
1968 // observing object alignment. 1815 // observing object alignment.
1969 DCHECK((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); 1816 DCHECK((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
1970 mov(scratch1, Operand(length, LSL, 1)); // Length in bytes, not chars. 1817 slwi(scratch1, length, Operand(1)); // Length in bytes, not chars.
1971 add(scratch1, scratch1, 1818 addi(scratch1, scratch1,
1972 Operand(kObjectAlignmentMask + SeqTwoByteString::kHeaderSize)); 1819 Operand(kObjectAlignmentMask + SeqTwoByteString::kHeaderSize));
1973 and_(scratch1, scratch1, Operand(~kObjectAlignmentMask)); 1820 mov(r0, Operand(~kObjectAlignmentMask));
1821 and_(scratch1, scratch1, r0);
1974 1822
1975 // Allocate two-byte string in new space. 1823 // Allocate two-byte string in new space.
1976 Allocate(scratch1, 1824 Allocate(scratch1,
1977 result, 1825 result,
1978 scratch2, 1826 scratch2,
1979 scratch3, 1827 scratch3,
1980 gc_required, 1828 gc_required,
1981 TAG_OBJECT); 1829 TAG_OBJECT);
1982 1830
1983 // Set the map, length and hash field. 1831 // Set the map, length and hash field.
1984 InitializeNewString(result, 1832 InitializeNewString(result,
1985 length, 1833 length,
1986 Heap::kStringMapRootIndex, 1834 Heap::kStringMapRootIndex,
1987 scratch1, 1835 scratch1,
1988 scratch2); 1836 scratch2);
1989 } 1837 }
1990 1838
1991 1839
1992 void MacroAssembler::AllocateAsciiString(Register result, 1840 void MacroAssembler::AllocateAsciiString(Register result,
1993 Register length, 1841 Register length,
1994 Register scratch1, 1842 Register scratch1,
1995 Register scratch2, 1843 Register scratch2,
1996 Register scratch3, 1844 Register scratch3,
1997 Label* gc_required) { 1845 Label* gc_required) {
1998 // Calculate the number of bytes needed for the characters in the string while 1846 // Calculate the number of bytes needed for the characters in the string while
1999 // observing object alignment. 1847 // observing object alignment.
2000 DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); 1848 DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
2001 DCHECK(kCharSize == 1); 1849 DCHECK(kCharSize == 1);
2002 add(scratch1, length, 1850 addi(scratch1, length,
2003 Operand(kObjectAlignmentMask + SeqOneByteString::kHeaderSize)); 1851 Operand(kObjectAlignmentMask + SeqOneByteString::kHeaderSize));
2004 and_(scratch1, scratch1, Operand(~kObjectAlignmentMask)); 1852 li(r0, Operand(~kObjectAlignmentMask));
1853 and_(scratch1, scratch1, r0);
2005 1854
2006 // Allocate ASCII string in new space. 1855 // Allocate ASCII string in new space.
2007 Allocate(scratch1, 1856 Allocate(scratch1,
2008 result, 1857 result,
2009 scratch2, 1858 scratch2,
2010 scratch3, 1859 scratch3,
2011 gc_required, 1860 gc_required,
2012 TAG_OBJECT); 1861 TAG_OBJECT);
2013 1862
2014 // Set the map, length and hash field. 1863 // Set the map, length and hash field.
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
2087 scratch2); 1936 scratch2);
2088 } 1937 }
2089 1938
2090 1939
2091 void MacroAssembler::CompareObjectType(Register object, 1940 void MacroAssembler::CompareObjectType(Register object,
2092 Register map, 1941 Register map,
2093 Register type_reg, 1942 Register type_reg,
2094 InstanceType type) { 1943 InstanceType type) {
2095 const Register temp = type_reg.is(no_reg) ? ip : type_reg; 1944 const Register temp = type_reg.is(no_reg) ? ip : type_reg;
2096 1945
2097 ldr(map, FieldMemOperand(object, HeapObject::kMapOffset)); 1946 LoadP(map, FieldMemOperand(object, HeapObject::kMapOffset));
2098 CompareInstanceType(map, temp, type); 1947 CompareInstanceType(map, temp, type);
2099 } 1948 }
2100 1949
2101 1950
2102 void MacroAssembler::CheckObjectTypeRange(Register object, 1951 void MacroAssembler::CheckObjectTypeRange(Register object,
2103 Register map, 1952 Register map,
2104 InstanceType min_type, 1953 InstanceType min_type,
2105 InstanceType max_type, 1954 InstanceType max_type,
2106 Label* false_label) { 1955 Label* false_label) {
2107 STATIC_ASSERT(Map::kInstanceTypeOffset < 4096); 1956 STATIC_ASSERT(Map::kInstanceTypeOffset < 4096);
2108 STATIC_ASSERT(LAST_TYPE < 256); 1957 STATIC_ASSERT(LAST_TYPE < 256);
2109 ldr(map, FieldMemOperand(object, HeapObject::kMapOffset)); 1958 LoadP(map, FieldMemOperand(object, HeapObject::kMapOffset));
2110 ldrb(ip, FieldMemOperand(map, Map::kInstanceTypeOffset)); 1959 lbz(ip, FieldMemOperand(map, Map::kInstanceTypeOffset));
2111 sub(ip, ip, Operand(min_type)); 1960 subi(ip, ip, Operand(min_type));
2112 cmp(ip, Operand(max_type - min_type)); 1961 cmpli(ip, Operand(max_type - min_type));
2113 b(hi, false_label); 1962 bgt(false_label);
2114 } 1963 }
2115 1964
2116 1965
2117 void MacroAssembler::CompareInstanceType(Register map, 1966 void MacroAssembler::CompareInstanceType(Register map,
2118 Register type_reg, 1967 Register type_reg,
2119 InstanceType type) { 1968 InstanceType type) {
2120 // Registers map and type_reg can be ip. These two lines assert
2121 // that ip can be used with the two instructions (the constants
2122 // will never need ip).
2123 STATIC_ASSERT(Map::kInstanceTypeOffset < 4096); 1969 STATIC_ASSERT(Map::kInstanceTypeOffset < 4096);
2124 STATIC_ASSERT(LAST_TYPE < 256); 1970 STATIC_ASSERT(LAST_TYPE < 256);
2125 ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset)); 1971 lbz(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
2126 cmp(type_reg, Operand(type)); 1972 cmpi(type_reg, Operand(type));
2127 } 1973 }
2128 1974
2129 1975
2130 void MacroAssembler::CompareRoot(Register obj, 1976 void MacroAssembler::CompareRoot(Register obj,
2131 Heap::RootListIndex index) { 1977 Heap::RootListIndex index) {
2132 DCHECK(!obj.is(ip)); 1978 DCHECK(!obj.is(ip));
2133 LoadRoot(ip, index); 1979 LoadRoot(ip, index);
2134 cmp(obj, ip); 1980 cmp(obj, ip);
2135 } 1981 }
2136 1982
2137 1983
2138 void MacroAssembler::CheckFastElements(Register map, 1984 void MacroAssembler::CheckFastElements(Register map,
2139 Register scratch, 1985 Register scratch,
2140 Label* fail) { 1986 Label* fail) {
2141 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); 1987 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
2142 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 1988 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
2143 STATIC_ASSERT(FAST_ELEMENTS == 2); 1989 STATIC_ASSERT(FAST_ELEMENTS == 2);
2144 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); 1990 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
2145 ldrb(scratch, FieldMemOperand(map, Map::kBitField2Offset)); 1991 lbz(scratch, FieldMemOperand(map, Map::kBitField2Offset));
2146 cmp(scratch, Operand(Map::kMaximumBitField2FastHoleyElementValue)); 1992 STATIC_ASSERT(Map::kMaximumBitField2FastHoleyElementValue < 0x8000);
2147 b(hi, fail); 1993 cmpli(scratch, Operand(Map::kMaximumBitField2FastHoleyElementValue));
1994 bgt(fail);
2148 } 1995 }
2149 1996
2150 1997
2151 void MacroAssembler::CheckFastObjectElements(Register map, 1998 void MacroAssembler::CheckFastObjectElements(Register map,
2152 Register scratch, 1999 Register scratch,
2153 Label* fail) { 2000 Label* fail) {
2154 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); 2001 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
2155 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 2002 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
2156 STATIC_ASSERT(FAST_ELEMENTS == 2); 2003 STATIC_ASSERT(FAST_ELEMENTS == 2);
2157 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); 2004 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
2158 ldrb(scratch, FieldMemOperand(map, Map::kBitField2Offset)); 2005 lbz(scratch, FieldMemOperand(map, Map::kBitField2Offset));
2159 cmp(scratch, Operand(Map::kMaximumBitField2FastHoleySmiElementValue)); 2006 cmpli(scratch, Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
2160 b(ls, fail); 2007 ble(fail);
2161 cmp(scratch, Operand(Map::kMaximumBitField2FastHoleyElementValue)); 2008 cmpli(scratch, Operand(Map::kMaximumBitField2FastHoleyElementValue));
2162 b(hi, fail); 2009 bgt(fail);
2163 } 2010 }
2164 2011
2165 2012
2166 void MacroAssembler::CheckFastSmiElements(Register map, 2013 void MacroAssembler::CheckFastSmiElements(Register map,
2167 Register scratch, 2014 Register scratch,
2168 Label* fail) { 2015 Label* fail) {
2169 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); 2016 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
2170 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 2017 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
2171 ldrb(scratch, FieldMemOperand(map, Map::kBitField2Offset)); 2018 lbz(scratch, FieldMemOperand(map, Map::kBitField2Offset));
2172 cmp(scratch, Operand(Map::kMaximumBitField2FastHoleySmiElementValue)); 2019 cmpli(scratch, Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
2173 b(hi, fail); 2020 bgt(fail);
2174 } 2021 }
2175 2022
2176 2023
2024
2177 void MacroAssembler::StoreNumberToDoubleElements( 2025 void MacroAssembler::StoreNumberToDoubleElements(
2178 Register value_reg, 2026 Register value_reg,
2179 Register key_reg, 2027 Register key_reg,
2180 Register elements_reg, 2028 Register elements_reg,
2181 Register scratch1, 2029 Register scratch1,
2182 LowDwVfpRegister double_scratch, 2030 DoubleRegister double_scratch,
2183 Label* fail, 2031 Label* fail,
2184 int elements_offset) { 2032 int elements_offset) {
2185 Label smi_value, store; 2033 Label smi_value, store;
2186 2034
2187 // Handle smi values specially. 2035 // Handle smi values specially.
2188 JumpIfSmi(value_reg, &smi_value); 2036 JumpIfSmi(value_reg, &smi_value);
2189 2037
2190 // Ensure that the object is a heap number 2038 // Ensure that the object is a heap number
2191 CheckMap(value_reg, 2039 CheckMap(value_reg,
2192 scratch1, 2040 scratch1,
2193 isolate()->factory()->heap_number_map(), 2041 isolate()->factory()->heap_number_map(),
2194 fail, 2042 fail,
2195 DONT_DO_SMI_CHECK); 2043 DONT_DO_SMI_CHECK);
2196 2044
2197 vldr(double_scratch, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); 2045 lfd(double_scratch, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
2198 // Force a canonical NaN. 2046 // Force a canonical NaN.
2199 if (emit_debug_code()) { 2047 CanonicalizeNaN(double_scratch);
2200 vmrs(ip);
2201 tst(ip, Operand(kVFPDefaultNaNModeControlBit));
2202 Assert(ne, kDefaultNaNModeNotSet);
2203 }
2204 VFPCanonicalizeNaN(double_scratch);
2205 b(&store); 2048 b(&store);
2206 2049
2207 bind(&smi_value); 2050 bind(&smi_value);
2208 SmiToDouble(double_scratch, value_reg); 2051 SmiToDouble(double_scratch, value_reg);
2209 2052
2210 bind(&store); 2053 bind(&store);
2211 add(scratch1, elements_reg, Operand::DoubleOffsetFromSmiKey(key_reg)); 2054 SmiToDoubleArrayOffset(scratch1, key_reg);
2212 vstr(double_scratch, 2055 add(scratch1, elements_reg, scratch1);
2056 stfd(double_scratch,
2213 FieldMemOperand(scratch1, 2057 FieldMemOperand(scratch1,
2214 FixedDoubleArray::kHeaderSize - elements_offset)); 2058 FixedDoubleArray::kHeaderSize - elements_offset));
2215 } 2059 }
2216 2060
2217 2061
2062 void MacroAssembler::AddAndCheckForOverflow(Register dst,
2063 Register left,
2064 Register right,
2065 Register overflow_dst,
2066 Register scratch) {
2067 DCHECK(!dst.is(overflow_dst));
2068 DCHECK(!dst.is(scratch));
2069 DCHECK(!overflow_dst.is(scratch));
2070 DCHECK(!overflow_dst.is(left));
2071 DCHECK(!overflow_dst.is(right));
2072
2073 // C = A+B; C overflows if A/B have same sign and C has diff sign than A
2074 if (dst.is(left)) {
2075 mr(scratch, left); // Preserve left.
2076 add(dst, left, right); // Left is overwritten.
2077 xor_(scratch, dst, scratch); // Original left.
2078 xor_(overflow_dst, dst, right);
2079 and_(overflow_dst, overflow_dst, scratch, SetRC);
2080 } else if (dst.is(right)) {
2081 mr(scratch, right); // Preserve right.
2082 add(dst, left, right); // Right is overwritten.
2083 xor_(scratch, dst, scratch); // Original right.
2084 xor_(overflow_dst, dst, left);
2085 and_(overflow_dst, overflow_dst, scratch, SetRC);
2086 } else {
2087 add(dst, left, right);
2088 xor_(overflow_dst, dst, left);
2089 xor_(scratch, dst, right);
2090 and_(overflow_dst, scratch, overflow_dst, SetRC);
2091 }
2092 }
2093
2094 void MacroAssembler::SubAndCheckForOverflow(Register dst,
2095 Register left,
2096 Register right,
2097 Register overflow_dst,
2098 Register scratch) {
2099 DCHECK(!dst.is(overflow_dst));
2100 DCHECK(!dst.is(scratch));
2101 DCHECK(!overflow_dst.is(scratch));
2102 DCHECK(!overflow_dst.is(left));
2103 DCHECK(!overflow_dst.is(right));
2104
2105 // C = A-B; C overflows if A/B have diff signs and C has diff sign than A
2106 if (dst.is(left)) {
2107 mr(scratch, left); // Preserve left.
2108 sub(dst, left, right); // Left is overwritten.
2109 xor_(overflow_dst, dst, scratch);
2110 xor_(scratch, scratch, right);
2111 and_(overflow_dst, overflow_dst, scratch, SetRC);
2112 } else if (dst.is(right)) {
2113 mr(scratch, right); // Preserve right.
2114 sub(dst, left, right); // Right is overwritten.
2115 xor_(overflow_dst, dst, left);
2116 xor_(scratch, left, scratch);
2117 and_(overflow_dst, overflow_dst, scratch, SetRC);
2118 } else {
2119 sub(dst, left, right);
2120 xor_(overflow_dst, dst, left);
2121 xor_(scratch, left, right);
2122 and_(overflow_dst, scratch, overflow_dst, SetRC);
2123 }
2124 }
2125
2126
2218 void MacroAssembler::CompareMap(Register obj, 2127 void MacroAssembler::CompareMap(Register obj,
2219 Register scratch, 2128 Register scratch,
2220 Handle<Map> map, 2129 Handle<Map> map,
2221 Label* early_success) { 2130 Label* early_success) {
2222 ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); 2131 LoadP(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
2223 CompareMap(scratch, map, early_success); 2132 CompareMap(scratch, map, early_success);
2224 } 2133 }
2225 2134
2226 2135
2227 void MacroAssembler::CompareMap(Register obj_map, 2136 void MacroAssembler::CompareMap(Register obj_map,
2228 Handle<Map> map, 2137 Handle<Map> map,
2229 Label* early_success) { 2138 Label* early_success) {
2230 cmp(obj_map, Operand(map)); 2139 mov(r0, Operand(map));
2140 cmp(obj_map, r0);
2231 } 2141 }
2232 2142
2233 2143
2234 void MacroAssembler::CheckMap(Register obj, 2144 void MacroAssembler::CheckMap(Register obj,
2235 Register scratch, 2145 Register scratch,
2236 Handle<Map> map, 2146 Handle<Map> map,
2237 Label* fail, 2147 Label* fail,
2238 SmiCheckType smi_check_type) { 2148 SmiCheckType smi_check_type) {
2239 if (smi_check_type == DO_SMI_CHECK) { 2149 if (smi_check_type == DO_SMI_CHECK) {
2240 JumpIfSmi(obj, fail); 2150 JumpIfSmi(obj, fail);
2241 } 2151 }
2242 2152
2243 Label success; 2153 Label success;
2244 CompareMap(obj, scratch, map, &success); 2154 CompareMap(obj, scratch, map, &success);
2245 b(ne, fail); 2155 bne(fail);
2246 bind(&success); 2156 bind(&success);
2247 } 2157 }
2248 2158
2249 2159
2250 void MacroAssembler::CheckMap(Register obj, 2160 void MacroAssembler::CheckMap(Register obj,
2251 Register scratch, 2161 Register scratch,
2252 Heap::RootListIndex index, 2162 Heap::RootListIndex index,
2253 Label* fail, 2163 Label* fail,
2254 SmiCheckType smi_check_type) { 2164 SmiCheckType smi_check_type) {
2255 if (smi_check_type == DO_SMI_CHECK) { 2165 if (smi_check_type == DO_SMI_CHECK) {
2256 JumpIfSmi(obj, fail); 2166 JumpIfSmi(obj, fail);
2257 } 2167 }
2258 ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); 2168 LoadP(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
2259 LoadRoot(ip, index); 2169 LoadRoot(ip, index);
2260 cmp(scratch, ip); 2170 cmp(scratch, ip);
2261 b(ne, fail); 2171 bne(fail);
2262 } 2172 }
2263 2173
2264 2174
2265 void MacroAssembler::DispatchMap(Register obj, 2175 void MacroAssembler::DispatchMap(Register obj,
2266 Register scratch, 2176 Register scratch,
2267 Handle<Map> map, 2177 Handle<Map> map,
2268 Handle<Code> success, 2178 Handle<Code> success,
2269 SmiCheckType smi_check_type) { 2179 SmiCheckType smi_check_type) {
2270 Label fail; 2180 Label fail;
2271 if (smi_check_type == DO_SMI_CHECK) { 2181 if (smi_check_type == DO_SMI_CHECK) {
2272 JumpIfSmi(obj, &fail); 2182 JumpIfSmi(obj, &fail);
2273 } 2183 }
2274 ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); 2184 LoadP(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
2275 mov(ip, Operand(map)); 2185 mov(ip, Operand(map));
2276 cmp(scratch, ip); 2186 cmp(scratch, ip);
2277 Jump(success, RelocInfo::CODE_TARGET, eq); 2187 bne(&fail);
2188 Jump(success, RelocInfo::CODE_TARGET, al);
2278 bind(&fail); 2189 bind(&fail);
2279 } 2190 }
2280 2191
2281 2192
2282 void MacroAssembler::TryGetFunctionPrototype(Register function, 2193 void MacroAssembler::TryGetFunctionPrototype(Register function,
2283 Register result, 2194 Register result,
2284 Register scratch, 2195 Register scratch,
2285 Label* miss, 2196 Label* miss,
2286 bool miss_on_bound_function) { 2197 bool miss_on_bound_function) {
2287 Label non_instance; 2198 Label non_instance;
2288 if (miss_on_bound_function) { 2199 if (miss_on_bound_function) {
2289 // Check that the receiver isn't a smi. 2200 // Check that the receiver isn't a smi.
2290 JumpIfSmi(function, miss); 2201 JumpIfSmi(function, miss);
2291 2202
2292 // Check that the function really is a function. Load map into result reg. 2203 // Check that the function really is a function. Load map into result reg.
2293 CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE); 2204 CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE);
2294 b(ne, miss); 2205 bne(miss);
2295 2206
2296 ldr(scratch, 2207 LoadP(scratch,
2297 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); 2208 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
2298 ldr(scratch, 2209 lwz(scratch,
2299 FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset)); 2210 FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
2300 tst(scratch, 2211 TestBit(scratch,
2301 Operand(Smi::FromInt(1 << SharedFunctionInfo::kBoundFunction))); 2212 #if V8_TARGET_ARCH_PPC64
2302 b(ne, miss); 2213 SharedFunctionInfo::kBoundFunction,
2214 #else
2215 SharedFunctionInfo::kBoundFunction + kSmiTagSize,
2216 #endif
2217 r0);
2218 bne(miss, cr0);
2303 2219
2304 // Make sure that the function has an instance prototype. 2220 // Make sure that the function has an instance prototype.
2305 ldrb(scratch, FieldMemOperand(result, Map::kBitFieldOffset)); 2221 lbz(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
2306 tst(scratch, Operand(1 << Map::kHasNonInstancePrototype)); 2222 andi(r0, scratch, Operand(1 << Map::kHasNonInstancePrototype));
2307 b(ne, &non_instance); 2223 bne(&non_instance, cr0);
2308 } 2224 }
2309 2225
2310 // Get the prototype or initial map from the function. 2226 // Get the prototype or initial map from the function.
2311 ldr(result, 2227 LoadP(result,
2312 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 2228 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2313 2229
2314 // If the prototype or initial map is the hole, don't return it and 2230 // If the prototype or initial map is the hole, don't return it and
2315 // simply miss the cache instead. This will allow us to allocate a 2231 // simply miss the cache instead. This will allow us to allocate a
2316 // prototype object on-demand in the runtime system. 2232 // prototype object on-demand in the runtime system.
2317 LoadRoot(ip, Heap::kTheHoleValueRootIndex); 2233 LoadRoot(ip, Heap::kTheHoleValueRootIndex);
2318 cmp(result, ip); 2234 cmp(result, ip);
2319 b(eq, miss); 2235 beq(miss);
2320 2236
2321 // If the function does not have an initial map, we're done. 2237 // If the function does not have an initial map, we're done.
2322 Label done; 2238 Label done;
2323 CompareObjectType(result, scratch, scratch, MAP_TYPE); 2239 CompareObjectType(result, scratch, scratch, MAP_TYPE);
2324 b(ne, &done); 2240 bne(&done);
2325 2241
2326 // Get the prototype from the initial map. 2242 // Get the prototype from the initial map.
2327 ldr(result, FieldMemOperand(result, Map::kPrototypeOffset)); 2243 LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset));
2328 2244
2329 if (miss_on_bound_function) { 2245 if (miss_on_bound_function) {
2330 jmp(&done); 2246 b(&done);
2331 2247
2332 // Non-instance prototype: Fetch prototype from constructor field 2248 // Non-instance prototype: Fetch prototype from constructor field
2333 // in initial map. 2249 // in initial map.
2334 bind(&non_instance); 2250 bind(&non_instance);
2335 ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); 2251 LoadP(result, FieldMemOperand(result, Map::kConstructorOffset));
2336 } 2252 }
2337 2253
2338 // All done. 2254 // All done.
2339 bind(&done); 2255 bind(&done);
2340 } 2256 }
2341 2257
2342 2258
2343 void MacroAssembler::CallStub(CodeStub* stub, 2259 void MacroAssembler::CallStub(CodeStub* stub,
2344 TypeFeedbackId ast_id, 2260 TypeFeedbackId ast_id,
2345 Condition cond) { 2261 Condition cond) {
(...skipping 12 matching lines...) Expand all
2358 } 2274 }
2359 2275
2360 2276
2361 void MacroAssembler::CallApiFunctionAndReturn( 2277 void MacroAssembler::CallApiFunctionAndReturn(
2362 Register function_address, 2278 Register function_address,
2363 ExternalReference thunk_ref, 2279 ExternalReference thunk_ref,
2364 int stack_space, 2280 int stack_space,
2365 MemOperand return_value_operand, 2281 MemOperand return_value_operand,
2366 MemOperand* context_restore_operand) { 2282 MemOperand* context_restore_operand) {
2367 ExternalReference next_address = 2283 ExternalReference next_address =
2368 ExternalReference::handle_scope_next_address(isolate()); 2284 ExternalReference::handle_scope_next_address(isolate());
2369 const int kNextOffset = 0; 2285 const int kNextOffset = 0;
2370 const int kLimitOffset = AddressOffset( 2286 const int kLimitOffset = AddressOffset(
2371 ExternalReference::handle_scope_limit_address(isolate()), 2287 ExternalReference::handle_scope_limit_address(isolate()),
2372 next_address); 2288 next_address);
2373 const int kLevelOffset = AddressOffset( 2289 const int kLevelOffset = AddressOffset(
2374 ExternalReference::handle_scope_level_address(isolate()), 2290 ExternalReference::handle_scope_level_address(isolate()),
2375 next_address); 2291 next_address);
2376 2292
2377 DCHECK(function_address.is(r1) || function_address.is(r2)); 2293 DCHECK(function_address.is(r4) || function_address.is(r5));
2294 Register scratch = r6;
2378 2295
2379 Label profiler_disabled; 2296 Label profiler_disabled;
2380 Label end_profiler_check; 2297 Label end_profiler_check;
2381 mov(r9, Operand(ExternalReference::is_profiling_address(isolate()))); 2298 mov(scratch, Operand(ExternalReference::is_profiling_address(isolate())));
2382 ldrb(r9, MemOperand(r9, 0)); 2299 lbz(scratch, MemOperand(scratch, 0));
2383 cmp(r9, Operand(0)); 2300 cmpi(scratch, Operand::Zero());
2384 b(eq, &profiler_disabled); 2301 beq(&profiler_disabled);
2385 2302
2386 // Additional parameter is the address of the actual callback. 2303 // Additional parameter is the address of the actual callback.
2387 mov(r3, Operand(thunk_ref)); 2304 mov(scratch, Operand(thunk_ref));
2388 jmp(&end_profiler_check); 2305 jmp(&end_profiler_check);
2389 2306
2390 bind(&profiler_disabled); 2307 bind(&profiler_disabled);
2391 Move(r3, function_address); 2308 mr(scratch, function_address);
2392 bind(&end_profiler_check); 2309 bind(&end_profiler_check);
2393 2310
2394 // Allocate HandleScope in callee-save registers. 2311 // Allocate HandleScope in callee-save registers.
2395 mov(r9, Operand(next_address)); 2312 // r17 - next_address
2396 ldr(r4, MemOperand(r9, kNextOffset)); 2313 // r14 - next_address->kNextOffset
2397 ldr(r5, MemOperand(r9, kLimitOffset)); 2314 // r15 - next_address->kLimitOffset
2398 ldr(r6, MemOperand(r9, kLevelOffset)); 2315 // r16 - next_address->kLevelOffset
2399 add(r6, r6, Operand(1)); 2316 mov(r17, Operand(next_address));
2400 str(r6, MemOperand(r9, kLevelOffset)); 2317 LoadP(r14, MemOperand(r17, kNextOffset));
2318 LoadP(r15, MemOperand(r17, kLimitOffset));
2319 lwz(r16, MemOperand(r17, kLevelOffset));
2320 addi(r16, r16, Operand(1));
2321 stw(r16, MemOperand(r17, kLevelOffset));
2401 2322
2402 if (FLAG_log_timer_events) { 2323 if (FLAG_log_timer_events) {
2403 FrameScope frame(this, StackFrame::MANUAL); 2324 FrameScope frame(this, StackFrame::MANUAL);
2404 PushSafepointRegisters(); 2325 PushSafepointRegisters();
2405 PrepareCallCFunction(1, r0); 2326 PrepareCallCFunction(1, r3);
2406 mov(r0, Operand(ExternalReference::isolate_address(isolate()))); 2327 mov(r3, Operand(ExternalReference::isolate_address(isolate())));
2407 CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1); 2328 CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1);
2408 PopSafepointRegisters(); 2329 PopSafepointRegisters();
2409 } 2330 }
2410 2331
2411 // Native call returns to the DirectCEntry stub which redirects to the 2332 // Native call returns to the DirectCEntry stub which redirects to the
2412 // return address pushed on stack (could have moved after GC). 2333 // return address pushed on stack (could have moved after GC).
2413 // DirectCEntry stub itself is generated early and never moves. 2334 // DirectCEntry stub itself is generated early and never moves.
2414 DirectCEntryStub stub(isolate()); 2335 DirectCEntryStub stub(isolate());
2415 stub.GenerateCall(this, r3); 2336 stub.GenerateCall(this, scratch);
2416 2337
2417 if (FLAG_log_timer_events) { 2338 if (FLAG_log_timer_events) {
2418 FrameScope frame(this, StackFrame::MANUAL); 2339 FrameScope frame(this, StackFrame::MANUAL);
2419 PushSafepointRegisters(); 2340 PushSafepointRegisters();
2420 PrepareCallCFunction(1, r0); 2341 PrepareCallCFunction(1, r3);
2421 mov(r0, Operand(ExternalReference::isolate_address(isolate()))); 2342 mov(r3, Operand(ExternalReference::isolate_address(isolate())));
2422 CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1); 2343 CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1);
2423 PopSafepointRegisters(); 2344 PopSafepointRegisters();
2424 } 2345 }
2425 2346
2426 Label promote_scheduled_exception; 2347 Label promote_scheduled_exception;
2427 Label exception_handled; 2348 Label exception_handled;
2428 Label delete_allocated_handles; 2349 Label delete_allocated_handles;
2429 Label leave_exit_frame; 2350 Label leave_exit_frame;
2430 Label return_value_loaded; 2351 Label return_value_loaded;
2431 2352
2432 // load value from ReturnValue 2353 // load value from ReturnValue
2433 ldr(r0, return_value_operand); 2354 LoadP(r3, return_value_operand);
2434 bind(&return_value_loaded); 2355 bind(&return_value_loaded);
2435 // No more valid handles (the result handle was the last one). Restore 2356 // No more valid handles (the result handle was the last one). Restore
2436 // previous handle scope. 2357 // previous handle scope.
2437 str(r4, MemOperand(r9, kNextOffset)); 2358 StoreP(r14, MemOperand(r17, kNextOffset));
2438 if (emit_debug_code()) { 2359 if (emit_debug_code()) {
2439 ldr(r1, MemOperand(r9, kLevelOffset)); 2360 lwz(r4, MemOperand(r17, kLevelOffset));
2440 cmp(r1, r6); 2361 cmp(r4, r16);
2441 Check(eq, kUnexpectedLevelAfterReturnFromApiCall); 2362 Check(eq, kUnexpectedLevelAfterReturnFromApiCall);
2442 } 2363 }
2443 sub(r6, r6, Operand(1)); 2364 subi(r16, r16, Operand(1));
2444 str(r6, MemOperand(r9, kLevelOffset)); 2365 stw(r16, MemOperand(r17, kLevelOffset));
2445 ldr(ip, MemOperand(r9, kLimitOffset)); 2366 LoadP(ip, MemOperand(r17, kLimitOffset));
2446 cmp(r5, ip); 2367 cmp(r15, ip);
2447 b(ne, &delete_allocated_handles); 2368 bne(&delete_allocated_handles);
2448 2369
2449 // Check if the function scheduled an exception. 2370 // Check if the function scheduled an exception.
2450 bind(&leave_exit_frame); 2371 bind(&leave_exit_frame);
2451 LoadRoot(r4, Heap::kTheHoleValueRootIndex); 2372 LoadRoot(r14, Heap::kTheHoleValueRootIndex);
2452 mov(ip, Operand(ExternalReference::scheduled_exception_address(isolate()))); 2373 mov(ip, Operand(ExternalReference::scheduled_exception_address(isolate())));
2453 ldr(r5, MemOperand(ip)); 2374 LoadP(r15, MemOperand(ip));
2454 cmp(r4, r5); 2375 cmp(r14, r15);
2455 b(ne, &promote_scheduled_exception); 2376 bne(&promote_scheduled_exception);
2456 bind(&exception_handled); 2377 bind(&exception_handled);
2457 2378
2458 bool restore_context = context_restore_operand != NULL; 2379 bool restore_context = context_restore_operand != NULL;
2459 if (restore_context) { 2380 if (restore_context) {
2460 ldr(cp, *context_restore_operand); 2381 LoadP(cp, *context_restore_operand);
2461 } 2382 }
2462 // LeaveExitFrame expects unwind space to be in a register. 2383 // LeaveExitFrame expects unwind space to be in a register.
2463 mov(r4, Operand(stack_space)); 2384 mov(r14, Operand(stack_space));
2464 LeaveExitFrame(false, r4, !restore_context); 2385 LeaveExitFrame(false, r14, !restore_context);
2465 mov(pc, lr); 2386 blr();
2466 2387
2467 bind(&promote_scheduled_exception); 2388 bind(&promote_scheduled_exception);
2468 { 2389 {
2469 FrameScope frame(this, StackFrame::INTERNAL); 2390 FrameScope frame(this, StackFrame::INTERNAL);
2470 CallExternalReference( 2391 CallExternalReference(
2471 ExternalReference(Runtime::kPromoteScheduledException, isolate()), 2392 ExternalReference(Runtime::kPromoteScheduledException, isolate()),
2472 0); 2393 0);
2473 } 2394 }
2474 jmp(&exception_handled); 2395 jmp(&exception_handled);
2475 2396
2476 // HandleScope limit has changed. Delete allocated extensions. 2397 // HandleScope limit has changed. Delete allocated extensions.
2477 bind(&delete_allocated_handles); 2398 bind(&delete_allocated_handles);
2478 str(r5, MemOperand(r9, kLimitOffset)); 2399 StoreP(r15, MemOperand(r17, kLimitOffset));
2479 mov(r4, r0); 2400 mr(r14, r3);
2480 PrepareCallCFunction(1, r5); 2401 PrepareCallCFunction(1, r15);
2481 mov(r0, Operand(ExternalReference::isolate_address(isolate()))); 2402 mov(r3, Operand(ExternalReference::isolate_address(isolate())));
2482 CallCFunction( 2403 CallCFunction(
2483 ExternalReference::delete_handle_scope_extensions(isolate()), 1); 2404 ExternalReference::delete_handle_scope_extensions(isolate()), 1);
2484 mov(r0, r4); 2405 mr(r3, r14);
2485 jmp(&leave_exit_frame); 2406 b(&leave_exit_frame);
2486 } 2407 }
2487 2408
2488 2409
2489 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { 2410 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
2490 return has_frame_ || !stub->SometimesSetsUpAFrame(); 2411 return has_frame_ || !stub->SometimesSetsUpAFrame();
2491 } 2412 }
2492 2413
2493 2414
2494 void MacroAssembler::IndexFromHash(Register hash, Register index) { 2415 void MacroAssembler::IndexFromHash(Register hash, Register index) {
2495 // If the hash field contains an array index pick it out. The assert checks 2416 // If the hash field contains an array index pick it out. The assert checks
2496 // that the constants for the maximum number of digits for an array index 2417 // that the constants for the maximum number of digits for an array index
2497 // cached in the hash field and the number of bits reserved for it does not 2418 // cached in the hash field and the number of bits reserved for it does not
2498 // conflict. 2419 // conflict.
2499 DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) < 2420 DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
2500 (1 << String::kArrayIndexValueBits)); 2421 (1 << String::kArrayIndexValueBits));
2501 DecodeFieldToSmi<String::ArrayIndexValueBits>(index, hash); 2422 DecodeFieldToSmi<String::ArrayIndexValueBits>(index, hash);
2502 } 2423 }
2503 2424
2504 2425
2505 void MacroAssembler::SmiToDouble(LowDwVfpRegister value, Register smi) { 2426 void MacroAssembler::SmiToDouble(DoubleRegister value, Register smi) {
2506 if (CpuFeatures::IsSupported(VFP3)) { 2427 SmiUntag(ip, smi);
2507 vmov(value.low(), smi); 2428 ConvertIntToDouble(ip, value);
2508 vcvt_f64_s32(value, 1);
2509 } else {
2510 SmiUntag(ip, smi);
2511 vmov(value.low(), ip);
2512 vcvt_f64_s32(value, value.low());
2513 }
2514 } 2429 }
2515 2430
2516 2431
2517 void MacroAssembler::TestDoubleIsInt32(DwVfpRegister double_input, 2432 void MacroAssembler::TestDoubleIsInt32(DoubleRegister double_input,
2518 LowDwVfpRegister double_scratch) { 2433 Register scratch1,
2519 DCHECK(!double_input.is(double_scratch)); 2434 Register scratch2,
2520 vcvt_s32_f64(double_scratch.low(), double_input); 2435 DoubleRegister double_scratch) {
2521 vcvt_f64_s32(double_scratch, double_scratch.low()); 2436 TryDoubleToInt32Exact(scratch1, double_input, scratch2, double_scratch);
2522 VFPCompareAndSetFlags(double_input, double_scratch);
2523 } 2437 }
2524 2438
2525 2439
2526 void MacroAssembler::TryDoubleToInt32Exact(Register result, 2440 void MacroAssembler::TryDoubleToInt32Exact(Register result,
2527 DwVfpRegister double_input, 2441 DoubleRegister double_input,
2528 LowDwVfpRegister double_scratch) { 2442 Register scratch,
2443 DoubleRegister double_scratch) {
2444 Label done;
2529 DCHECK(!double_input.is(double_scratch)); 2445 DCHECK(!double_input.is(double_scratch));
2530 vcvt_s32_f64(double_scratch.low(), double_input); 2446
2531 vmov(result, double_scratch.low()); 2447 ConvertDoubleToInt64(double_input,
2532 vcvt_f64_s32(double_scratch, double_scratch.low()); 2448 #if !V8_TARGET_ARCH_PPC64
2533 VFPCompareAndSetFlags(double_input, double_scratch); 2449 scratch,
2450 #endif
2451 result, double_scratch);
2452
2453 #if V8_TARGET_ARCH_PPC64
2454 TestIfInt32(result, scratch, r0);
2455 #else
2456 TestIfInt32(scratch, result, r0);
2457 #endif
2458 bne(&done);
2459
2460 // convert back and compare
2461 fcfid(double_scratch, double_scratch);
2462 fcmpu(double_scratch, double_input);
2463 bind(&done);
2534 } 2464 }
2535 2465
2536 2466
2537 void MacroAssembler::TryInt32Floor(Register result, 2467 void MacroAssembler::TryInt32Floor(Register result,
2538 DwVfpRegister double_input, 2468 DoubleRegister double_input,
2539 Register input_high, 2469 Register input_high,
2540 LowDwVfpRegister double_scratch, 2470 Register scratch,
2471 DoubleRegister double_scratch,
2541 Label* done, 2472 Label* done,
2542 Label* exact) { 2473 Label* exact) {
2543 DCHECK(!result.is(input_high)); 2474 DCHECK(!result.is(input_high));
2544 DCHECK(!double_input.is(double_scratch)); 2475 DCHECK(!double_input.is(double_scratch));
2545 Label negative, exception; 2476 Label exception;
2546 2477
2547 VmovHigh(input_high, double_input); 2478 MovDoubleHighToInt(input_high, double_input);
2548 2479
2549 // Test for NaN and infinities. 2480 // Test for NaN/Inf
2550 Sbfx(result, input_high, 2481 ExtractBitMask(result, input_high, HeapNumber::kExponentMask);
2551 HeapNumber::kExponentShift, HeapNumber::kExponentBits); 2482 cmpli(result, Operand(0x7ff));
2552 cmp(result, Operand(-1)); 2483 beq(&exception);
2553 b(eq, &exception);
2554 // Test for values that can be exactly represented as a
2555 // signed 32-bit integer.
2556 TryDoubleToInt32Exact(result, double_input, double_scratch);
2557 // If exact, return (result already fetched).
2558 b(eq, exact);
2559 cmp(input_high, Operand::Zero());
2560 b(mi, &negative);
2561 2484
2562 // Input is in ]+0, +inf[. 2485 // Convert (rounding to -Inf)
2563 // If result equals 0x7fffffff input was out of range or 2486 ConvertDoubleToInt64(double_input,
2564 // in ]0x7fffffff, 0x80000000[. We ignore this last case which 2487 #if !V8_TARGET_ARCH_PPC64
2565 // could fits into an int32, that means we always think input was 2488 scratch,
2566 // out of range and always go to exception. 2489 #endif
2567 // If result < 0x7fffffff, go to done, result fetched. 2490 result, double_scratch,
2568 cmn(result, Operand(1)); 2491 kRoundToMinusInf);
2569 b(mi, &exception); 2492
2493 // Test for overflow
2494 #if V8_TARGET_ARCH_PPC64
2495 TestIfInt32(result, scratch, r0);
2496 #else
2497 TestIfInt32(scratch, result, r0);
2498 #endif
2499 bne(&exception);
2500
2501 // Test for exactness
2502 fcfid(double_scratch, double_scratch);
2503 fcmpu(double_scratch, double_input);
2504 beq(exact);
2570 b(done); 2505 b(done);
2571 2506
2572 // Input is in ]-inf, -0[.
2573 // If x is a non integer negative number,
2574 // floor(x) <=> round_to_zero(x) - 1.
2575 bind(&negative);
2576 sub(result, result, Operand(1), SetCC);
2577 // If result is still negative, go to done, result fetched.
2578 // Else, we had an overflow and we fall through exception.
2579 b(mi, done);
2580 bind(&exception); 2507 bind(&exception);
2581 } 2508 }
2582 2509
2510
2583 void MacroAssembler::TryInlineTruncateDoubleToI(Register result, 2511 void MacroAssembler::TryInlineTruncateDoubleToI(Register result,
2584 DwVfpRegister double_input, 2512 DoubleRegister double_input,
2585 Label* done) { 2513 Label* done) {
2586 LowDwVfpRegister double_scratch = kScratchDoubleReg; 2514 DoubleRegister double_scratch = kScratchDoubleReg;
2587 vcvt_s32_f64(double_scratch.low(), double_input); 2515 Register scratch = ip;
2588 vmov(result, double_scratch.low());
2589 2516
2590 // If result is not saturated (0x7fffffff or 0x80000000), we are done. 2517 ConvertDoubleToInt64(double_input,
2591 sub(ip, result, Operand(1)); 2518 #if !V8_TARGET_ARCH_PPC64
2592 cmp(ip, Operand(0x7ffffffe)); 2519 scratch,
2593 b(lt, done); 2520 #endif
2521 result, double_scratch);
2522
2523 // Test for overflow
2524 #if V8_TARGET_ARCH_PPC64
2525 TestIfInt32(result, scratch, r0);
2526 #else
2527 TestIfInt32(scratch, result, r0);
2528 #endif
2529 beq(done);
2594 } 2530 }
2595 2531
2596 2532
2597 void MacroAssembler::TruncateDoubleToI(Register result, 2533 void MacroAssembler::TruncateDoubleToI(Register result,
2598 DwVfpRegister double_input) { 2534 DoubleRegister double_input) {
2599 Label done; 2535 Label done;
2600 2536
2601 TryInlineTruncateDoubleToI(result, double_input, &done); 2537 TryInlineTruncateDoubleToI(result, double_input, &done);
2602 2538
2603 // If we fell through then inline version didn't succeed - call stub instead. 2539 // If we fell through then inline version didn't succeed - call stub instead.
2604 push(lr); 2540 mflr(r0);
2605 sub(sp, sp, Operand(kDoubleSize)); // Put input on stack. 2541 push(r0);
2606 vstr(double_input, MemOperand(sp, 0)); 2542 // Put input on stack.
2543 stfdu(double_input, MemOperand(sp, -kDoubleSize));
2607 2544
2608 DoubleToIStub stub(isolate(), sp, result, 0, true, true); 2545 DoubleToIStub stub(isolate(), sp, result, 0, true, true);
2609 CallStub(&stub); 2546 CallStub(&stub);
2610 2547
2611 add(sp, sp, Operand(kDoubleSize)); 2548 addi(sp, sp, Operand(kDoubleSize));
2612 pop(lr); 2549 pop(r0);
2550 mtlr(r0);
2613 2551
2614 bind(&done); 2552 bind(&done);
2615 } 2553 }
2616 2554
2617 2555
2618 void MacroAssembler::TruncateHeapNumberToI(Register result, 2556 void MacroAssembler::TruncateHeapNumberToI(Register result,
2619 Register object) { 2557 Register object) {
2620 Label done; 2558 Label done;
2621 LowDwVfpRegister double_scratch = kScratchDoubleReg; 2559 DoubleRegister double_scratch = kScratchDoubleReg;
2622 DCHECK(!result.is(object)); 2560 DCHECK(!result.is(object));
2623 2561
2624 vldr(double_scratch, 2562 lfd(double_scratch, FieldMemOperand(object, HeapNumber::kValueOffset));
2625 MemOperand(object, HeapNumber::kValueOffset - kHeapObjectTag));
2626 TryInlineTruncateDoubleToI(result, double_scratch, &done); 2563 TryInlineTruncateDoubleToI(result, double_scratch, &done);
2627 2564
2628 // If we fell through then inline version didn't succeed - call stub instead. 2565 // If we fell through then inline version didn't succeed - call stub instead.
2629 push(lr); 2566 mflr(r0);
2567 push(r0);
2630 DoubleToIStub stub(isolate(), 2568 DoubleToIStub stub(isolate(),
2631 object, 2569 object,
2632 result, 2570 result,
2633 HeapNumber::kValueOffset - kHeapObjectTag, 2571 HeapNumber::kValueOffset - kHeapObjectTag,
2634 true, 2572 true,
2635 true); 2573 true);
2636 CallStub(&stub); 2574 CallStub(&stub);
2637 pop(lr); 2575 pop(r0);
2576 mtlr(r0);
2638 2577
2639 bind(&done); 2578 bind(&done);
2640 } 2579 }
2641 2580
2642 2581
2643 void MacroAssembler::TruncateNumberToI(Register object, 2582 void MacroAssembler::TruncateNumberToI(Register object,
2644 Register result, 2583 Register result,
2645 Register heap_number_map, 2584 Register heap_number_map,
2646 Register scratch1, 2585 Register scratch1,
2647 Label* not_number) { 2586 Label* not_number) {
2648 Label done; 2587 Label done;
2649 DCHECK(!result.is(object)); 2588 DCHECK(!result.is(object));
2650 2589
2651 UntagAndJumpIfSmi(result, object, &done); 2590 UntagAndJumpIfSmi(result, object, &done);
2652 JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); 2591 JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
2653 TruncateHeapNumberToI(result, object); 2592 TruncateHeapNumberToI(result, object);
2654 2593
2655 bind(&done); 2594 bind(&done);
2656 } 2595 }
2657 2596
2658 2597
2659 void MacroAssembler::GetLeastBitsFromSmi(Register dst, 2598 void MacroAssembler::GetLeastBitsFromSmi(Register dst,
2660 Register src, 2599 Register src,
2661 int num_least_bits) { 2600 int num_least_bits) {
2662 if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size()) { 2601 #if V8_TARGET_ARCH_PPC64
2663 ubfx(dst, src, kSmiTagSize, num_least_bits); 2602 rldicl(dst, src, kBitsPerPointer - kSmiShift,
2664 } else { 2603 kBitsPerPointer - num_least_bits);
2665 SmiUntag(dst, src); 2604 #else
2666 and_(dst, dst, Operand((1 << num_least_bits) - 1)); 2605 rlwinm(dst, src, kBitsPerPointer - kSmiShift,
2667 } 2606 kBitsPerPointer - num_least_bits, 31);
2607 #endif
2668 } 2608 }
2669 2609
2670 2610
2671 void MacroAssembler::GetLeastBitsFromInt32(Register dst, 2611 void MacroAssembler::GetLeastBitsFromInt32(Register dst,
2672 Register src, 2612 Register src,
2673 int num_least_bits) { 2613 int num_least_bits) {
2674 and_(dst, src, Operand((1 << num_least_bits) - 1)); 2614 rlwinm(dst, src, 0, 32 - num_least_bits, 31);
2675 } 2615 }
2676 2616
2677 2617
2678 void MacroAssembler::CallRuntime(const Runtime::Function* f, 2618 void MacroAssembler::CallRuntime(const Runtime::Function* f,
2679 int num_arguments, 2619 int num_arguments,
2680 SaveFPRegsMode save_doubles) { 2620 SaveFPRegsMode save_doubles) {
2681 // All parameters are on the stack. r0 has the return value after call. 2621 // All parameters are on the stack. r3 has the return value after call.
2682 2622
2683 // If the expected number of arguments of the runtime function is 2623 // If the expected number of arguments of the runtime function is
2684 // constant, we check that the actual number of arguments match the 2624 // constant, we check that the actual number of arguments match the
2685 // expectation. 2625 // expectation.
2686 CHECK(f->nargs < 0 || f->nargs == num_arguments); 2626 CHECK(f->nargs < 0 || f->nargs == num_arguments);
2687 2627
2688 // TODO(1236192): Most runtime routines don't need the number of 2628 // TODO(1236192): Most runtime routines don't need the number of
2689 // arguments passed in because it is constant. At some point we 2629 // arguments passed in because it is constant. At some point we
2690 // should remove this need and make the runtime routine entry code 2630 // should remove this need and make the runtime routine entry code
2691 // smarter. 2631 // smarter.
2692 mov(r0, Operand(num_arguments)); 2632 mov(r3, Operand(num_arguments));
2693 mov(r1, Operand(ExternalReference(f, isolate()))); 2633 mov(r4, Operand(ExternalReference(f, isolate())));
2694 CEntryStub stub(isolate(), 1, save_doubles); 2634 CEntryStub stub(isolate(),
2635 #if V8_TARGET_ARCH_PPC64
2636 f->result_size,
2637 #else
2638 1,
2639 #endif
2640 save_doubles);
2695 CallStub(&stub); 2641 CallStub(&stub);
2696 } 2642 }
2697 2643
2698 2644
2699 void MacroAssembler::CallExternalReference(const ExternalReference& ext, 2645 void MacroAssembler::CallExternalReference(const ExternalReference& ext,
2700 int num_arguments) { 2646 int num_arguments) {
2701 mov(r0, Operand(num_arguments)); 2647 mov(r3, Operand(num_arguments));
2702 mov(r1, Operand(ext)); 2648 mov(r4, Operand(ext));
2703 2649
2704 CEntryStub stub(isolate(), 1); 2650 CEntryStub stub(isolate(), 1);
2705 CallStub(&stub); 2651 CallStub(&stub);
2706 } 2652 }
2707 2653
2708 2654
2709 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext, 2655 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
2710 int num_arguments, 2656 int num_arguments,
2711 int result_size) { 2657 int result_size) {
2712 // TODO(1236192): Most runtime routines don't need the number of 2658 // TODO(1236192): Most runtime routines don't need the number of
2713 // arguments passed in because it is constant. At some point we 2659 // arguments passed in because it is constant. At some point we
2714 // should remove this need and make the runtime routine entry code 2660 // should remove this need and make the runtime routine entry code
2715 // smarter. 2661 // smarter.
2716 mov(r0, Operand(num_arguments)); 2662 mov(r3, Operand(num_arguments));
2717 JumpToExternalReference(ext); 2663 JumpToExternalReference(ext);
2718 } 2664 }
2719 2665
2720 2666
2721 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, 2667 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
2722 int num_arguments, 2668 int num_arguments,
2723 int result_size) { 2669 int result_size) {
2724 TailCallExternalReference(ExternalReference(fid, isolate()), 2670 TailCallExternalReference(ExternalReference(fid, isolate()),
2725 num_arguments, 2671 num_arguments,
2726 result_size); 2672 result_size);
2727 } 2673 }
2728 2674
2729 2675
2730 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin) { 2676 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin) {
2731 #if defined(__thumb__) 2677 mov(r4, Operand(builtin));
2732 // Thumb mode builtin.
2733 DCHECK((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1);
2734 #endif
2735 mov(r1, Operand(builtin));
2736 CEntryStub stub(isolate(), 1); 2678 CEntryStub stub(isolate(), 1);
2737 Jump(stub.GetCode(), RelocInfo::CODE_TARGET); 2679 Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
2738 } 2680 }
2739 2681
2740 2682
2741 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, 2683 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
2742 InvokeFlag flag, 2684 InvokeFlag flag,
2743 const CallWrapper& call_wrapper) { 2685 const CallWrapper& call_wrapper) {
2744 // You can't call a builtin without a valid frame. 2686 // You can't call a builtin without a valid frame.
2745 DCHECK(flag == JUMP_FUNCTION || has_frame()); 2687 DCHECK(flag == JUMP_FUNCTION || has_frame());
2746 2688
2747 GetBuiltinEntry(r2, id); 2689 GetBuiltinEntry(r5, id);
2748 if (flag == CALL_FUNCTION) { 2690 if (flag == CALL_FUNCTION) {
2749 call_wrapper.BeforeCall(CallSize(r2)); 2691 call_wrapper.BeforeCall(CallSize(r5));
2750 Call(r2); 2692 Call(r5);
2751 call_wrapper.AfterCall(); 2693 call_wrapper.AfterCall();
2752 } else { 2694 } else {
2753 DCHECK(flag == JUMP_FUNCTION); 2695 DCHECK(flag == JUMP_FUNCTION);
2754 Jump(r2); 2696 Jump(r5);
2755 } 2697 }
2756 } 2698 }
2757 2699
2758 2700
2759 void MacroAssembler::GetBuiltinFunction(Register target, 2701 void MacroAssembler::GetBuiltinFunction(Register target,
2760 Builtins::JavaScript id) { 2702 Builtins::JavaScript id) {
2761 // Load the builtins object into target register. 2703 // Load the builtins object into target register.
2762 ldr(target, 2704 LoadP(target,
2763 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 2705 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
2764 ldr(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset)); 2706 LoadP(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset));
2765 // Load the JavaScript builtin function from the builtins object. 2707 // Load the JavaScript builtin function from the builtins object.
2766 ldr(target, FieldMemOperand(target, 2708 LoadP(target,
2767 JSBuiltinsObject::OffsetOfFunctionWithId(id))); 2709 FieldMemOperand(target,
2710 JSBuiltinsObject::OffsetOfFunctionWithId(id)), r0);
2768 } 2711 }
2769 2712
2770 2713
2771 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { 2714 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
2772 DCHECK(!target.is(r1)); 2715 DCHECK(!target.is(r4));
2773 GetBuiltinFunction(r1, id); 2716 GetBuiltinFunction(r4, id);
2774 // Load the code entry point from the builtins object. 2717 // Load the code entry point from the builtins object.
2775 ldr(target, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); 2718 LoadP(target, FieldMemOperand(r4, JSFunction::kCodeEntryOffset));
2776 } 2719 }
2777 2720
2778 2721
2779 void MacroAssembler::SetCounter(StatsCounter* counter, int value, 2722 void MacroAssembler::SetCounter(StatsCounter* counter, int value,
2780 Register scratch1, Register scratch2) { 2723 Register scratch1, Register scratch2) {
2781 if (FLAG_native_code_counters && counter->Enabled()) { 2724 if (FLAG_native_code_counters && counter->Enabled()) {
2782 mov(scratch1, Operand(value)); 2725 mov(scratch1, Operand(value));
2783 mov(scratch2, Operand(ExternalReference(counter))); 2726 mov(scratch2, Operand(ExternalReference(counter)));
2784 str(scratch1, MemOperand(scratch2)); 2727 stw(scratch1, MemOperand(scratch2));
2785 } 2728 }
2786 } 2729 }
2787 2730
2788 2731
2789 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value, 2732 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
2790 Register scratch1, Register scratch2) { 2733 Register scratch1, Register scratch2) {
2791 DCHECK(value > 0); 2734 DCHECK(value > 0);
2792 if (FLAG_native_code_counters && counter->Enabled()) { 2735 if (FLAG_native_code_counters && counter->Enabled()) {
2793 mov(scratch2, Operand(ExternalReference(counter))); 2736 mov(scratch2, Operand(ExternalReference(counter)));
2794 ldr(scratch1, MemOperand(scratch2)); 2737 lwz(scratch1, MemOperand(scratch2));
2795 add(scratch1, scratch1, Operand(value)); 2738 addi(scratch1, scratch1, Operand(value));
2796 str(scratch1, MemOperand(scratch2)); 2739 stw(scratch1, MemOperand(scratch2));
2797 } 2740 }
2798 } 2741 }
2799 2742
2800 2743
2801 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value, 2744 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
2802 Register scratch1, Register scratch2) { 2745 Register scratch1, Register scratch2) {
2803 DCHECK(value > 0); 2746 DCHECK(value > 0);
2804 if (FLAG_native_code_counters && counter->Enabled()) { 2747 if (FLAG_native_code_counters && counter->Enabled()) {
2805 mov(scratch2, Operand(ExternalReference(counter))); 2748 mov(scratch2, Operand(ExternalReference(counter)));
2806 ldr(scratch1, MemOperand(scratch2)); 2749 lwz(scratch1, MemOperand(scratch2));
2807 sub(scratch1, scratch1, Operand(value)); 2750 subi(scratch1, scratch1, Operand(value));
2808 str(scratch1, MemOperand(scratch2)); 2751 stw(scratch1, MemOperand(scratch2));
2809 } 2752 }
2810 } 2753 }
2811 2754
2812 2755
2813 void MacroAssembler::Assert(Condition cond, BailoutReason reason) { 2756 void MacroAssembler::Assert(Condition cond, BailoutReason reason,
2757 CRegister cr) {
2814 if (emit_debug_code()) 2758 if (emit_debug_code())
2815 Check(cond, reason); 2759 Check(cond, reason, cr);
2816 } 2760 }
2817 2761
2818 2762
2819 void MacroAssembler::AssertFastElements(Register elements) { 2763 void MacroAssembler::AssertFastElements(Register elements) {
2820 if (emit_debug_code()) { 2764 if (emit_debug_code()) {
2821 DCHECK(!elements.is(ip)); 2765 DCHECK(!elements.is(ip));
2822 Label ok; 2766 Label ok;
2823 push(elements); 2767 push(elements);
2824 ldr(elements, FieldMemOperand(elements, HeapObject::kMapOffset)); 2768 LoadP(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
2825 LoadRoot(ip, Heap::kFixedArrayMapRootIndex); 2769 LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
2826 cmp(elements, ip); 2770 cmp(elements, ip);
2827 b(eq, &ok); 2771 beq(&ok);
2828 LoadRoot(ip, Heap::kFixedDoubleArrayMapRootIndex); 2772 LoadRoot(ip, Heap::kFixedDoubleArrayMapRootIndex);
2829 cmp(elements, ip); 2773 cmp(elements, ip);
2830 b(eq, &ok); 2774 beq(&ok);
2831 LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); 2775 LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
2832 cmp(elements, ip); 2776 cmp(elements, ip);
2833 b(eq, &ok); 2777 beq(&ok);
2834 Abort(kJSObjectWithFastElementsMapHasSlowElements); 2778 Abort(kJSObjectWithFastElementsMapHasSlowElements);
2835 bind(&ok); 2779 bind(&ok);
2836 pop(elements); 2780 pop(elements);
2837 } 2781 }
2838 } 2782 }
2839 2783
2840 2784
2841 void MacroAssembler::Check(Condition cond, BailoutReason reason) { 2785 void MacroAssembler::Check(Condition cond, BailoutReason reason, CRegister cr) {
2842 Label L; 2786 Label L;
2843 b(cond, &L); 2787 b(cond, &L, cr);
2844 Abort(reason); 2788 Abort(reason);
2845 // will not return here 2789 // will not return here
2846 bind(&L); 2790 bind(&L);
2847 } 2791 }
2848 2792
2849 2793
2850 void MacroAssembler::Abort(BailoutReason reason) { 2794 void MacroAssembler::Abort(BailoutReason reason) {
2851 Label abort_start; 2795 Label abort_start;
2852 bind(&abort_start); 2796 bind(&abort_start);
2853 #ifdef DEBUG 2797 #ifdef DEBUG
2854 const char* msg = GetBailoutReason(reason); 2798 const char* msg = GetBailoutReason(reason);
2855 if (msg != NULL) { 2799 if (msg != NULL) {
2856 RecordComment("Abort message: "); 2800 RecordComment("Abort message: ");
2857 RecordComment(msg); 2801 RecordComment(msg);
2858 } 2802 }
2859 2803
2860 if (FLAG_trap_on_abort) { 2804 if (FLAG_trap_on_abort) {
2861 stop(msg); 2805 stop(msg);
2862 return; 2806 return;
2863 } 2807 }
2864 #endif 2808 #endif
2865 2809
2866 mov(r0, Operand(Smi::FromInt(reason))); 2810 LoadSmiLiteral(r0, Smi::FromInt(reason));
2867 push(r0); 2811 push(r0);
2868
2869 // Disable stub call restrictions to always allow calls to abort. 2812 // Disable stub call restrictions to always allow calls to abort.
2870 if (!has_frame_) { 2813 if (!has_frame_) {
2871 // We don't actually want to generate a pile of code for this, so just 2814 // We don't actually want to generate a pile of code for this, so just
2872 // claim there is a stack frame, without generating one. 2815 // claim there is a stack frame, without generating one.
2873 FrameScope scope(this, StackFrame::NONE); 2816 FrameScope scope(this, StackFrame::NONE);
2874 CallRuntime(Runtime::kAbort, 1); 2817 CallRuntime(Runtime::kAbort, 1);
2875 } else { 2818 } else {
2876 CallRuntime(Runtime::kAbort, 1); 2819 CallRuntime(Runtime::kAbort, 1);
2877 } 2820 }
2878 // will not return here 2821 // will not return here
2879 if (is_const_pool_blocked()) {
2880 // If the calling code cares about the exact number of
2881 // instructions generated, we insert padding here to keep the size
2882 // of the Abort macro constant.
2883 static const int kExpectedAbortInstructions = 7;
2884 int abort_instructions = InstructionsGeneratedSince(&abort_start);
2885 DCHECK(abort_instructions <= kExpectedAbortInstructions);
2886 while (abort_instructions++ < kExpectedAbortInstructions) {
2887 nop();
2888 }
2889 }
2890 } 2822 }
2891 2823
2892 2824
2893 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { 2825 void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
2894 if (context_chain_length > 0) { 2826 if (context_chain_length > 0) {
2895 // Move up the chain of contexts to the context containing the slot. 2827 // Move up the chain of contexts to the context containing the slot.
2896 ldr(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX))); 2828 LoadP(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2897 for (int i = 1; i < context_chain_length; i++) { 2829 for (int i = 1; i < context_chain_length; i++) {
2898 ldr(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX))); 2830 LoadP(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2899 } 2831 }
2900 } else { 2832 } else {
2901 // Slot is in the current function context. Move it into the 2833 // Slot is in the current function context. Move it into the
2902 // destination register in case we store into it (the write barrier 2834 // destination register in case we store into it (the write barrier
2903 // cannot be allowed to destroy the context in esi). 2835 // cannot be allowed to destroy the context in esi).
2904 mov(dst, cp); 2836 mr(dst, cp);
2905 } 2837 }
2906 } 2838 }
2907 2839
2908 2840
2909 void MacroAssembler::LoadTransitionedArrayMapConditional( 2841 void MacroAssembler::LoadTransitionedArrayMapConditional(
2910 ElementsKind expected_kind, 2842 ElementsKind expected_kind,
2911 ElementsKind transitioned_kind, 2843 ElementsKind transitioned_kind,
2912 Register map_in_out, 2844 Register map_in_out,
2913 Register scratch, 2845 Register scratch,
2914 Label* no_map_match) { 2846 Label* no_map_match) {
2915 // Load the global or builtins object from the current context. 2847 // Load the global or builtins object from the current context.
2916 ldr(scratch, 2848 LoadP(scratch,
2917 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 2849 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
2918 ldr(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); 2850 LoadP(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset));
2919 2851
2920 // Check that the function's map is the same as the expected cached map. 2852 // Check that the function's map is the same as the expected cached map.
2921 ldr(scratch, 2853 LoadP(scratch,
2922 MemOperand(scratch, 2854 MemOperand(scratch,
2923 Context::SlotOffset(Context::JS_ARRAY_MAPS_INDEX))); 2855 Context::SlotOffset(Context::JS_ARRAY_MAPS_INDEX)));
2924 size_t offset = expected_kind * kPointerSize + 2856 size_t offset = expected_kind * kPointerSize +
2925 FixedArrayBase::kHeaderSize; 2857 FixedArrayBase::kHeaderSize;
2926 ldr(ip, FieldMemOperand(scratch, offset)); 2858 LoadP(ip, FieldMemOperand(scratch, offset));
2927 cmp(map_in_out, ip); 2859 cmp(map_in_out, ip);
2928 b(ne, no_map_match); 2860 bne(no_map_match);
2929 2861
2930 // Use the transitioned cached map. 2862 // Use the transitioned cached map.
2931 offset = transitioned_kind * kPointerSize + 2863 offset = transitioned_kind * kPointerSize +
2932 FixedArrayBase::kHeaderSize; 2864 FixedArrayBase::kHeaderSize;
2933 ldr(map_in_out, FieldMemOperand(scratch, offset)); 2865 LoadP(map_in_out, FieldMemOperand(scratch, offset));
2934 } 2866 }
2935 2867
2936 2868
2937 void MacroAssembler::LoadGlobalFunction(int index, Register function) { 2869 void MacroAssembler::LoadGlobalFunction(int index, Register function) {
2938 // Load the global or builtins object from the current context. 2870 // Load the global or builtins object from the current context.
2939 ldr(function, 2871 LoadP(function,
2940 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 2872 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
2941 // Load the native context from the global or builtins object. 2873 // Load the native context from the global or builtins object.
2942 ldr(function, FieldMemOperand(function, 2874 LoadP(function, FieldMemOperand(function,
2943 GlobalObject::kNativeContextOffset)); 2875 GlobalObject::kNativeContextOffset));
2944 // Load the function from the native context. 2876 // Load the function from the native context.
2945 ldr(function, MemOperand(function, Context::SlotOffset(index))); 2877 LoadP(function, MemOperand(function, Context::SlotOffset(index)), r0);
2946 } 2878 }
2947 2879
2948 2880
2949 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, 2881 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
2950 Register map, 2882 Register map,
2951 Register scratch) { 2883 Register scratch) {
2952 // Load the initial map. The global functions all have initial maps. 2884 // Load the initial map. The global functions all have initial maps.
2953 ldr(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 2885 LoadP(map,
2886 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2954 if (emit_debug_code()) { 2887 if (emit_debug_code()) {
2955 Label ok, fail; 2888 Label ok, fail;
2956 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK); 2889 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
2957 b(&ok); 2890 b(&ok);
2958 bind(&fail); 2891 bind(&fail);
2959 Abort(kGlobalFunctionsMustHaveInitialMap); 2892 Abort(kGlobalFunctionsMustHaveInitialMap);
2960 bind(&ok); 2893 bind(&ok);
2961 } 2894 }
2962 } 2895 }
2963 2896
2964 2897
2965 void MacroAssembler::JumpIfNotPowerOfTwoOrZero( 2898 void MacroAssembler::JumpIfNotPowerOfTwoOrZero(
2966 Register reg, 2899 Register reg,
2967 Register scratch, 2900 Register scratch,
2968 Label* not_power_of_two_or_zero) { 2901 Label* not_power_of_two_or_zero) {
2969 sub(scratch, reg, Operand(1), SetCC); 2902 subi(scratch, reg, Operand(1));
2970 b(mi, not_power_of_two_or_zero); 2903 cmpi(scratch, Operand::Zero());
2971 tst(scratch, reg); 2904 blt(not_power_of_two_or_zero);
2972 b(ne, not_power_of_two_or_zero); 2905 and_(r0, scratch, reg, SetRC);
2906 bne(not_power_of_two_or_zero, cr0);
2973 } 2907 }
2974 2908
2975 2909
2976 void MacroAssembler::JumpIfNotPowerOfTwoOrZeroAndNeg( 2910 void MacroAssembler::JumpIfNotPowerOfTwoOrZeroAndNeg(
2977 Register reg, 2911 Register reg,
2978 Register scratch, 2912 Register scratch,
2979 Label* zero_and_neg, 2913 Label* zero_and_neg,
2980 Label* not_power_of_two) { 2914 Label* not_power_of_two) {
2981 sub(scratch, reg, Operand(1), SetCC); 2915 subi(scratch, reg, Operand(1));
2982 b(mi, zero_and_neg); 2916 cmpi(scratch, Operand::Zero());
2983 tst(scratch, reg); 2917 blt(zero_and_neg);
2984 b(ne, not_power_of_two); 2918 and_(r0, scratch, reg, SetRC);
2919 bne(not_power_of_two, cr0);
2985 } 2920 }
2986 2921
2922 #if !V8_TARGET_ARCH_PPC64
2923 void MacroAssembler::SmiTagCheckOverflow(Register reg, Register overflow) {
2924 DCHECK(!reg.is(overflow));
2925 mr(overflow, reg); // Save original value.
2926 SmiTag(reg);
2927 xor_(overflow, overflow, reg, SetRC); // Overflow if (value ^ 2 * value) < 0.
2928 }
2929
2930
2931 void MacroAssembler::SmiTagCheckOverflow(Register dst,
2932 Register src,
2933 Register overflow) {
2934 if (dst.is(src)) {
2935 // Fall back to slower case.
2936 SmiTagCheckOverflow(dst, overflow);
2937 } else {
2938 DCHECK(!dst.is(src));
2939 DCHECK(!dst.is(overflow));
2940 DCHECK(!src.is(overflow));
2941 SmiTag(dst, src);
2942 xor_(overflow, dst, src, SetRC); // Overflow if (value ^ 2 * value) < 0.
2943 }
2944 }
2945 #endif
2987 2946
2988 void MacroAssembler::JumpIfNotBothSmi(Register reg1, 2947 void MacroAssembler::JumpIfNotBothSmi(Register reg1,
2989 Register reg2, 2948 Register reg2,
2990 Label* on_not_both_smi) { 2949 Label* on_not_both_smi) {
2991 STATIC_ASSERT(kSmiTag == 0); 2950 STATIC_ASSERT(kSmiTag == 0);
2992 tst(reg1, Operand(kSmiTagMask)); 2951 DCHECK_EQ(1, static_cast<int>(kSmiTagMask));
2993 tst(reg2, Operand(kSmiTagMask), eq); 2952 orx(r0, reg1, reg2, LeaveRC);
2994 b(ne, on_not_both_smi); 2953 JumpIfNotSmi(r0, on_not_both_smi);
2995 } 2954 }
2996 2955
2997 2956
2998 void MacroAssembler::UntagAndJumpIfSmi( 2957 void MacroAssembler::UntagAndJumpIfSmi(
2999 Register dst, Register src, Label* smi_case) { 2958 Register dst, Register src, Label* smi_case) {
3000 STATIC_ASSERT(kSmiTag == 0); 2959 STATIC_ASSERT(kSmiTag == 0);
3001 SmiUntag(dst, src, SetCC); 2960 STATIC_ASSERT(kSmiTagSize == 1);
3002 b(cc, smi_case); // Shifter carry is not set for a smi. 2961 TestBit(src, 0, r0);
2962 SmiUntag(dst, src);
2963 beq(smi_case, cr0);
3003 } 2964 }
3004 2965
3005 2966
3006 void MacroAssembler::UntagAndJumpIfNotSmi( 2967 void MacroAssembler::UntagAndJumpIfNotSmi(
3007 Register dst, Register src, Label* non_smi_case) { 2968 Register dst, Register src, Label* non_smi_case) {
3008 STATIC_ASSERT(kSmiTag == 0); 2969 STATIC_ASSERT(kSmiTag == 0);
3009 SmiUntag(dst, src, SetCC); 2970 STATIC_ASSERT(kSmiTagSize == 1);
3010 b(cs, non_smi_case); // Shifter carry is set for a non-smi. 2971 TestBit(src, 0, r0);
2972 SmiUntag(dst, src);
2973 bne(non_smi_case, cr0);
3011 } 2974 }
3012 2975
3013 2976
3014 void MacroAssembler::JumpIfEitherSmi(Register reg1, 2977 void MacroAssembler::JumpIfEitherSmi(Register reg1,
3015 Register reg2, 2978 Register reg2,
3016 Label* on_either_smi) { 2979 Label* on_either_smi) {
3017 STATIC_ASSERT(kSmiTag == 0); 2980 STATIC_ASSERT(kSmiTag == 0);
3018 tst(reg1, Operand(kSmiTagMask)); 2981 JumpIfSmi(reg1, on_either_smi);
3019 tst(reg2, Operand(kSmiTagMask), ne); 2982 JumpIfSmi(reg2, on_either_smi);
3020 b(eq, on_either_smi);
3021 } 2983 }
3022 2984
3023 2985
3024 void MacroAssembler::AssertNotSmi(Register object) { 2986 void MacroAssembler::AssertNotSmi(Register object) {
3025 if (emit_debug_code()) { 2987 if (emit_debug_code()) {
3026 STATIC_ASSERT(kSmiTag == 0); 2988 STATIC_ASSERT(kSmiTag == 0);
3027 tst(object, Operand(kSmiTagMask)); 2989 TestIfSmi(object, r0);
3028 Check(ne, kOperandIsASmi); 2990 Check(ne, kOperandIsASmi, cr0);
3029 } 2991 }
3030 } 2992 }
3031 2993
3032 2994
3033 void MacroAssembler::AssertSmi(Register object) { 2995 void MacroAssembler::AssertSmi(Register object) {
3034 if (emit_debug_code()) { 2996 if (emit_debug_code()) {
3035 STATIC_ASSERT(kSmiTag == 0); 2997 STATIC_ASSERT(kSmiTag == 0);
3036 tst(object, Operand(kSmiTagMask)); 2998 TestIfSmi(object, r0);
3037 Check(eq, kOperandIsNotSmi); 2999 Check(eq, kOperandIsNotSmi, cr0);
3038 } 3000 }
3039 } 3001 }
3040 3002
3041 3003
3042 void MacroAssembler::AssertString(Register object) { 3004 void MacroAssembler::AssertString(Register object) {
3043 if (emit_debug_code()) { 3005 if (emit_debug_code()) {
3044 STATIC_ASSERT(kSmiTag == 0); 3006 STATIC_ASSERT(kSmiTag == 0);
3045 tst(object, Operand(kSmiTagMask)); 3007 TestIfSmi(object, r0);
3046 Check(ne, kOperandIsASmiAndNotAString); 3008 Check(ne, kOperandIsASmiAndNotAString, cr0);
3047 push(object); 3009 push(object);
3048 ldr(object, FieldMemOperand(object, HeapObject::kMapOffset)); 3010 LoadP(object, FieldMemOperand(object, HeapObject::kMapOffset));
3049 CompareInstanceType(object, object, FIRST_NONSTRING_TYPE); 3011 CompareInstanceType(object, object, FIRST_NONSTRING_TYPE);
3050 pop(object); 3012 pop(object);
3051 Check(lo, kOperandIsNotAString); 3013 Check(lt, kOperandIsNotAString);
3052 } 3014 }
3053 } 3015 }
3054 3016
3055 3017
3056 void MacroAssembler::AssertName(Register object) { 3018 void MacroAssembler::AssertName(Register object) {
3057 if (emit_debug_code()) { 3019 if (emit_debug_code()) {
3058 STATIC_ASSERT(kSmiTag == 0); 3020 STATIC_ASSERT(kSmiTag == 0);
3059 tst(object, Operand(kSmiTagMask)); 3021 TestIfSmi(object, r0);
3060 Check(ne, kOperandIsASmiAndNotAName); 3022 Check(ne, kOperandIsASmiAndNotAName, cr0);
3061 push(object); 3023 push(object);
3062 ldr(object, FieldMemOperand(object, HeapObject::kMapOffset)); 3024 LoadP(object, FieldMemOperand(object, HeapObject::kMapOffset));
3063 CompareInstanceType(object, object, LAST_NAME_TYPE); 3025 CompareInstanceType(object, object, LAST_NAME_TYPE);
3064 pop(object); 3026 pop(object);
3065 Check(le, kOperandIsNotAName); 3027 Check(le, kOperandIsNotAName);
3066 } 3028 }
3067 } 3029 }
3068 3030
3069 3031
3070 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object, 3032 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object,
3071 Register scratch) { 3033 Register scratch) {
3072 if (emit_debug_code()) { 3034 if (emit_debug_code()) {
3073 Label done_checking; 3035 Label done_checking;
3074 AssertNotSmi(object); 3036 AssertNotSmi(object);
3075 CompareRoot(object, Heap::kUndefinedValueRootIndex); 3037 CompareRoot(object, Heap::kUndefinedValueRootIndex);
3076 b(eq, &done_checking); 3038 beq(&done_checking);
3077 ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); 3039 LoadP(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
3078 CompareRoot(scratch, Heap::kAllocationSiteMapRootIndex); 3040 CompareRoot(scratch, Heap::kAllocationSiteMapRootIndex);
3079 Assert(eq, kExpectedUndefinedOrCell); 3041 Assert(eq, kExpectedUndefinedOrCell);
3080 bind(&done_checking); 3042 bind(&done_checking);
3081 } 3043 }
3082 } 3044 }
3083 3045
3084 3046
3085 void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) { 3047 void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) {
3086 if (emit_debug_code()) { 3048 if (emit_debug_code()) {
3087 CompareRoot(reg, index); 3049 CompareRoot(reg, index);
3088 Check(eq, kHeapNumberMapRegisterClobbered); 3050 Check(eq, kHeapNumberMapRegisterClobbered);
3089 } 3051 }
3090 } 3052 }
3091 3053
3092 3054
3093 void MacroAssembler::JumpIfNotHeapNumber(Register object, 3055 void MacroAssembler::JumpIfNotHeapNumber(Register object,
3094 Register heap_number_map, 3056 Register heap_number_map,
3095 Register scratch, 3057 Register scratch,
3096 Label* on_not_heap_number) { 3058 Label* on_not_heap_number) {
3097 ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); 3059 LoadP(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
3098 AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 3060 AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
3099 cmp(scratch, heap_number_map); 3061 cmp(scratch, heap_number_map);
3100 b(ne, on_not_heap_number); 3062 bne(on_not_heap_number);
3101 } 3063 }
3102 3064
3103 3065
3104 void MacroAssembler::LookupNumberStringCache(Register object, 3066 void MacroAssembler::LookupNumberStringCache(Register object,
3105 Register result, 3067 Register result,
3106 Register scratch1, 3068 Register scratch1,
3107 Register scratch2, 3069 Register scratch2,
3108 Register scratch3, 3070 Register scratch3,
3109 Label* not_found) { 3071 Label* not_found) {
3110 // Use of registers. Register result is used as a temporary. 3072 // Use of registers. Register result is used as a temporary.
3111 Register number_string_cache = result; 3073 Register number_string_cache = result;
3112 Register mask = scratch3; 3074 Register mask = scratch3;
3113 3075
3114 // Load the number string cache. 3076 // Load the number string cache.
3115 LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); 3077 LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
3116 3078
3117 // Make the hash mask from the length of the number string cache. It 3079 // Make the hash mask from the length of the number string cache. It
3118 // contains two elements (number and string) for each cache entry. 3080 // contains two elements (number and string) for each cache entry.
3119 ldr(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset)); 3081 LoadP(mask, FieldMemOperand(number_string_cache,
3082 FixedArray::kLengthOffset));
3120 // Divide length by two (length is a smi). 3083 // Divide length by two (length is a smi).
3121 mov(mask, Operand(mask, ASR, kSmiTagSize + 1)); 3084 ShiftRightArithImm(mask, mask, kSmiTagSize + kSmiShiftSize + 1);
3122 sub(mask, mask, Operand(1)); // Make mask. 3085 subi(mask, mask, Operand(1)); // Make mask.
3123 3086
3124 // Calculate the entry in the number string cache. The hash value in the 3087 // Calculate the entry in the number string cache. The hash value in the
3125 // number string cache for smis is just the smi value, and the hash for 3088 // number string cache for smis is just the smi value, and the hash for
3126 // doubles is the xor of the upper and lower words. See 3089 // doubles is the xor of the upper and lower words. See
3127 // Heap::GetNumberStringCache. 3090 // Heap::GetNumberStringCache.
3128 Label is_smi; 3091 Label is_smi;
3129 Label load_result_from_cache; 3092 Label load_result_from_cache;
3130 JumpIfSmi(object, &is_smi); 3093 JumpIfSmi(object, &is_smi);
3131 CheckMap(object, 3094 CheckMap(object,
3132 scratch1, 3095 scratch1,
3133 Heap::kHeapNumberMapRootIndex, 3096 Heap::kHeapNumberMapRootIndex,
3134 not_found, 3097 not_found,
3135 DONT_DO_SMI_CHECK); 3098 DONT_DO_SMI_CHECK);
3136 3099
3137 STATIC_ASSERT(8 == kDoubleSize); 3100 STATIC_ASSERT(8 == kDoubleSize);
3138 add(scratch1, 3101 lwz(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
3139 object, 3102 lwz(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset));
3140 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); 3103 xor_(scratch1, scratch1, scratch2);
3141 ldm(ia, scratch1, scratch1.bit() | scratch2.bit()); 3104 and_(scratch1, scratch1, mask);
3142 eor(scratch1, scratch1, Operand(scratch2));
3143 and_(scratch1, scratch1, Operand(mask));
3144 3105
3145 // Calculate address of entry in string cache: each entry consists 3106 // Calculate address of entry in string cache: each entry consists
3146 // of two pointer sized fields. 3107 // of two pointer sized fields.
3147 add(scratch1, 3108 ShiftLeftImm(scratch1, scratch1, Operand(kPointerSizeLog2 + 1));
3148 number_string_cache, 3109 add(scratch1, number_string_cache, scratch1);
3149 Operand(scratch1, LSL, kPointerSizeLog2 + 1));
3150 3110
3151 Register probe = mask; 3111 Register probe = mask;
3152 ldr(probe, FieldMemOperand(scratch1, FixedArray::kHeaderSize)); 3112 LoadP(probe, FieldMemOperand(scratch1, FixedArray::kHeaderSize));
3153 JumpIfSmi(probe, not_found); 3113 JumpIfSmi(probe, not_found);
3154 sub(scratch2, object, Operand(kHeapObjectTag)); 3114 lfd(d0, FieldMemOperand(object, HeapNumber::kValueOffset));
3155 vldr(d0, scratch2, HeapNumber::kValueOffset); 3115 lfd(d1, FieldMemOperand(probe, HeapNumber::kValueOffset));
3156 sub(probe, probe, Operand(kHeapObjectTag)); 3116 fcmpu(d0, d1);
3157 vldr(d1, probe, HeapNumber::kValueOffset); 3117 bne(not_found); // The cache did not contain this value.
3158 VFPCompareAndSetFlags(d0, d1);
3159 b(ne, not_found); // The cache did not contain this value.
3160 b(&load_result_from_cache); 3118 b(&load_result_from_cache);
3161 3119
3162 bind(&is_smi); 3120 bind(&is_smi);
3163 Register scratch = scratch1; 3121 Register scratch = scratch1;
3164 and_(scratch, mask, Operand(object, ASR, 1)); 3122 SmiUntag(scratch, object);
3123 and_(scratch, mask, scratch);
3165 // Calculate address of entry in string cache: each entry consists 3124 // Calculate address of entry in string cache: each entry consists
3166 // of two pointer sized fields. 3125 // of two pointer sized fields.
3167 add(scratch, 3126 ShiftLeftImm(scratch, scratch, Operand(kPointerSizeLog2 + 1));
3168 number_string_cache, 3127 add(scratch, number_string_cache, scratch);
3169 Operand(scratch, LSL, kPointerSizeLog2 + 1));
3170 3128
3171 // Check if the entry is the smi we are looking for. 3129 // Check if the entry is the smi we are looking for.
3172 ldr(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize)); 3130 LoadP(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize));
3173 cmp(object, probe); 3131 cmp(object, probe);
3174 b(ne, not_found); 3132 bne(not_found);
3175 3133
3176 // Get the result from the cache. 3134 // Get the result from the cache.
3177 bind(&load_result_from_cache); 3135 bind(&load_result_from_cache);
3178 ldr(result, FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize)); 3136 LoadP(result,
3137 FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize));
3179 IncrementCounter(isolate()->counters()->number_to_string_native(), 3138 IncrementCounter(isolate()->counters()->number_to_string_native(),
3180 1, 3139 1,
3181 scratch1, 3140 scratch1,
3182 scratch2); 3141 scratch2);
3183 } 3142 }
3184 3143
3185 3144
3186 void MacroAssembler::JumpIfNonSmisNotBothSequentialAsciiStrings( 3145 void MacroAssembler::JumpIfNonSmisNotBothSequentialAsciiStrings(
3187 Register first, 3146 Register first,
3188 Register second, 3147 Register second,
3189 Register scratch1, 3148 Register scratch1,
3190 Register scratch2, 3149 Register scratch2,
3191 Label* failure) { 3150 Label* failure) {
3192 // Test that both first and second are sequential ASCII strings. 3151 // Test that both first and second are sequential ASCII strings.
3193 // Assume that they are non-smis. 3152 // Assume that they are non-smis.
3194 ldr(scratch1, FieldMemOperand(first, HeapObject::kMapOffset)); 3153 LoadP(scratch1, FieldMemOperand(first, HeapObject::kMapOffset));
3195 ldr(scratch2, FieldMemOperand(second, HeapObject::kMapOffset)); 3154 LoadP(scratch2, FieldMemOperand(second, HeapObject::kMapOffset));
3196 ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); 3155 lbz(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
3197 ldrb(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset)); 3156 lbz(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset));
3198 3157
3199 JumpIfBothInstanceTypesAreNotSequentialAscii(scratch1, 3158 JumpIfBothInstanceTypesAreNotSequentialAscii(scratch1,
3200 scratch2, 3159 scratch2,
3201 scratch1, 3160 scratch1,
3202 scratch2, 3161 scratch2,
3203 failure); 3162 failure);
3204 } 3163 }
3205 3164
3206 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first, 3165 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first,
3207 Register second, 3166 Register second,
3208 Register scratch1, 3167 Register scratch1,
3209 Register scratch2, 3168 Register scratch2,
3210 Label* failure) { 3169 Label* failure) {
3211 // Check that neither is a smi. 3170 // Check that neither is a smi.
3212 and_(scratch1, first, Operand(second)); 3171 and_(scratch1, first, second);
3213 JumpIfSmi(scratch1, failure); 3172 JumpIfSmi(scratch1, failure);
3214 JumpIfNonSmisNotBothSequentialAsciiStrings(first, 3173 JumpIfNonSmisNotBothSequentialAsciiStrings(first,
3215 second, 3174 second,
3216 scratch1, 3175 scratch1,
3217 scratch2, 3176 scratch2,
3218 failure); 3177 failure);
3219 } 3178 }
3220 3179
3221 3180
3222 void MacroAssembler::JumpIfNotUniqueName(Register reg, 3181 void MacroAssembler::JumpIfNotUniqueName(Register reg,
3223 Label* not_unique_name) { 3182 Label* not_unique_name) {
3224 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 3183 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
3225 Label succeed; 3184 Label succeed;
3226 tst(reg, Operand(kIsNotStringMask | kIsNotInternalizedMask)); 3185 andi(r0, reg, Operand(kIsNotStringMask | kIsNotInternalizedMask));
3227 b(eq, &succeed); 3186 beq(&succeed, cr0);
3228 cmp(reg, Operand(SYMBOL_TYPE)); 3187 cmpi(reg, Operand(SYMBOL_TYPE));
3229 b(ne, not_unique_name); 3188 bne(not_unique_name);
3230 3189
3231 bind(&succeed); 3190 bind(&succeed);
3232 } 3191 }
3233 3192
3234 3193
3235 // Allocates a heap number or jumps to the need_gc label if the young space 3194 // Allocates a heap number or jumps to the need_gc label if the young space
3236 // is full and a scavenge is needed. 3195 // is full and a scavenge is needed.
3237 void MacroAssembler::AllocateHeapNumber(Register result, 3196 void MacroAssembler::AllocateHeapNumber(Register result,
3238 Register scratch1, 3197 Register scratch1,
3239 Register scratch2, 3198 Register scratch2,
3240 Register heap_number_map, 3199 Register heap_number_map,
3241 Label* gc_required, 3200 Label* gc_required,
3242 TaggingMode tagging_mode, 3201 TaggingMode tagging_mode,
3243 MutableMode mode) { 3202 MutableMode mode) {
3244 // Allocate an object in the heap for the heap number and tag it as a heap 3203 // Allocate an object in the heap for the heap number and tag it as a heap
3245 // object. 3204 // object.
3246 Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required, 3205 Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
3247 tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS); 3206 tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS);
3248 3207
3249 Heap::RootListIndex map_index = mode == MUTABLE 3208 Heap::RootListIndex map_index = mode == MUTABLE
3250 ? Heap::kMutableHeapNumberMapRootIndex 3209 ? Heap::kMutableHeapNumberMapRootIndex
3251 : Heap::kHeapNumberMapRootIndex; 3210 : Heap::kHeapNumberMapRootIndex;
3252 AssertIsRoot(heap_number_map, map_index); 3211 AssertIsRoot(heap_number_map, map_index);
3253 3212
3254 // Store heap number map in the allocated object. 3213 // Store heap number map in the allocated object.
3255 if (tagging_mode == TAG_RESULT) { 3214 if (tagging_mode == TAG_RESULT) {
3256 str(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset)); 3215 StoreP(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset),
3216 r0);
3257 } else { 3217 } else {
3258 str(heap_number_map, MemOperand(result, HeapObject::kMapOffset)); 3218 StoreP(heap_number_map, MemOperand(result, HeapObject::kMapOffset));
3259 } 3219 }
3260 } 3220 }
3261 3221
3262 3222
3263 void MacroAssembler::AllocateHeapNumberWithValue(Register result, 3223 void MacroAssembler::AllocateHeapNumberWithValue(Register result,
3264 DwVfpRegister value, 3224 DoubleRegister value,
3265 Register scratch1, 3225 Register scratch1,
3266 Register scratch2, 3226 Register scratch2,
3267 Register heap_number_map, 3227 Register heap_number_map,
3268 Label* gc_required) { 3228 Label* gc_required) {
3269 AllocateHeapNumber(result, scratch1, scratch2, heap_number_map, gc_required); 3229 AllocateHeapNumber(result, scratch1, scratch2, heap_number_map, gc_required);
3270 sub(scratch1, result, Operand(kHeapObjectTag)); 3230 stfd(value, FieldMemOperand(result, HeapNumber::kValueOffset));
3271 vstr(value, scratch1, HeapNumber::kValueOffset);
3272 } 3231 }
3273 3232
3274 3233
3275 // Copies a fixed number of fields of heap objects from src to dst. 3234 // Copies a fixed number of fields of heap objects from src to dst.
3276 void MacroAssembler::CopyFields(Register dst, 3235 void MacroAssembler::CopyFields(Register dst,
3277 Register src, 3236 Register src,
3278 LowDwVfpRegister double_scratch, 3237 RegList temps,
3279 int field_count) { 3238 int field_count) {
3280 int double_count = field_count / (DwVfpRegister::kSizeInBytes / kPointerSize); 3239 // At least one bit set in the first 15 registers.
3281 for (int i = 0; i < double_count; i++) { 3240 DCHECK((temps & ((1 << 15) - 1)) != 0);
3282 vldr(double_scratch, FieldMemOperand(src, i * DwVfpRegister::kSizeInBytes)); 3241 DCHECK((temps & dst.bit()) == 0);
3283 vstr(double_scratch, FieldMemOperand(dst, i * DwVfpRegister::kSizeInBytes)); 3242 DCHECK((temps & src.bit()) == 0);
3243 // Primitive implementation using only one temporary register.
3244
3245 Register tmp = no_reg;
3246 // Find a temp register in temps list.
3247 for (int i = 0; i < 15; i++) {
3248 if ((temps & (1 << i)) != 0) {
3249 tmp.set_code(i);
3250 break;
3251 }
3284 } 3252 }
3253 DCHECK(!tmp.is(no_reg));
3285 3254
3286 STATIC_ASSERT(SwVfpRegister::kSizeInBytes == kPointerSize); 3255 for (int i = 0; i < field_count; i++) {
3287 STATIC_ASSERT(2 * SwVfpRegister::kSizeInBytes == DwVfpRegister::kSizeInBytes); 3256 LoadP(tmp, FieldMemOperand(src, i * kPointerSize), r0);
3288 3257 StoreP(tmp, FieldMemOperand(dst, i * kPointerSize), r0);
3289 int remain = field_count % (DwVfpRegister::kSizeInBytes / kPointerSize);
3290 if (remain != 0) {
3291 vldr(double_scratch.low(),
3292 FieldMemOperand(src, (field_count - 1) * kPointerSize));
3293 vstr(double_scratch.low(),
3294 FieldMemOperand(dst, (field_count - 1) * kPointerSize));
3295 } 3258 }
3296 } 3259 }
3297 3260
3298 3261
3299 void MacroAssembler::CopyBytes(Register src, 3262 void MacroAssembler::CopyBytes(Register src,
3300 Register dst, 3263 Register dst,
3301 Register length, 3264 Register length,
3302 Register scratch) { 3265 Register scratch) {
3303 Label align_loop_1, word_loop, byte_loop, byte_loop_1, done; 3266 Label align_loop, aligned, word_loop, byte_loop, byte_loop_1, done;
3267
3268 DCHECK(!scratch.is(r0));
3269
3270 cmpi(length, Operand::Zero());
3271 beq(&done);
3272
3273 // Check src alignment and length to see whether word_loop is possible
3274 andi(scratch, src, Operand(kPointerSize - 1));
3275 beq(&aligned, cr0);
3276 subfic(scratch, scratch, Operand(kPointerSize * 2));
3277 cmp(length, scratch);
3278 blt(&byte_loop);
3304 3279
3305 // Align src before copying in word size chunks. 3280 // Align src before copying in word size chunks.
3306 cmp(length, Operand(kPointerSize)); 3281 subi(scratch, scratch, Operand(kPointerSize));
3307 b(le, &byte_loop); 3282 mtctr(scratch);
3283 bind(&align_loop);
3284 lbz(scratch, MemOperand(src));
3285 addi(src, src, Operand(1));
3286 subi(length, length, Operand(1));
3287 stb(scratch, MemOperand(dst));
3288 addi(dst, dst, Operand(1));
3289 bdnz(&align_loop);
3308 3290
3309 bind(&align_loop_1); 3291 bind(&aligned);
3310 tst(src, Operand(kPointerSize - 1)); 3292
3311 b(eq, &word_loop);
3312 ldrb(scratch, MemOperand(src, 1, PostIndex));
3313 strb(scratch, MemOperand(dst, 1, PostIndex));
3314 sub(length, length, Operand(1), SetCC);
3315 b(&align_loop_1);
3316 // Copy bytes in word size chunks. 3293 // Copy bytes in word size chunks.
3294 if (emit_debug_code()) {
3295 andi(r0, src, Operand(kPointerSize - 1));
3296 Assert(eq, kExpectingAlignmentForCopyBytes, cr0);
3297 }
3298
3299 ShiftRightImm(scratch, length, Operand(kPointerSizeLog2));
3300 cmpi(scratch, Operand::Zero());
3301 beq(&byte_loop);
3302
3303 mtctr(scratch);
3317 bind(&word_loop); 3304 bind(&word_loop);
3318 if (emit_debug_code()) { 3305 LoadP(scratch, MemOperand(src));
3319 tst(src, Operand(kPointerSize - 1)); 3306 addi(src, src, Operand(kPointerSize));
3320 Assert(eq, kExpectingAlignmentForCopyBytes); 3307 subi(length, length, Operand(kPointerSize));
3308 if (CpuFeatures::IsSupported(UNALIGNED_ACCESSES)) {
3309 // currently false for PPC - but possible future opt
3310 StoreP(scratch, MemOperand(dst));
3311 addi(dst, dst, Operand(kPointerSize));
3312 } else {
3313 #if V8_TARGET_LITTLE_ENDIAN
3314 stb(scratch, MemOperand(dst, 0));
3315 ShiftRightImm(scratch, scratch, Operand(8));
3316 stb(scratch, MemOperand(dst, 1));
3317 ShiftRightImm(scratch, scratch, Operand(8));
3318 stb(scratch, MemOperand(dst, 2));
3319 ShiftRightImm(scratch, scratch, Operand(8));
3320 stb(scratch, MemOperand(dst, 3));
3321 #if V8_TARGET_ARCH_PPC64
3322 ShiftRightImm(scratch, scratch, Operand(8));
3323 stb(scratch, MemOperand(dst, 4));
3324 ShiftRightImm(scratch, scratch, Operand(8));
3325 stb(scratch, MemOperand(dst, 5));
3326 ShiftRightImm(scratch, scratch, Operand(8));
3327 stb(scratch, MemOperand(dst, 6));
3328 ShiftRightImm(scratch, scratch, Operand(8));
3329 stb(scratch, MemOperand(dst, 7));
3330 #endif
3331 #else
3332 #if V8_TARGET_ARCH_PPC64
3333 stb(scratch, MemOperand(dst, 7));
3334 ShiftRightImm(scratch, scratch, Operand(8));
3335 stb(scratch, MemOperand(dst, 6));
3336 ShiftRightImm(scratch, scratch, Operand(8));
3337 stb(scratch, MemOperand(dst, 5));
3338 ShiftRightImm(scratch, scratch, Operand(8));
3339 stb(scratch, MemOperand(dst, 4));
3340 ShiftRightImm(scratch, scratch, Operand(8));
3341 #endif
3342 stb(scratch, MemOperand(dst, 3));
3343 ShiftRightImm(scratch, scratch, Operand(8));
3344 stb(scratch, MemOperand(dst, 2));
3345 ShiftRightImm(scratch, scratch, Operand(8));
3346 stb(scratch, MemOperand(dst, 1));
3347 ShiftRightImm(scratch, scratch, Operand(8));
3348 stb(scratch, MemOperand(dst, 0));
3349 #endif
3350 addi(dst, dst, Operand(kPointerSize));
3321 } 3351 }
3322 cmp(length, Operand(kPointerSize)); 3352 bdnz(&word_loop);
3323 b(lt, &byte_loop);
3324 ldr(scratch, MemOperand(src, kPointerSize, PostIndex));
3325 if (CpuFeatures::IsSupported(UNALIGNED_ACCESSES)) {
3326 str(scratch, MemOperand(dst, kPointerSize, PostIndex));
3327 } else {
3328 strb(scratch, MemOperand(dst, 1, PostIndex));
3329 mov(scratch, Operand(scratch, LSR, 8));
3330 strb(scratch, MemOperand(dst, 1, PostIndex));
3331 mov(scratch, Operand(scratch, LSR, 8));
3332 strb(scratch, MemOperand(dst, 1, PostIndex));
3333 mov(scratch, Operand(scratch, LSR, 8));
3334 strb(scratch, MemOperand(dst, 1, PostIndex));
3335 }
3336 sub(length, length, Operand(kPointerSize));
3337 b(&word_loop);
3338 3353
3339 // Copy the last bytes if any left. 3354 // Copy the last bytes if any left.
3355 cmpi(length, Operand::Zero());
3356 beq(&done);
3357
3340 bind(&byte_loop); 3358 bind(&byte_loop);
3341 cmp(length, Operand::Zero()); 3359 mtctr(length);
3342 b(eq, &done);
3343 bind(&byte_loop_1); 3360 bind(&byte_loop_1);
3344 ldrb(scratch, MemOperand(src, 1, PostIndex)); 3361 lbz(scratch, MemOperand(src));
3345 strb(scratch, MemOperand(dst, 1, PostIndex)); 3362 addi(src, src, Operand(1));
3346 sub(length, length, Operand(1), SetCC); 3363 stb(scratch, MemOperand(dst));
3347 b(ne, &byte_loop_1); 3364 addi(dst, dst, Operand(1));
3365 bdnz(&byte_loop_1);
3366
3348 bind(&done); 3367 bind(&done);
3349 } 3368 }
3350 3369
3351 3370
3371 void MacroAssembler::InitializeNFieldsWithFiller(Register start_offset,
3372 Register count,
3373 Register filler) {
3374 Label loop;
3375 mtctr(count);
3376 bind(&loop);
3377 StoreP(filler, MemOperand(start_offset));
3378 addi(start_offset, start_offset, Operand(kPointerSize));
3379 bdnz(&loop);
3380 }
3381
3352 void MacroAssembler::InitializeFieldsWithFiller(Register start_offset, 3382 void MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
3353 Register end_offset, 3383 Register end_offset,
3354 Register filler) { 3384 Register filler) {
3355 Label loop, entry; 3385 Label done;
3356 b(&entry); 3386 sub(r0, end_offset, start_offset, LeaveOE, SetRC);
3357 bind(&loop); 3387 beq(&done, cr0);
3358 str(filler, MemOperand(start_offset, kPointerSize, PostIndex)); 3388 ShiftRightImm(r0, r0, Operand(kPointerSizeLog2));
3359 bind(&entry); 3389 InitializeNFieldsWithFiller(start_offset, r0, filler);
3360 cmp(start_offset, end_offset); 3390 bind(&done);
3361 b(lt, &loop);
3362 } 3391 }
3363 3392
3364 3393
3365 void MacroAssembler::CheckFor32DRegs(Register scratch) { 3394 void MacroAssembler::SaveFPRegs(Register location, int first, int count) {
3366 mov(scratch, Operand(ExternalReference::cpu_features())); 3395 DCHECK(count > 0);
3367 ldr(scratch, MemOperand(scratch)); 3396 int cur = first;
3368 tst(scratch, Operand(1u << VFP32DREGS)); 3397 subi(location, location, Operand(count * kDoubleSize));
3398 for (int i = 0; i < count; i++) {
3399 DoubleRegister reg = DoubleRegister::from_code(cur++);
3400 stfd(reg, MemOperand(location, i * kDoubleSize));
3401 }
3369 } 3402 }
3370 3403
3371 3404
3372 void MacroAssembler::SaveFPRegs(Register location, Register scratch) { 3405 void MacroAssembler::RestoreFPRegs(Register location, int first, int count) {
3373 CheckFor32DRegs(scratch); 3406 DCHECK(count > 0);
3374 vstm(db_w, location, d16, d31, ne); 3407 int cur = first + count - 1;
3375 sub(location, location, Operand(16 * kDoubleSize), LeaveCC, eq); 3408 for (int i = count - 1; i >= 0; i--) {
3376 vstm(db_w, location, d0, d15); 3409 DoubleRegister reg = DoubleRegister::from_code(cur--);
3410 lfd(reg, MemOperand(location, i * kDoubleSize));
3411 }
3412 addi(location, location, Operand(count * kDoubleSize));
3377 } 3413 }
3378 3414
3379 3415
3380 void MacroAssembler::RestoreFPRegs(Register location, Register scratch) {
3381 CheckFor32DRegs(scratch);
3382 vldm(ia_w, location, d0, d15);
3383 vldm(ia_w, location, d16, d31, ne);
3384 add(location, location, Operand(16 * kDoubleSize), LeaveCC, eq);
3385 }
3386
3387
3388 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii( 3416 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii(
3389 Register first, 3417 Register first,
3390 Register second, 3418 Register second,
3391 Register scratch1, 3419 Register scratch1,
3392 Register scratch2, 3420 Register scratch2,
3393 Label* failure) { 3421 Label* failure) {
3394 const int kFlatAsciiStringMask = 3422 const int kFlatAsciiStringMask =
3395 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; 3423 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
3396 const int kFlatAsciiStringTag = 3424 const int kFlatAsciiStringTag =
3397 kStringTag | kOneByteStringTag | kSeqStringTag; 3425 kStringTag | kOneByteStringTag | kSeqStringTag;
3398 and_(scratch1, first, Operand(kFlatAsciiStringMask)); 3426 andi(scratch1, first, Operand(kFlatAsciiStringMask));
3399 and_(scratch2, second, Operand(kFlatAsciiStringMask)); 3427 andi(scratch2, second, Operand(kFlatAsciiStringMask));
3400 cmp(scratch1, Operand(kFlatAsciiStringTag)); 3428 cmpi(scratch1, Operand(kFlatAsciiStringTag));
3401 // Ignore second test if first test failed. 3429 bne(failure);
3402 cmp(scratch2, Operand(kFlatAsciiStringTag), eq); 3430 cmpi(scratch2, Operand(kFlatAsciiStringTag));
3403 b(ne, failure); 3431 bne(failure);
3404 } 3432 }
3405 3433
3406 3434
3407 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(Register type, 3435 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(Register type,
3408 Register scratch, 3436 Register scratch,
3409 Label* failure) { 3437 Label* failure) {
3410 const int kFlatAsciiStringMask = 3438 const int kFlatAsciiStringMask =
3411 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; 3439 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
3412 const int kFlatAsciiStringTag = 3440 const int kFlatAsciiStringTag =
3413 kStringTag | kOneByteStringTag | kSeqStringTag; 3441 kStringTag | kOneByteStringTag | kSeqStringTag;
3414 and_(scratch, type, Operand(kFlatAsciiStringMask)); 3442 andi(scratch, type, Operand(kFlatAsciiStringMask));
3415 cmp(scratch, Operand(kFlatAsciiStringTag)); 3443 cmpi(scratch, Operand(kFlatAsciiStringTag));
3416 b(ne, failure); 3444 bne(failure);
3417 } 3445 }
3418 3446
3419 static const int kRegisterPassedArguments = 4; 3447 static const int kRegisterPassedArguments = 8;
3420 3448
3421 3449
3422 int MacroAssembler::CalculateStackPassedWords(int num_reg_arguments, 3450 int MacroAssembler::CalculateStackPassedWords(int num_reg_arguments,
3423 int num_double_arguments) { 3451 int num_double_arguments) {
3424 int stack_passed_words = 0; 3452 int stack_passed_words = 0;
3425 if (use_eabi_hardfloat()) { 3453 if (num_double_arguments > DoubleRegister::kNumRegisters) {
3426 // In the hard floating point calling convention, we can use
3427 // all double registers to pass doubles.
3428 if (num_double_arguments > DoubleRegister::NumRegisters()) {
3429 stack_passed_words += 3454 stack_passed_words +=
3430 2 * (num_double_arguments - DoubleRegister::NumRegisters()); 3455 2 * (num_double_arguments - DoubleRegister::kNumRegisters);
3431 }
3432 } else {
3433 // In the soft floating point calling convention, every double
3434 // argument is passed using two registers.
3435 num_reg_arguments += 2 * num_double_arguments;
3436 } 3456 }
3437 // Up to four simple arguments are passed in registers r0..r3. 3457 // Up to 8 simple arguments are passed in registers r3..r10.
3438 if (num_reg_arguments > kRegisterPassedArguments) { 3458 if (num_reg_arguments > kRegisterPassedArguments) {
3439 stack_passed_words += num_reg_arguments - kRegisterPassedArguments; 3459 stack_passed_words += num_reg_arguments - kRegisterPassedArguments;
3440 } 3460 }
3441 return stack_passed_words; 3461 return stack_passed_words;
3442 } 3462 }
3443 3463
3444 3464
3445 void MacroAssembler::EmitSeqStringSetCharCheck(Register string, 3465 void MacroAssembler::EmitSeqStringSetCharCheck(Register string,
3446 Register index, 3466 Register index,
3447 Register value, 3467 Register value,
3448 uint32_t encoding_mask) { 3468 uint32_t encoding_mask) {
3449 Label is_object; 3469 Label is_object;
3450 SmiTst(string); 3470 TestIfSmi(string, r0);
3451 Check(ne, kNonObject); 3471 Check(ne, kNonObject, cr0);
3452 3472
3453 ldr(ip, FieldMemOperand(string, HeapObject::kMapOffset)); 3473 LoadP(ip, FieldMemOperand(string, HeapObject::kMapOffset));
3454 ldrb(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset)); 3474 lbz(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset));
3455 3475
3456 and_(ip, ip, Operand(kStringRepresentationMask | kStringEncodingMask)); 3476 andi(ip, ip, Operand(kStringRepresentationMask | kStringEncodingMask));
3457 cmp(ip, Operand(encoding_mask)); 3477 cmpi(ip, Operand(encoding_mask));
3458 Check(eq, kUnexpectedStringType); 3478 Check(eq, kUnexpectedStringType);
3459 3479
3460 // The index is assumed to be untagged coming in, tag it to compare with the 3480 // The index is assumed to be untagged coming in, tag it to compare with the
3461 // string length without using a temp register, it is restored at the end of 3481 // string length without using a temp register, it is restored at the end of
3462 // this function. 3482 // this function.
3483 #if !V8_TARGET_ARCH_PPC64
3463 Label index_tag_ok, index_tag_bad; 3484 Label index_tag_ok, index_tag_bad;
3464 TrySmiTag(index, index, &index_tag_bad); 3485 JumpIfNotSmiCandidate(index, r0, &index_tag_bad);
3486 #endif
3487 SmiTag(index, index);
3488 #if !V8_TARGET_ARCH_PPC64
3465 b(&index_tag_ok); 3489 b(&index_tag_ok);
3466 bind(&index_tag_bad); 3490 bind(&index_tag_bad);
3467 Abort(kIndexIsTooLarge); 3491 Abort(kIndexIsTooLarge);
3468 bind(&index_tag_ok); 3492 bind(&index_tag_ok);
3493 #endif
3469 3494
3470 ldr(ip, FieldMemOperand(string, String::kLengthOffset)); 3495 LoadP(ip, FieldMemOperand(string, String::kLengthOffset));
3471 cmp(index, ip); 3496 cmp(index, ip);
3472 Check(lt, kIndexIsTooLarge); 3497 Check(lt, kIndexIsTooLarge);
3473 3498
3474 cmp(index, Operand(Smi::FromInt(0))); 3499 DCHECK(Smi::FromInt(0) == 0);
3500 cmpi(index, Operand::Zero());
3475 Check(ge, kIndexIsNegative); 3501 Check(ge, kIndexIsNegative);
3476 3502
3477 SmiUntag(index, index); 3503 SmiUntag(index, index);
3478 } 3504 }
3479 3505
3480 3506
3481 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, 3507 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
3482 int num_double_arguments, 3508 int num_double_arguments,
3483 Register scratch) { 3509 Register scratch) {
3484 int frame_alignment = ActivationFrameAlignment(); 3510 int frame_alignment = ActivationFrameAlignment();
3485 int stack_passed_arguments = CalculateStackPassedWords( 3511 int stack_passed_arguments = CalculateStackPassedWords(
3486 num_reg_arguments, num_double_arguments); 3512 num_reg_arguments, num_double_arguments);
3513 int stack_space = kNumRequiredStackFrameSlots;
3514
3487 if (frame_alignment > kPointerSize) { 3515 if (frame_alignment > kPointerSize) {
3488 // Make stack end at alignment and make room for num_arguments - 4 words 3516 // Make stack end at alignment and make room for stack arguments
3489 // and the original value of sp. 3517 // -- preserving original value of sp.
3490 mov(scratch, sp); 3518 mr(scratch, sp);
3491 sub(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize)); 3519 addi(sp, sp, Operand(-(stack_passed_arguments + 1) * kPointerSize));
3492 DCHECK(IsPowerOf2(frame_alignment)); 3520 DCHECK(IsPowerOf2(frame_alignment));
3493 and_(sp, sp, Operand(-frame_alignment)); 3521 ClearRightImm(sp, sp, Operand(WhichPowerOf2(frame_alignment)));
3494 str(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize)); 3522 StoreP(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
3495 } else { 3523 } else {
3496 sub(sp, sp, Operand(stack_passed_arguments * kPointerSize)); 3524 // Make room for stack arguments
3525 stack_space += stack_passed_arguments;
3497 } 3526 }
3527
3528 // Allocate frame with required slots to make ABI work.
3529 li(r0, Operand::Zero());
3530 StorePU(r0, MemOperand(sp, -stack_space * kPointerSize));
3498 } 3531 }
3499 3532
3500 3533
3501 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, 3534 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
3502 Register scratch) { 3535 Register scratch) {
3503 PrepareCallCFunction(num_reg_arguments, 0, scratch); 3536 PrepareCallCFunction(num_reg_arguments, 0, scratch);
3504 } 3537 }
3505 3538
3506 3539
3507 void MacroAssembler::MovToFloatParameter(DwVfpRegister src) { 3540 void MacroAssembler::MovToFloatParameter(DoubleRegister src) {
3508 DCHECK(src.is(d0)); 3541 Move(d1, src);
3509 if (!use_eabi_hardfloat()) { 3542 }
3510 vmov(r0, r1, src); 3543
3544
3545 void MacroAssembler::MovToFloatResult(DoubleRegister src) {
3546 Move(d1, src);
3547 }
3548
3549
3550 void MacroAssembler::MovToFloatParameters(DoubleRegister src1,
3551 DoubleRegister src2) {
3552 if (src2.is(d1)) {
3553 DCHECK(!src1.is(d2));
3554 Move(d2, src2);
3555 Move(d1, src1);
3556 } else {
3557 Move(d1, src1);
3558 Move(d2, src2);
3511 } 3559 }
3512 } 3560 }
3513 3561
3514
3515 // On ARM this is just a synonym to make the purpose clear.
3516 void MacroAssembler::MovToFloatResult(DwVfpRegister src) {
3517 MovToFloatParameter(src);
3518 }
3519
3520
3521 void MacroAssembler::MovToFloatParameters(DwVfpRegister src1,
3522 DwVfpRegister src2) {
3523 DCHECK(src1.is(d0));
3524 DCHECK(src2.is(d1));
3525 if (!use_eabi_hardfloat()) {
3526 vmov(r0, r1, src1);
3527 vmov(r2, r3, src2);
3528 }
3529 }
3530
3531 3562
3532 void MacroAssembler::CallCFunction(ExternalReference function, 3563 void MacroAssembler::CallCFunction(ExternalReference function,
3533 int num_reg_arguments, 3564 int num_reg_arguments,
3534 int num_double_arguments) { 3565 int num_double_arguments) {
3535 mov(ip, Operand(function)); 3566 mov(ip, Operand(function));
3536 CallCFunctionHelper(ip, num_reg_arguments, num_double_arguments); 3567 CallCFunctionHelper(ip, num_reg_arguments, num_double_arguments);
3537 } 3568 }
3538 3569
3539 3570
3540 void MacroAssembler::CallCFunction(Register function, 3571 void MacroAssembler::CallCFunction(Register function,
(...skipping 12 matching lines...) Expand all
3553 void MacroAssembler::CallCFunction(Register function, 3584 void MacroAssembler::CallCFunction(Register function,
3554 int num_arguments) { 3585 int num_arguments) {
3555 CallCFunction(function, num_arguments, 0); 3586 CallCFunction(function, num_arguments, 0);
3556 } 3587 }
3557 3588
3558 3589
3559 void MacroAssembler::CallCFunctionHelper(Register function, 3590 void MacroAssembler::CallCFunctionHelper(Register function,
3560 int num_reg_arguments, 3591 int num_reg_arguments,
3561 int num_double_arguments) { 3592 int num_double_arguments) {
3562 DCHECK(has_frame()); 3593 DCHECK(has_frame());
3563 // Make sure that the stack is aligned before calling a C function unless
3564 // running in the simulator. The simulator has its own alignment check which
3565 // provides more information.
3566 #if V8_HOST_ARCH_ARM
3567 if (emit_debug_code()) {
3568 int frame_alignment = base::OS::ActivationFrameAlignment();
3569 int frame_alignment_mask = frame_alignment - 1;
3570 if (frame_alignment > kPointerSize) {
3571 DCHECK(IsPowerOf2(frame_alignment));
3572 Label alignment_as_expected;
3573 tst(sp, Operand(frame_alignment_mask));
3574 b(eq, &alignment_as_expected);
3575 // Don't use Check here, as it will call Runtime_Abort possibly
3576 // re-entering here.
3577 stop("Unexpected alignment");
3578 bind(&alignment_as_expected);
3579 }
3580 }
3581 #endif
3582
3583 // Just call directly. The function called cannot cause a GC, or 3594 // Just call directly. The function called cannot cause a GC, or
3584 // allow preemption, so the return address in the link register 3595 // allow preemption, so the return address in the link register
3585 // stays correct. 3596 // stays correct.
3586 Call(function); 3597 #if ABI_USES_FUNCTION_DESCRIPTORS && !defined(USE_SIMULATOR)
3598 // AIX uses a function descriptor. When calling C code be aware
3599 // of this descriptor and pick up values from it
3600 LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(function, kPointerSize));
3601 LoadP(ip, MemOperand(function, 0));
3602 Register dest = ip;
3603 #elif ABI_TOC_ADDRESSABILITY_VIA_IP
3604 Move(ip, function);
3605 Register dest = ip;
3606 #else
3607 Register dest = function;
3608 #endif
3609
3610 Call(dest);
3611
3612 // Remove frame bought in PrepareCallCFunction
3587 int stack_passed_arguments = CalculateStackPassedWords( 3613 int stack_passed_arguments = CalculateStackPassedWords(
3588 num_reg_arguments, num_double_arguments); 3614 num_reg_arguments, num_double_arguments);
3615 int stack_space = kNumRequiredStackFrameSlots + stack_passed_arguments;
3589 if (ActivationFrameAlignment() > kPointerSize) { 3616 if (ActivationFrameAlignment() > kPointerSize) {
3590 ldr(sp, MemOperand(sp, stack_passed_arguments * kPointerSize)); 3617 LoadP(sp, MemOperand(sp, stack_space * kPointerSize));
3591 } else { 3618 } else {
3592 add(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize))); 3619 addi(sp, sp, Operand(stack_space * kPointerSize));
3593 } 3620 }
3594 } 3621 }
3595 3622
3596 3623
3597 void MacroAssembler::GetRelocatedValueLocation(Register ldr_location, 3624 void MacroAssembler::FlushICache(Register address, size_t size,
3598 Register result, 3625 Register scratch) {
3599 Register scratch) { 3626 Label done;
3600 Label small_constant_pool_load, load_result; 3627
3601 ldr(result, MemOperand(ldr_location)); 3628 dcbf(r0, address);
3602 3629 sync();
3603 if (FLAG_enable_ool_constant_pool) { 3630 icbi(r0, address);
3604 // Check if this is an extended constant pool load. 3631 isync();
3605 and_(scratch, result, Operand(GetConsantPoolLoadMask())); 3632
3606 teq(scratch, Operand(GetConsantPoolLoadPattern())); 3633 // This code handles ranges which cross a single cacheline boundary.
3607 b(eq, &small_constant_pool_load); 3634 // scratch is last cacheline which intersects range.
3608 if (emit_debug_code()) { 3635 const int kCacheLineSizeLog2 = WhichPowerOf2(CpuFeatures::cache_line_size());
3609 // Check that the instruction sequence is: 3636
3610 // movw reg, #offset_low 3637 DCHECK(size > 0 && size <= (size_t)(1 << kCacheLineSizeLog2));
3611 // movt reg, #offset_high 3638 addi(scratch, address, Operand(size - 1));
3612 // ldr reg, [pp, reg] 3639 ClearRightImm(scratch, scratch, Operand(kCacheLineSizeLog2));
3613 Instr patterns[] = {GetMovWPattern(), GetMovTPattern(), 3640 cmpl(scratch, address);
3614 GetLdrPpRegOffsetPattern()}; 3641 ble(&done);
3615 for (int i = 0; i < 3; i++) { 3642
3616 ldr(result, MemOperand(ldr_location, i * kInstrSize)); 3643 dcbf(r0, scratch);
3617 and_(result, result, Operand(patterns[i])); 3644 sync();
3618 cmp(result, Operand(patterns[i])); 3645 icbi(r0, scratch);
3619 Check(eq, kTheInstructionToPatchShouldBeALoadFromConstantPool); 3646 isync();
3620 } 3647
3621 // Result was clobbered. Restore it. 3648 bind(&done);
3622 ldr(result, MemOperand(ldr_location)); 3649 }
3623 } 3650
3624 3651
3625 // Get the offset into the constant pool. First extract movw immediate into 3652 void MacroAssembler::SetRelocatedValue(Register location,
3626 // result. 3653 Register scratch,
3627 and_(scratch, result, Operand(0xfff)); 3654 Register new_value) {
3628 mov(ip, Operand(result, LSR, 4)); 3655 lwz(scratch, MemOperand(location));
3629 and_(ip, ip, Operand(0xf000)); 3656
3630 orr(result, scratch, Operand(ip)); 3657 #if V8_OOL_CONSTANT_POOL
3631 // Then extract movt immediate and or into result. 3658 if (emit_debug_code()) {
3632 ldr(scratch, MemOperand(ldr_location, kInstrSize)); 3659 // Check that the instruction sequence is a load from the constant pool
3633 and_(ip, scratch, Operand(0xf0000)); 3660 #if V8_TARGET_ARCH_PPC64
3634 orr(result, result, Operand(ip, LSL, 12)); 3661 And(scratch, scratch, Operand(kOpcodeMask | (0x1f * B16)));
3635 and_(scratch, scratch, Operand(0xfff)); 3662 Cmpi(scratch, Operand(ADDI), r0);
3636 orr(result, result, Operand(scratch, LSL, 16)); 3663 Check(eq, kTheInstructionShouldBeALi);
3637 3664 lwz(scratch, MemOperand(location, kInstrSize));
3638 b(&load_result); 3665 #endif
3639 } 3666 ExtractBitMask(scratch, scratch, 0x1f * B16);
3640 3667 cmpi(scratch, Operand(kConstantPoolRegister.code()));
3641 bind(&small_constant_pool_load);
3642 if (emit_debug_code()) {
3643 // Check that the instruction is a ldr reg, [<pc or pp> + offset] .
3644 and_(result, result, Operand(GetConsantPoolLoadPattern()));
3645 cmp(result, Operand(GetConsantPoolLoadPattern()));
3646 Check(eq, kTheInstructionToPatchShouldBeALoadFromConstantPool); 3668 Check(eq, kTheInstructionToPatchShouldBeALoadFromConstantPool);
3647 // Result was clobbered. Restore it. 3669 // Scratch was clobbered. Restore it.
3648 ldr(result, MemOperand(ldr_location)); 3670 lwz(scratch, MemOperand(location));
3649 } 3671 }
3650 3672 // Get the address of the constant and patch it.
3651 // Get the offset into the constant pool. 3673 andi(scratch, scratch, Operand(kImm16Mask));
3652 const uint32_t kLdrOffsetMask = (1 << 12) - 1; 3674 StorePX(new_value, MemOperand(kConstantPoolRegister, scratch));
3653 and_(result, result, Operand(kLdrOffsetMask)); 3675 #else
3654 3676 // This code assumes a FIXED_SEQUENCE for lis/ori
3655 bind(&load_result); 3677
3656 // Get the address of the constant. 3678 // At this point scratch is a lis instruction.
3657 if (FLAG_enable_ool_constant_pool) { 3679 if (emit_debug_code()) {
3658 add(result, pp, Operand(result)); 3680 And(scratch, scratch, Operand(kOpcodeMask | (0x1f * B16)));
3659 } else { 3681 Cmpi(scratch, Operand(ADDIS), r0);
3660 add(result, ldr_location, Operand(result)); 3682 Check(eq, kTheInstructionToPatchShouldBeALis);
3661 add(result, result, Operand(Instruction::kPCReadOffset)); 3683 lwz(scratch, MemOperand(location));
3662 } 3684 }
3685
3686 // insert new high word into lis instruction
3687 #if V8_TARGET_ARCH_PPC64
3688 srdi(ip, new_value, Operand(32));
3689 rlwimi(scratch, ip, 16, 16, 31);
3690 #else
3691 rlwimi(scratch, new_value, 16, 16, 31);
3692 #endif
3693
3694 stw(scratch, MemOperand(location));
3695
3696 lwz(scratch, MemOperand(location, kInstrSize));
3697 // scratch is now ori.
3698 if (emit_debug_code()) {
3699 And(scratch, scratch, Operand(kOpcodeMask));
3700 Cmpi(scratch, Operand(ORI), r0);
3701 Check(eq, kTheInstructionShouldBeAnOri);
3702 lwz(scratch, MemOperand(location, kInstrSize));
3703 }
3704
3705 // insert new low word into ori instruction
3706 #if V8_TARGET_ARCH_PPC64
3707 rlwimi(scratch, ip, 0, 16, 31);
3708 #else
3709 rlwimi(scratch, new_value, 0, 16, 31);
3710 #endif
3711 stw(scratch, MemOperand(location, kInstrSize));
3712
3713 #if V8_TARGET_ARCH_PPC64
3714 if (emit_debug_code()) {
3715 lwz(scratch, MemOperand(location, 2*kInstrSize));
3716 // scratch is now sldi.
3717 And(scratch, scratch, Operand(kOpcodeMask|kExt5OpcodeMask));
3718 Cmpi(scratch, Operand(EXT5|RLDICR), r0);
3719 Check(eq, kTheInstructionShouldBeASldi);
3720 }
3721
3722 lwz(scratch, MemOperand(location, 3*kInstrSize));
3723 // scratch is now ori.
3724 if (emit_debug_code()) {
3725 And(scratch, scratch, Operand(kOpcodeMask));
3726 Cmpi(scratch, Operand(ORIS), r0);
3727 Check(eq, kTheInstructionShouldBeAnOris);
3728 lwz(scratch, MemOperand(location, 3*kInstrSize));
3729 }
3730
3731 rlwimi(scratch, new_value, 16, 16, 31);
3732 stw(scratch, MemOperand(location, 3*kInstrSize));
3733
3734 lwz(scratch, MemOperand(location, 4*kInstrSize));
3735 // scratch is now ori.
3736 if (emit_debug_code()) {
3737 And(scratch, scratch, Operand(kOpcodeMask));
3738 Cmpi(scratch, Operand(ORI), r0);
3739 Check(eq, kTheInstructionShouldBeAnOri);
3740 lwz(scratch, MemOperand(location, 4*kInstrSize));
3741 }
3742 rlwimi(scratch, new_value, 0, 16, 31);
3743 stw(scratch, MemOperand(location, 4*kInstrSize));
3744 #endif
3745
3746 // Update the I-cache so the new lis and addic can be executed.
3747 #if V8_TARGET_ARCH_PPC64
3748 FlushICache(location, 5 * kInstrSize, scratch);
3749 #else
3750 FlushICache(location, 2 * kInstrSize, scratch);
3751 #endif
3752 #endif
3753 }
3754
3755
3756 void MacroAssembler::GetRelocatedValue(Register location,
3757 Register result,
3758 Register scratch) {
3759 lwz(result, MemOperand(location));
3760
3761 #if V8_OOL_CONSTANT_POOL
3762 if (emit_debug_code()) {
3763 // Check that the instruction sequence is a load from the constant pool
3764 #if V8_TARGET_ARCH_PPC64
3765 And(result, result, Operand(kOpcodeMask | (0x1f * B16)));
3766 Cmpi(result, Operand(ADDI), r0);
3767 Check(eq, kTheInstructionShouldBeALi);
3768 lwz(result, MemOperand(location, kInstrSize));
3769 #endif
3770 ExtractBitMask(result, result, 0x1f * B16);
3771 cmpi(result, Operand(kConstantPoolRegister.code()));
3772 Check(eq, kTheInstructionToPatchShouldBeALoadFromConstantPool);
3773 lwz(result, MemOperand(location));
3774 }
3775 // Get the address of the constant and retrieve it.
3776 andi(result, result, Operand(kImm16Mask));
3777 LoadPX(result, MemOperand(kConstantPoolRegister, result));
3778 #else
3779 // This code assumes a FIXED_SEQUENCE for lis/ori
3780 if (emit_debug_code()) {
3781 And(result, result, Operand(kOpcodeMask | (0x1f * B16)));
3782 Cmpi(result, Operand(ADDIS), r0);
3783 Check(eq, kTheInstructionShouldBeALis);
3784 lwz(result, MemOperand(location));
3785 }
3786
3787 // result now holds a lis instruction. Extract the immediate.
3788 slwi(result, result, Operand(16));
3789
3790 lwz(scratch, MemOperand(location, kInstrSize));
3791 if (emit_debug_code()) {
3792 And(scratch, scratch, Operand(kOpcodeMask));
3793 Cmpi(scratch, Operand(ORI), r0);
3794 Check(eq, kTheInstructionShouldBeAnOri);
3795 lwz(scratch, MemOperand(location, kInstrSize));
3796 }
3797 // Copy the low 16bits from ori instruction into result
3798 rlwimi(result, scratch, 0, 16, 31);
3799
3800 #if V8_TARGET_ARCH_PPC64
3801 if (emit_debug_code()) {
3802 lwz(scratch, MemOperand(location, 2*kInstrSize));
3803 // scratch is now sldi.
3804 And(scratch, scratch, Operand(kOpcodeMask|kExt5OpcodeMask));
3805 Cmpi(scratch, Operand(EXT5|RLDICR), r0);
3806 Check(eq, kTheInstructionShouldBeASldi);
3807 }
3808
3809 lwz(scratch, MemOperand(location, 3*kInstrSize));
3810 // scratch is now ori.
3811 if (emit_debug_code()) {
3812 And(scratch, scratch, Operand(kOpcodeMask));
3813 Cmpi(scratch, Operand(ORIS), r0);
3814 Check(eq, kTheInstructionShouldBeAnOris);
3815 lwz(scratch, MemOperand(location, 3*kInstrSize));
3816 }
3817 sldi(result, result, Operand(16));
3818 rldimi(result, scratch, 0, 48);
3819
3820 lwz(scratch, MemOperand(location, 4*kInstrSize));
3821 // scratch is now ori.
3822 if (emit_debug_code()) {
3823 And(scratch, scratch, Operand(kOpcodeMask));
3824 Cmpi(scratch, Operand(ORI), r0);
3825 Check(eq, kTheInstructionShouldBeAnOri);
3826 lwz(scratch, MemOperand(location, 4*kInstrSize));
3827 }
3828 sldi(result, result, Operand(16));
3829 rldimi(result, scratch, 0, 48);
3830 #endif
3831 #endif
3663 } 3832 }
3664 3833
3665 3834
3666 void MacroAssembler::CheckPageFlag( 3835 void MacroAssembler::CheckPageFlag(
3667 Register object, 3836 Register object,
3668 Register scratch, 3837 Register scratch, // scratch may be same register as object
3669 int mask, 3838 int mask,
3670 Condition cc, 3839 Condition cc,
3671 Label* condition_met) { 3840 Label* condition_met) {
3672 Bfc(scratch, object, 0, kPageSizeBits); 3841 DCHECK(cc == ne || cc == eq);
3673 ldr(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset)); 3842 ClearRightImm(scratch, object, Operand(kPageSizeBits));
3674 tst(scratch, Operand(mask)); 3843 LoadP(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset));
3675 b(cc, condition_met); 3844
3676 } 3845 And(r0, scratch, Operand(mask), SetRC);
3677 3846
3678 3847 if (cc == ne) {
3848 bne(condition_met, cr0);
3849 }
3850 if (cc == eq) {
3851 beq(condition_met, cr0);
3852 }
3853 }
3854
3855
3679 void MacroAssembler::CheckMapDeprecated(Handle<Map> map, 3856 void MacroAssembler::CheckMapDeprecated(Handle<Map> map,
3680 Register scratch, 3857 Register scratch,
3681 Label* if_deprecated) { 3858 Label* if_deprecated) {
3682 if (map->CanBeDeprecated()) { 3859 if (map->CanBeDeprecated()) {
3683 mov(scratch, Operand(map)); 3860 mov(scratch, Operand(map));
3684 ldr(scratch, FieldMemOperand(scratch, Map::kBitField3Offset)); 3861 lwz(scratch, FieldMemOperand(scratch, Map::kBitField3Offset));
3685 tst(scratch, Operand(Map::Deprecated::kMask)); 3862 ExtractBitMask(scratch, scratch, Map::Deprecated::kMask, SetRC);
3686 b(ne, if_deprecated); 3863 bne(if_deprecated, cr0);
3687 } 3864 }
3688 } 3865 }
3689 3866
3690 3867
3691 void MacroAssembler::JumpIfBlack(Register object, 3868 void MacroAssembler::JumpIfBlack(Register object,
3692 Register scratch0, 3869 Register scratch0,
3693 Register scratch1, 3870 Register scratch1,
3694 Label* on_black) { 3871 Label* on_black) {
3695 HasColor(object, scratch0, scratch1, on_black, 1, 0); // kBlackBitPattern. 3872 HasColor(object, scratch0, scratch1, on_black, 1, 0); // kBlackBitPattern.
3696 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); 3873 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0);
3697 } 3874 }
3698 3875
3699 3876
3700 void MacroAssembler::HasColor(Register object, 3877 void MacroAssembler::HasColor(Register object,
3701 Register bitmap_scratch, 3878 Register bitmap_scratch,
3702 Register mask_scratch, 3879 Register mask_scratch,
3703 Label* has_color, 3880 Label* has_color,
3704 int first_bit, 3881 int first_bit,
3705 int second_bit) { 3882 int second_bit) {
3706 DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, no_reg)); 3883 DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, no_reg));
3707 3884
3708 GetMarkBits(object, bitmap_scratch, mask_scratch); 3885 GetMarkBits(object, bitmap_scratch, mask_scratch);
3709 3886
3710 Label other_color, word_boundary; 3887 Label other_color, word_boundary;
3711 ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); 3888 lwz(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
3712 tst(ip, Operand(mask_scratch)); 3889 // Test the first bit
3713 b(first_bit == 1 ? eq : ne, &other_color); 3890 and_(r0, ip, mask_scratch, SetRC);
3714 // Shift left 1 by adding. 3891 b(first_bit == 1 ? eq : ne, &other_color, cr0);
3715 add(mask_scratch, mask_scratch, Operand(mask_scratch), SetCC); 3892 // Shift left 1
3716 b(eq, &word_boundary); 3893 // May need to load the next cell
3717 tst(ip, Operand(mask_scratch)); 3894 slwi(mask_scratch, mask_scratch, Operand(1), SetRC);
3718 b(second_bit == 1 ? ne : eq, has_color); 3895 beq(&word_boundary, cr0);
3719 jmp(&other_color); 3896 // Test the second bit
3897 and_(r0, ip, mask_scratch, SetRC);
3898 b(second_bit == 1 ? ne : eq, has_color, cr0);
3899 b(&other_color);
3720 3900
3721 bind(&word_boundary); 3901 bind(&word_boundary);
3722 ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize)); 3902 lwz(ip, MemOperand(bitmap_scratch,
3723 tst(ip, Operand(1)); 3903 MemoryChunk::kHeaderSize + kIntSize));
3724 b(second_bit == 1 ? ne : eq, has_color); 3904 andi(r0, ip, Operand(1));
3905 b(second_bit == 1 ? ne : eq, has_color, cr0);
3725 bind(&other_color); 3906 bind(&other_color);
3726 } 3907 }
3727 3908
3728 3909
3729 // Detect some, but not all, common pointer-free objects. This is used by the 3910 // Detect some, but not all, common pointer-free objects. This is used by the
3730 // incremental write barrier which doesn't care about oddballs (they are always 3911 // incremental write barrier which doesn't care about oddballs (they are always
3731 // marked black immediately so this code is not hit). 3912 // marked black immediately so this code is not hit).
3732 void MacroAssembler::JumpIfDataObject(Register value, 3913 void MacroAssembler::JumpIfDataObject(Register value,
3733 Register scratch, 3914 Register scratch,
3734 Label* not_data_object) { 3915 Label* not_data_object) {
3735 Label is_data_object; 3916 Label is_data_object;
3736 ldr(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); 3917 LoadP(scratch, FieldMemOperand(value, HeapObject::kMapOffset));
3737 CompareRoot(scratch, Heap::kHeapNumberMapRootIndex); 3918 CompareRoot(scratch, Heap::kHeapNumberMapRootIndex);
3738 b(eq, &is_data_object); 3919 beq(&is_data_object);
3739 DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); 3920 DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
3740 DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); 3921 DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
3741 // If it's a string and it's not a cons string then it's an object containing 3922 // If it's a string and it's not a cons string then it's an object containing
3742 // no GC pointers. 3923 // no GC pointers.
3743 ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); 3924 lbz(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
3744 tst(scratch, Operand(kIsIndirectStringMask | kIsNotStringMask)); 3925 STATIC_ASSERT((kIsIndirectStringMask | kIsNotStringMask) == 0x81);
3745 b(ne, not_data_object); 3926 andi(scratch, scratch, Operand(kIsIndirectStringMask | kIsNotStringMask));
3927 bne(not_data_object, cr0);
3746 bind(&is_data_object); 3928 bind(&is_data_object);
3747 } 3929 }
3748 3930
3749 3931
3750 void MacroAssembler::GetMarkBits(Register addr_reg, 3932 void MacroAssembler::GetMarkBits(Register addr_reg,
3751 Register bitmap_reg, 3933 Register bitmap_reg,
3752 Register mask_reg) { 3934 Register mask_reg) {
3753 DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg)); 3935 DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg));
3754 and_(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask)); 3936 DCHECK((~Page::kPageAlignmentMask & 0xffff) == 0);
3755 Ubfx(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2); 3937 lis(r0, Operand((~Page::kPageAlignmentMask >> 16)));
3938 and_(bitmap_reg, addr_reg, r0);
3756 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; 3939 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2;
3757 Ubfx(ip, addr_reg, kLowBits, kPageSizeBits - kLowBits); 3940 ExtractBitRange(mask_reg, addr_reg,
3758 add(bitmap_reg, bitmap_reg, Operand(ip, LSL, kPointerSizeLog2)); 3941 kLowBits - 1,
3759 mov(ip, Operand(1)); 3942 kPointerSizeLog2);
3760 mov(mask_reg, Operand(ip, LSL, mask_reg)); 3943 ExtractBitRange(ip, addr_reg,
3944 kPageSizeBits - 1,
3945 kLowBits);
3946 ShiftLeftImm(ip, ip, Operand(Bitmap::kBytesPerCellLog2));
3947 add(bitmap_reg, bitmap_reg, ip);
3948 li(ip, Operand(1));
3949 slw(mask_reg, ip, mask_reg);
3761 } 3950 }
3762 3951
3763 3952
3764 void MacroAssembler::EnsureNotWhite( 3953 void MacroAssembler::EnsureNotWhite(
3765 Register value, 3954 Register value,
3766 Register bitmap_scratch, 3955 Register bitmap_scratch,
3767 Register mask_scratch, 3956 Register mask_scratch,
3768 Register load_scratch, 3957 Register load_scratch,
3769 Label* value_is_white_and_not_data) { 3958 Label* value_is_white_and_not_data) {
3770 DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, ip)); 3959 DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, ip));
3771 GetMarkBits(value, bitmap_scratch, mask_scratch); 3960 GetMarkBits(value, bitmap_scratch, mask_scratch);
3772 3961
3773 // If the value is black or grey we don't need to do anything. 3962 // If the value is black or grey we don't need to do anything.
3774 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); 3963 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
3775 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); 3964 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0);
3776 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); 3965 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0);
3777 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); 3966 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
3778 3967
3779 Label done; 3968 Label done;
3780 3969
3781 // Since both black and grey have a 1 in the first position and white does 3970 // Since both black and grey have a 1 in the first position and white does
3782 // not have a 1 there we only need to check one bit. 3971 // not have a 1 there we only need to check one bit.
3783 ldr(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); 3972 lwz(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
3784 tst(mask_scratch, load_scratch); 3973 and_(r0, mask_scratch, load_scratch, SetRC);
3785 b(ne, &done); 3974 bne(&done, cr0);
3786 3975
3787 if (emit_debug_code()) { 3976 if (emit_debug_code()) {
3788 // Check for impossible bit pattern. 3977 // Check for impossible bit pattern.
3789 Label ok; 3978 Label ok;
3790 // LSL may overflow, making the check conservative. 3979 // LSL may overflow, making the check conservative.
3791 tst(load_scratch, Operand(mask_scratch, LSL, 1)); 3980 slwi(r0, mask_scratch, Operand(1));
3792 b(eq, &ok); 3981 and_(r0, load_scratch, r0, SetRC);
3982 beq(&ok, cr0);
3793 stop("Impossible marking bit pattern"); 3983 stop("Impossible marking bit pattern");
3794 bind(&ok); 3984 bind(&ok);
3795 } 3985 }
3796 3986
3797 // Value is white. We check whether it is data that doesn't need scanning. 3987 // Value is white. We check whether it is data that doesn't need scanning.
3798 // Currently only checks for HeapNumber and non-cons strings. 3988 // Currently only checks for HeapNumber and non-cons strings.
3799 Register map = load_scratch; // Holds map while checking type. 3989 Register map = load_scratch; // Holds map while checking type.
3800 Register length = load_scratch; // Holds length of object after testing type. 3990 Register length = load_scratch; // Holds length of object after testing type.
3801 Label is_data_object; 3991 Label is_data_object, maybe_string_object, is_string_object, is_encoded;
3992 #if V8_TARGET_ARCH_PPC64
3993 Label length_computed;
3994 #endif
3995
3802 3996
3803 // Check for heap-number 3997 // Check for heap-number
3804 ldr(map, FieldMemOperand(value, HeapObject::kMapOffset)); 3998 LoadP(map, FieldMemOperand(value, HeapObject::kMapOffset));
3805 CompareRoot(map, Heap::kHeapNumberMapRootIndex); 3999 CompareRoot(map, Heap::kHeapNumberMapRootIndex);
3806 mov(length, Operand(HeapNumber::kSize), LeaveCC, eq); 4000 bne(&maybe_string_object);
3807 b(eq, &is_data_object); 4001 li(length, Operand(HeapNumber::kSize));
4002 b(&is_data_object);
4003 bind(&maybe_string_object);
3808 4004
3809 // Check for strings. 4005 // Check for strings.
3810 DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); 4006 DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
3811 DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); 4007 DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
3812 // If it's a string and it's not a cons string then it's an object containing 4008 // If it's a string and it's not a cons string then it's an object containing
3813 // no GC pointers. 4009 // no GC pointers.
3814 Register instance_type = load_scratch; 4010 Register instance_type = load_scratch;
3815 ldrb(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset)); 4011 lbz(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset));
3816 tst(instance_type, Operand(kIsIndirectStringMask | kIsNotStringMask)); 4012 andi(r0, instance_type, Operand(kIsIndirectStringMask | kIsNotStringMask));
3817 b(ne, value_is_white_and_not_data); 4013 bne(value_is_white_and_not_data, cr0);
3818 // It's a non-indirect (non-cons and non-slice) string. 4014 // It's a non-indirect (non-cons and non-slice) string.
3819 // If it's external, the length is just ExternalString::kSize. 4015 // If it's external, the length is just ExternalString::kSize.
3820 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). 4016 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2).
3821 // External strings are the only ones with the kExternalStringTag bit 4017 // External strings are the only ones with the kExternalStringTag bit
3822 // set. 4018 // set.
3823 DCHECK_EQ(0, kSeqStringTag & kExternalStringTag); 4019 DCHECK_EQ(0, kSeqStringTag & kExternalStringTag);
3824 DCHECK_EQ(0, kConsStringTag & kExternalStringTag); 4020 DCHECK_EQ(0, kConsStringTag & kExternalStringTag);
3825 tst(instance_type, Operand(kExternalStringTag)); 4021 andi(r0, instance_type, Operand(kExternalStringTag));
3826 mov(length, Operand(ExternalString::kSize), LeaveCC, ne); 4022 beq(&is_string_object, cr0);
3827 b(ne, &is_data_object); 4023 li(length, Operand(ExternalString::kSize));
4024 b(&is_data_object);
4025 bind(&is_string_object);
3828 4026
3829 // Sequential string, either ASCII or UC16. 4027 // Sequential string, either ASCII or UC16.
3830 // For ASCII (char-size of 1) we shift the smi tag away to get the length. 4028 // For ASCII (char-size of 1) we untag the smi to get the length.
3831 // For UC16 (char-size of 2) we just leave the smi tag in place, thereby 4029 // For UC16 (char-size of 2):
3832 // getting the length multiplied by 2. 4030 // - (32-bit) we just leave the smi tag in place, thereby getting
4031 // the length multiplied by 2.
4032 // - (64-bit) we compute the offset in the 2-byte array
3833 DCHECK(kOneByteStringTag == 4 && kStringEncodingMask == 4); 4033 DCHECK(kOneByteStringTag == 4 && kStringEncodingMask == 4);
3834 DCHECK(kSmiTag == 0 && kSmiTagSize == 1); 4034 LoadP(ip, FieldMemOperand(value, String::kLengthOffset));
3835 ldr(ip, FieldMemOperand(value, String::kLengthOffset)); 4035 andi(r0, instance_type, Operand(kStringEncodingMask));
3836 tst(instance_type, Operand(kStringEncodingMask)); 4036 beq(&is_encoded, cr0);
3837 mov(ip, Operand(ip, LSR, 1), LeaveCC, ne); 4037 SmiUntag(ip);
3838 add(length, ip, Operand(SeqString::kHeaderSize + kObjectAlignmentMask)); 4038 #if V8_TARGET_ARCH_PPC64
3839 and_(length, length, Operand(~kObjectAlignmentMask)); 4039 b(&length_computed);
4040 #endif
4041 bind(&is_encoded);
4042 #if V8_TARGET_ARCH_PPC64
4043 SmiToShortArrayOffset(ip, ip);
4044 bind(&length_computed);
4045 #else
4046 DCHECK(kSmiShift == 1);
4047 #endif
4048 addi(length, ip, Operand(SeqString::kHeaderSize + kObjectAlignmentMask));
4049 li(r0, Operand(~kObjectAlignmentMask));
4050 and_(length, length, r0);
3840 4051
3841 bind(&is_data_object); 4052 bind(&is_data_object);
3842 // Value is a data object, and it is white. Mark it black. Since we know 4053 // Value is a data object, and it is white. Mark it black. Since we know
3843 // that the object is white we can make it black by flipping one bit. 4054 // that the object is white we can make it black by flipping one bit.
3844 ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); 4055 lwz(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
3845 orr(ip, ip, Operand(mask_scratch)); 4056 orx(ip, ip, mask_scratch);
3846 str(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); 4057 stw(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
3847 4058
3848 and_(bitmap_scratch, bitmap_scratch, Operand(~Page::kPageAlignmentMask)); 4059 mov(ip, Operand(~Page::kPageAlignmentMask));
3849 ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); 4060 and_(bitmap_scratch, bitmap_scratch, ip);
3850 add(ip, ip, Operand(length)); 4061 lwz(ip, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
3851 str(ip, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); 4062 add(ip, ip, length);
4063 stw(ip, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
3852 4064
3853 bind(&done); 4065 bind(&done);
3854 } 4066 }
3855 4067
3856 4068
4069 // Saturate a value into 8-bit unsigned integer
4070 // if input_value < 0, output_value is 0
4071 // if input_value > 255, output_value is 255
4072 // otherwise output_value is the input_value
3857 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) { 4073 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) {
3858 Usat(output_reg, 8, Operand(input_reg)); 4074 Label done, negative_label, overflow_label;
4075 int satval = (1 << 8) - 1;
4076
4077 cmpi(input_reg, Operand::Zero());
4078 blt(&negative_label);
4079
4080 cmpi(input_reg, Operand(satval));
4081 bgt(&overflow_label);
4082 if (!output_reg.is(input_reg)) {
4083 mr(output_reg, input_reg);
4084 }
4085 b(&done);
4086
4087 bind(&negative_label);
4088 li(output_reg, Operand::Zero()); // set to 0 if negative
4089 b(&done);
4090
4091
4092 bind(&overflow_label); // set to satval if > satval
4093 li(output_reg, Operand(satval));
4094
4095 bind(&done);
4096 }
4097
4098
4099 void MacroAssembler::SetRoundingMode(FPRoundingMode RN) {
4100 mtfsfi(7, RN);
4101 }
4102
4103
4104 void MacroAssembler::ResetRoundingMode() {
4105 mtfsfi(7, kRoundToNearest); // reset (default is kRoundToNearest)
3859 } 4106 }
3860 4107
3861 4108
3862 void MacroAssembler::ClampDoubleToUint8(Register result_reg, 4109 void MacroAssembler::ClampDoubleToUint8(Register result_reg,
3863 DwVfpRegister input_reg, 4110 DoubleRegister input_reg,
3864 LowDwVfpRegister double_scratch) { 4111 DoubleRegister double_scratch) {
4112 Label above_zero;
3865 Label done; 4113 Label done;
3866 4114 Label in_bounds;
3867 // Handle inputs >= 255 (including +infinity). 4115
3868 Vmov(double_scratch, 255.0, result_reg); 4116 LoadDoubleLiteral(double_scratch, 0.0, result_reg);
3869 mov(result_reg, Operand(255)); 4117 fcmpu(input_reg, double_scratch);
3870 VFPCompareAndSetFlags(input_reg, double_scratch); 4118 bgt(&above_zero);
3871 b(ge, &done); 4119
3872 4120 // Double value is less than zero, NaN or Inf, return 0.
3873 // For inputs < 255 (including negative) vcvt_u32_f64 with round-to-nearest 4121 LoadIntLiteral(result_reg, 0);
3874 // rounding mode will provide the correct result. 4122 b(&done);
3875 vcvt_u32_f64(double_scratch.low(), input_reg, kFPSCRRounding); 4123
3876 vmov(result_reg, double_scratch.low()); 4124 // Double value is >= 255, return 255.
3877 4125 bind(&above_zero);
4126 LoadDoubleLiteral(double_scratch, 255.0, result_reg);
4127 fcmpu(input_reg, double_scratch);
4128 ble(&in_bounds);
4129 LoadIntLiteral(result_reg, 255);
4130 b(&done);
4131
4132 // In 0-255 range, round and truncate.
4133 bind(&in_bounds);
4134
4135 // round to nearest (default rounding mode)
4136 fctiw(double_scratch, input_reg);
4137 MovDoubleLowToInt(result_reg, double_scratch);
3878 bind(&done); 4138 bind(&done);
3879 } 4139 }
3880 4140
3881 4141
3882 void MacroAssembler::LoadInstanceDescriptors(Register map, 4142 void MacroAssembler::LoadInstanceDescriptors(Register map,
3883 Register descriptors) { 4143 Register descriptors) {
3884 ldr(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset)); 4144 LoadP(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset));
3885 } 4145 }
3886 4146
3887 4147
3888 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { 4148 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
3889 ldr(dst, FieldMemOperand(map, Map::kBitField3Offset)); 4149 lwz(dst, FieldMemOperand(map, Map::kBitField3Offset));
3890 DecodeField<Map::NumberOfOwnDescriptorsBits>(dst); 4150 DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
3891 } 4151 }
3892 4152
3893 4153
3894 void MacroAssembler::EnumLength(Register dst, Register map) { 4154 void MacroAssembler::EnumLength(Register dst, Register map) {
3895 STATIC_ASSERT(Map::EnumLengthBits::kShift == 0); 4155 STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
3896 ldr(dst, FieldMemOperand(map, Map::kBitField3Offset)); 4156 lwz(dst, FieldMemOperand(map, Map::kBitField3Offset));
3897 and_(dst, dst, Operand(Map::EnumLengthBits::kMask)); 4157 ExtractBitMask(dst, dst, Map::EnumLengthBits::kMask);
3898 SmiTag(dst); 4158 SmiTag(dst);
3899 } 4159 }
3900 4160
3901 4161
3902 void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) { 4162 void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) {
3903 Register empty_fixed_array_value = r6; 4163 Register empty_fixed_array_value = r9;
3904 LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); 4164 LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
3905 Label next, start; 4165 Label next, start;
3906 mov(r2, r0); 4166 mr(r5, r3);
3907 4167
3908 // Check if the enum length field is properly initialized, indicating that 4168 // Check if the enum length field is properly initialized, indicating that
3909 // there is an enum cache. 4169 // there is an enum cache.
3910 ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset)); 4170 LoadP(r4, FieldMemOperand(r5, HeapObject::kMapOffset));
3911 4171
3912 EnumLength(r3, r1); 4172 EnumLength(r6, r4);
3913 cmp(r3, Operand(Smi::FromInt(kInvalidEnumCacheSentinel))); 4173 CmpSmiLiteral(r6, Smi::FromInt(kInvalidEnumCacheSentinel), r0);
3914 b(eq, call_runtime); 4174 beq(call_runtime);
3915 4175
3916 jmp(&start); 4176 b(&start);
3917 4177
3918 bind(&next); 4178 bind(&next);
3919 ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset)); 4179 LoadP(r4, FieldMemOperand(r5, HeapObject::kMapOffset));
3920 4180
3921 // For all objects but the receiver, check that the cache is empty. 4181 // For all objects but the receiver, check that the cache is empty.
3922 EnumLength(r3, r1); 4182 EnumLength(r6, r4);
3923 cmp(r3, Operand(Smi::FromInt(0))); 4183 CmpSmiLiteral(r6, Smi::FromInt(0), r0);
3924 b(ne, call_runtime); 4184 bne(call_runtime);
3925 4185
3926 bind(&start); 4186 bind(&start);
3927 4187
3928 // Check that there are no elements. Register r2 contains the current JS 4188 // Check that there are no elements. Register r5 contains the current JS
3929 // object we've reached through the prototype chain. 4189 // object we've reached through the prototype chain.
3930 Label no_elements; 4190 Label no_elements;
3931 ldr(r2, FieldMemOperand(r2, JSObject::kElementsOffset)); 4191 LoadP(r5, FieldMemOperand(r5, JSObject::kElementsOffset));
3932 cmp(r2, empty_fixed_array_value); 4192 cmp(r5, empty_fixed_array_value);
3933 b(eq, &no_elements); 4193 beq(&no_elements);
3934 4194
3935 // Second chance, the object may be using the empty slow element dictionary. 4195 // Second chance, the object may be using the empty slow element dictionary.
3936 CompareRoot(r2, Heap::kEmptySlowElementDictionaryRootIndex); 4196 CompareRoot(r5, Heap::kEmptySlowElementDictionaryRootIndex);
3937 b(ne, call_runtime); 4197 bne(call_runtime);
3938 4198
3939 bind(&no_elements); 4199 bind(&no_elements);
3940 ldr(r2, FieldMemOperand(r1, Map::kPrototypeOffset)); 4200 LoadP(r5, FieldMemOperand(r4, Map::kPrototypeOffset));
3941 cmp(r2, null_value); 4201 cmp(r5, null_value);
3942 b(ne, &next); 4202 bne(&next);
3943 } 4203 }
3944 4204
3945 4205
4206 ////////////////////////////////////////////////////////////////////////////////
4207 //
4208 // New MacroAssembler Interfaces added for PPC
4209 //
4210 ////////////////////////////////////////////////////////////////////////////////
4211 void MacroAssembler::LoadIntLiteral(Register dst, int value) {
4212 mov(dst, Operand(value));
4213 }
4214
4215
4216 void MacroAssembler::LoadSmiLiteral(Register dst, Smi *smi) {
4217 mov(dst, Operand(smi));
4218 }
4219
4220
4221 void MacroAssembler::LoadDoubleLiteral(DoubleRegister result,
4222 double value,
4223 Register scratch) {
4224 #if V8_OOL_CONSTANT_POOL
4225 // TODO(mbrandy): enable extended constant pool usage for doubles.
4226 // See ARM commit e27ab337 for a reference.
4227 if (is_constant_pool_available() && !is_constant_pool_full()) {
4228 RelocInfo rinfo(pc_, value);
4229 ConstantPoolAddEntry(rinfo);
4230 #if V8_TARGET_ARCH_PPC64
4231 // We use 2 instruction sequence here for consistency with mov.
4232 li(scratch, Operand::Zero());
4233 lfdx(result, MemOperand(kConstantPoolRegister, scratch));
4234 #else
4235 lfd(result, MemOperand(kConstantPoolRegister, 0));
4236 #endif
4237 return;
4238 }
4239 #endif
4240
4241 // avoid gcc strict aliasing error using union cast
4242 union {
4243 double dval;
4244 #if V8_TARGET_ARCH_PPC64
4245 intptr_t ival;
4246 #else
4247 intptr_t ival[2];
4248 #endif
4249 } litVal;
4250
4251 litVal.dval = value;
4252
4253 #if V8_TARGET_ARCH_PPC64
4254 if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
4255 mov(scratch, Operand(litVal.ival));
4256 mtfprd(result, scratch);
4257 return;
4258 }
4259 #endif
4260
4261 addi(sp, sp, Operand(-kDoubleSize));
4262 #if V8_TARGET_ARCH_PPC64
4263 mov(scratch, Operand(litVal.ival));
4264 std(scratch, MemOperand(sp));
4265 #else
4266 LoadIntLiteral(scratch, litVal.ival[0]);
4267 stw(scratch, MemOperand(sp, 0));
4268 LoadIntLiteral(scratch, litVal.ival[1]);
4269 stw(scratch, MemOperand(sp, 4));
4270 #endif
4271 nop(); // LHS/RAW optimization
4272 lfd(result, MemOperand(sp, 0));
4273 addi(sp, sp, Operand(kDoubleSize));
4274 }
4275
4276
4277 void MacroAssembler::MovIntToDouble(DoubleRegister dst,
4278 Register src,
4279 Register scratch) {
4280 // sign-extend src to 64-bit
4281 #if V8_TARGET_ARCH_PPC64
4282 if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
4283 mtfprwa(dst, src);
4284 return;
4285 }
4286 #endif
4287
4288 DCHECK(!src.is(scratch));
4289 subi(sp, sp, Operand(kDoubleSize));
4290 #if V8_TARGET_ARCH_PPC64
4291 extsw(scratch, src);
4292 std(scratch, MemOperand(sp, 0));
4293 #else
4294 srawi(scratch, src, 31);
4295 stw(scratch, MemOperand(sp, Register::kExponentOffset));
4296 stw(src, MemOperand(sp, Register::kMantissaOffset));
4297 #endif
4298 nop(); // LHS/RAW optimization
4299 lfd(dst, MemOperand(sp, 0));
4300 addi(sp, sp, Operand(kDoubleSize));
4301 }
4302
4303
4304 void MacroAssembler::MovUnsignedIntToDouble(DoubleRegister dst,
4305 Register src,
4306 Register scratch) {
4307 // zero-extend src to 64-bit
4308 #if V8_TARGET_ARCH_PPC64
4309 if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
4310 mtfprwz(dst, src);
4311 return;
4312 }
4313 #endif
4314
4315 DCHECK(!src.is(scratch));
4316 subi(sp, sp, Operand(kDoubleSize));
4317 #if V8_TARGET_ARCH_PPC64
4318 clrldi(scratch, src, Operand(32));
4319 std(scratch, MemOperand(sp, 0));
4320 #else
4321 li(scratch, Operand::Zero());
4322 stw(scratch, MemOperand(sp, Register::kExponentOffset));
4323 stw(src, MemOperand(sp, Register::kMantissaOffset));
4324 #endif
4325 nop(); // LHS/RAW optimization
4326 lfd(dst, MemOperand(sp, 0));
4327 addi(sp, sp, Operand(kDoubleSize));
4328 }
4329
4330
4331 void MacroAssembler::MovInt64ToDouble(DoubleRegister dst,
4332 #if !V8_TARGET_ARCH_PPC64
4333 Register src_hi,
4334 #endif
4335 Register src) {
4336 #if V8_TARGET_ARCH_PPC64
4337 if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
4338 mtfprd(dst, src);
4339 return;
4340 }
4341 #endif
4342
4343 subi(sp, sp, Operand(kDoubleSize));
4344 #if V8_TARGET_ARCH_PPC64
4345 std(src, MemOperand(sp, 0));
4346 #else
4347 stw(src_hi, MemOperand(sp, Register::kExponentOffset));
4348 stw(src, MemOperand(sp, Register::kMantissaOffset));
4349 #endif
4350 nop(); // LHS/RAW optimization
4351 lfd(dst, MemOperand(sp, 0));
4352 addi(sp, sp, Operand(kDoubleSize));
4353 }
4354
4355
4356 #if V8_TARGET_ARCH_PPC64
4357 void MacroAssembler::MovInt64ComponentsToDouble(DoubleRegister dst,
4358 Register src_hi,
4359 Register src_lo,
4360 Register scratch) {
4361 if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
4362 sldi(scratch, src_hi, Operand(32));
4363 rldimi(scratch, src_lo, 0, 32);
4364 mtfprd(dst, scratch);
4365 return;
4366 }
4367
4368 subi(sp, sp, Operand(kDoubleSize));
4369 stw(src_hi, MemOperand(sp, Register::kExponentOffset));
4370 stw(src_lo, MemOperand(sp, Register::kMantissaOffset));
4371 nop(); // LHS/RAW optimization
4372 lfd(dst, MemOperand(sp));
4373 addi(sp, sp, Operand(kDoubleSize));
4374 }
4375 #endif
4376
4377
4378 void MacroAssembler::MovDoubleLowToInt(Register dst,
4379 DoubleRegister src) {
4380 #if V8_TARGET_ARCH_PPC64
4381 if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
4382 mffprwz(dst, src);
4383 return;
4384 }
4385 #endif
4386
4387 subi(sp, sp, Operand(kDoubleSize));
4388 stfd(src, MemOperand(sp));
4389 nop(); // LHS/RAW optimization
4390 lwz(dst, MemOperand(sp, Register::kMantissaOffset));
4391 addi(sp, sp, Operand(kDoubleSize));
4392 }
4393
4394
4395 void MacroAssembler::MovDoubleHighToInt(Register dst,
4396 DoubleRegister src) {
4397 #if V8_TARGET_ARCH_PPC64
4398 if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
4399 mffprd(dst, src);
4400 srdi(dst, dst, Operand(32));
4401 return;
4402 }
4403 #endif
4404
4405 subi(sp, sp, Operand(kDoubleSize));
4406 stfd(src, MemOperand(sp));
4407 nop(); // LHS/RAW optimization
4408 lwz(dst, MemOperand(sp, Register::kExponentOffset));
4409 addi(sp, sp, Operand(kDoubleSize));
4410 }
4411
4412
4413 void MacroAssembler::MovDoubleToInt64(
4414 #if !V8_TARGET_ARCH_PPC64
4415 Register dst_hi,
4416 #endif
4417 Register dst,
4418 DoubleRegister src) {
4419 #if V8_TARGET_ARCH_PPC64
4420 if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
4421 mffprd(dst, src);
4422 return;
4423 }
4424 #endif
4425
4426 subi(sp, sp, Operand(kDoubleSize));
4427 stfd(src, MemOperand(sp));
4428 nop(); // LHS/RAW optimization
4429 #if V8_TARGET_ARCH_PPC64
4430 ld(dst, MemOperand(sp, 0));
4431 #else
4432 lwz(dst_hi, MemOperand(sp, Register::kExponentOffset));
4433 lwz(dst, MemOperand(sp, Register::kMantissaOffset));
4434 #endif
4435 addi(sp, sp, Operand(kDoubleSize));
4436 }
4437
4438
4439 void MacroAssembler::Add(Register dst, Register src,
4440 intptr_t value, Register scratch) {
4441 if (is_int16(value)) {
4442 addi(dst, src, Operand(value));
4443 } else {
4444 mov(scratch, Operand(value));
4445 add(dst, src, scratch);
4446 }
4447 }
4448
4449
4450 void MacroAssembler::Cmpi(Register src1, const Operand& src2, Register scratch,
4451 CRegister cr) {
4452 intptr_t value = src2.immediate();
4453 if (is_int16(value)) {
4454 cmpi(src1, src2, cr);
4455 } else {
4456 mov(scratch, src2);
4457 cmp(src1, scratch, cr);
4458 }
4459 }
4460
4461
4462 void MacroAssembler::Cmpli(Register src1, const Operand& src2, Register scratch,
4463 CRegister cr) {
4464 intptr_t value = src2.immediate();
4465 if (is_uint16(value)) {
4466 cmpli(src1, src2, cr);
4467 } else {
4468 mov(scratch, src2);
4469 cmpl(src1, scratch, cr);
4470 }
4471 }
4472
4473
4474 void MacroAssembler::Cmpwi(Register src1, const Operand& src2,
4475 Register scratch, CRegister cr) {
4476 intptr_t value = src2.immediate();
4477 if (is_int16(value)) {
4478 cmpwi(src1, src2, cr);
4479 } else {
4480 mov(scratch, src2);
4481 cmpw(src1, scratch, cr);
4482 }
4483 }
4484
4485
4486 void MacroAssembler::Cmplwi(Register src1, const Operand& src2,
4487 Register scratch, CRegister cr) {
4488 intptr_t value = src2.immediate();
4489 if (is_uint16(value)) {
4490 cmplwi(src1, src2, cr);
4491 } else {
4492 mov(scratch, src2);
4493 cmplw(src1, scratch, cr);
4494 }
4495 }
4496
4497
4498 void MacroAssembler::And(Register ra, Register rs, const Operand& rb,
4499 RCBit rc) {
4500 if (rb.is_reg()) {
4501 and_(ra, rs, rb.rm(), rc);
4502 } else {
4503 if (is_uint16(rb.imm_) && RelocInfo::IsNone(rb.rmode_) && rc == SetRC) {
4504 andi(ra, rs, rb);
4505 } else {
4506 // mov handles the relocation.
4507 DCHECK(!rs.is(r0));
4508 mov(r0, rb);
4509 and_(ra, rs, r0, rc);
4510 }
4511 }
4512 }
4513
4514
4515 void MacroAssembler::Or(Register ra, Register rs, const Operand& rb, RCBit rc) {
4516 if (rb.is_reg()) {
4517 orx(ra, rs, rb.rm(), rc);
4518 } else {
4519 if (is_uint16(rb.imm_) && RelocInfo::IsNone(rb.rmode_) && rc == LeaveRC) {
4520 ori(ra, rs, rb);
4521 } else {
4522 // mov handles the relocation.
4523 DCHECK(!rs.is(r0));
4524 mov(r0, rb);
4525 orx(ra, rs, r0, rc);
4526 }
4527 }
4528 }
4529
4530
4531 void MacroAssembler::Xor(Register ra, Register rs, const Operand& rb,
4532 RCBit rc) {
4533 if (rb.is_reg()) {
4534 xor_(ra, rs, rb.rm(), rc);
4535 } else {
4536 if (is_uint16(rb.imm_) && RelocInfo::IsNone(rb.rmode_) && rc == LeaveRC) {
4537 xori(ra, rs, rb);
4538 } else {
4539 // mov handles the relocation.
4540 DCHECK(!rs.is(r0));
4541 mov(r0, rb);
4542 xor_(ra, rs, r0, rc);
4543 }
4544 }
4545 }
4546
4547
4548 void MacroAssembler::CmpSmiLiteral(Register src1, Smi *smi, Register scratch,
4549 CRegister cr) {
4550 #if V8_TARGET_ARCH_PPC64
4551 LoadSmiLiteral(scratch, smi);
4552 cmp(src1, scratch, cr);
4553 #else
4554 Cmpi(src1, Operand(smi), scratch, cr);
4555 #endif
4556 }
4557
4558
4559 void MacroAssembler::CmplSmiLiteral(Register src1, Smi *smi, Register scratch,
4560 CRegister cr) {
4561 #if V8_TARGET_ARCH_PPC64
4562 LoadSmiLiteral(scratch, smi);
4563 cmpl(src1, scratch, cr);
4564 #else
4565 Cmpli(src1, Operand(smi), scratch, cr);
4566 #endif
4567 }
4568
4569
4570 void MacroAssembler::AddSmiLiteral(Register dst, Register src, Smi *smi,
4571 Register scratch) {
4572 #if V8_TARGET_ARCH_PPC64
4573 LoadSmiLiteral(scratch, smi);
4574 add(dst, src, scratch);
4575 #else
4576 Add(dst, src, reinterpret_cast<intptr_t>(smi), scratch);
4577 #endif
4578 }
4579
4580
4581 void MacroAssembler::SubSmiLiteral(Register dst, Register src, Smi *smi,
4582 Register scratch) {
4583 #if V8_TARGET_ARCH_PPC64
4584 LoadSmiLiteral(scratch, smi);
4585 sub(dst, src, scratch);
4586 #else
4587 Add(dst, src, -(reinterpret_cast<intptr_t>(smi)), scratch);
4588 #endif
4589 }
4590
4591
4592 void MacroAssembler::AndSmiLiteral(Register dst, Register src, Smi *smi,
4593 Register scratch, RCBit rc) {
4594 #if V8_TARGET_ARCH_PPC64
4595 LoadSmiLiteral(scratch, smi);
4596 and_(dst, src, scratch, rc);
4597 #else
4598 And(dst, src, Operand(smi), rc);
4599 #endif
4600 }
4601
4602
4603 // Load a "pointer" sized value from the memory location
4604 void MacroAssembler::LoadP(Register dst, const MemOperand& mem,
4605 Register scratch) {
4606 int offset = mem.offset();
4607
4608 if (!scratch.is(no_reg) && !is_int16(offset)) {
4609 /* cannot use d-form */
4610 LoadIntLiteral(scratch, offset);
4611 #if V8_TARGET_ARCH_PPC64
4612 ldx(dst, MemOperand(mem.ra(), scratch));
4613 #else
4614 lwzx(dst, MemOperand(mem.ra(), scratch));
4615 #endif
4616 } else {
4617 #if V8_TARGET_ARCH_PPC64
4618 int misaligned = (offset & 3);
4619 if (misaligned) {
4620 // adjust base to conform to offset alignment requirements
4621 // Todo: enhance to use scratch if dst is unsuitable
4622 DCHECK(!dst.is(r0));
4623 addi(dst, mem.ra(), Operand((offset & 3) - 4));
4624 ld(dst, MemOperand(dst, (offset & ~3) + 4));
4625 } else {
4626 ld(dst, mem);
4627 }
4628 #else
4629 lwz(dst, mem);
4630 #endif
4631 }
4632 }
4633
4634
4635 // Store a "pointer" sized value to the memory location
4636 void MacroAssembler::StoreP(Register src, const MemOperand& mem,
4637 Register scratch) {
4638 int offset = mem.offset();
4639
4640 if (!scratch.is(no_reg) && !is_int16(offset)) {
4641 /* cannot use d-form */
4642 LoadIntLiteral(scratch, offset);
4643 #if V8_TARGET_ARCH_PPC64
4644 stdx(src, MemOperand(mem.ra(), scratch));
4645 #else
4646 stwx(src, MemOperand(mem.ra(), scratch));
4647 #endif
4648 } else {
4649 #if V8_TARGET_ARCH_PPC64
4650 int misaligned = (offset & 3);
4651 if (misaligned) {
4652 // adjust base to conform to offset alignment requirements
4653 // a suitable scratch is required here
4654 DCHECK(!scratch.is(no_reg));
4655 if (scratch.is(r0)) {
4656 LoadIntLiteral(scratch, offset);
4657 stdx(src, MemOperand(mem.ra(), scratch));
4658 } else {
4659 addi(scratch, mem.ra(), Operand((offset & 3) - 4));
4660 std(src, MemOperand(scratch, (offset & ~3) + 4));
4661 }
4662 } else {
4663 std(src, mem);
4664 }
4665 #else
4666 stw(src, mem);
4667 #endif
4668 }
4669 }
4670
4671 void MacroAssembler::LoadWordArith(Register dst, const MemOperand& mem,
4672 Register scratch) {
4673 int offset = mem.offset();
4674
4675 if (!scratch.is(no_reg) && !is_int16(offset)) {
4676 /* cannot use d-form */
4677 LoadIntLiteral(scratch, offset);
4678 #if V8_TARGET_ARCH_PPC64
4679 // lwax(dst, MemOperand(mem.ra(), scratch));
4680 DCHECK(0); // lwax not yet implemented
4681 #else
4682 lwzx(dst, MemOperand(mem.ra(), scratch));
4683 #endif
4684 } else {
4685 #if V8_TARGET_ARCH_PPC64
4686 int misaligned = (offset & 3);
4687 if (misaligned) {
4688 // adjust base to conform to offset alignment requirements
4689 // Todo: enhance to use scratch if dst is unsuitable
4690 DCHECK(!dst.is(r0));
4691 addi(dst, mem.ra(), Operand((offset & 3) - 4));
4692 lwa(dst, MemOperand(dst, (offset & ~3) + 4));
4693 } else {
4694 lwa(dst, mem);
4695 }
4696 #else
4697 lwz(dst, mem);
4698 #endif
4699 }
4700 }
4701
4702
4703 // Variable length depending on whether offset fits into immediate field
4704 // MemOperand currently only supports d-form
4705 void MacroAssembler::LoadWord(Register dst, const MemOperand& mem,
4706 Register scratch, bool updateForm) {
4707 Register base = mem.ra();
4708 int offset = mem.offset();
4709
4710 bool use_dform = true;
4711 if (!is_int16(offset)) {
4712 use_dform = false;
4713 LoadIntLiteral(scratch, offset);
4714 }
4715
4716 if (!updateForm) {
4717 if (use_dform) {
4718 lwz(dst, mem);
4719 } else {
4720 lwzx(dst, MemOperand(base, scratch));
4721 }
4722 } else {
4723 if (use_dform) {
4724 lwzu(dst, mem);
4725 } else {
4726 lwzux(dst, MemOperand(base, scratch));
4727 }
4728 }
4729 }
4730
4731
4732 // Variable length depending on whether offset fits into immediate field
4733 // MemOperand current only supports d-form
4734 void MacroAssembler::StoreWord(Register src, const MemOperand& mem,
4735 Register scratch, bool updateForm) {
4736 Register base = mem.ra();
4737 int offset = mem.offset();
4738
4739 bool use_dform = true;
4740 if (!is_int16(offset)) {
4741 use_dform = false;
4742 LoadIntLiteral(scratch, offset);
4743 }
4744
4745 if (!updateForm) {
4746 if (use_dform) {
4747 stw(src, mem);
4748 } else {
4749 stwx(src, MemOperand(base, scratch));
4750 }
4751 } else {
4752 if (use_dform) {
4753 stwu(src, mem);
4754 } else {
4755 stwux(src, MemOperand(base, scratch));
4756 }
4757 }
4758 }
4759
4760
4761 // Variable length depending on whether offset fits into immediate field
4762 // MemOperand currently only supports d-form
4763 void MacroAssembler::LoadHalfWord(Register dst, const MemOperand& mem,
4764 Register scratch, bool updateForm) {
4765 Register base = mem.ra();
4766 int offset = mem.offset();
4767
4768 bool use_dform = true;
4769 if (!is_int16(offset)) {
4770 use_dform = false;
4771 LoadIntLiteral(scratch, offset);
4772 }
4773
4774 if (!updateForm) {
4775 if (use_dform) {
4776 lhz(dst, mem);
4777 } else {
4778 lhzx(dst, MemOperand(base, scratch));
4779 }
4780 } else {
4781 // If updateForm is ever true, then lhzu will
4782 // need to be implemented
4783 assert(0);
4784 #if 0 // LoadHalfWord w\ update not yet needed
4785 if (use_dform) {
4786 lhzu(dst, mem);
4787 } else {
4788 lhzux(dst, MemOperand(base, scratch));
4789 }
4790 #endif
4791 }
4792 }
4793
4794
4795 // Variable length depending on whether offset fits into immediate field
4796 // MemOperand current only supports d-form
4797 void MacroAssembler::StoreHalfWord(Register src, const MemOperand& mem,
4798 Register scratch, bool updateForm) {
4799 Register base = mem.ra();
4800 int offset = mem.offset();
4801
4802 bool use_dform = true;
4803 if (!is_int16(offset)) {
4804 use_dform = false;
4805 LoadIntLiteral(scratch, offset);
4806 }
4807
4808 if (!updateForm) {
4809 if (use_dform) {
4810 sth(src, mem);
4811 } else {
4812 sthx(src, MemOperand(base, scratch));
4813 }
4814 } else {
4815 // If updateForm is ever true, then sthu will
4816 // need to be implemented
4817 assert(0);
4818 #if 0 // StoreHalfWord w\ update not yet needed
4819 if (use_dform) {
4820 sthu(src, mem);
4821 } else {
4822 sthux(src, MemOperand(base, scratch));
4823 }
4824 #endif
4825 }
4826 }
4827
4828
4829 // Variable length depending on whether offset fits into immediate field
4830 // MemOperand currently only supports d-form
4831 void MacroAssembler::LoadByte(Register dst, const MemOperand& mem,
4832 Register scratch, bool updateForm) {
4833 Register base = mem.ra();
4834 int offset = mem.offset();
4835
4836 bool use_dform = true;
4837 if (!is_int16(offset)) {
4838 use_dform = false;
4839 LoadIntLiteral(scratch, offset);
4840 }
4841
4842 if (!updateForm) {
4843 if (use_dform) {
4844 lbz(dst, mem);
4845 } else {
4846 lbzx(dst, MemOperand(base, scratch));
4847 }
4848 } else {
4849 // If updateForm is ever true, then lbzu will
4850 // need to be implemented
4851 assert(0);
4852 #if 0 // LoadByte w\ update not yet needed
4853 if (use_dform) {
4854 lbzu(dst, mem);
4855 } else {
4856 lbzux(dst, MemOperand(base, scratch));
4857 }
4858 #endif
4859 }
4860 }
4861
4862
4863 // Variable length depending on whether offset fits into immediate field
4864 // MemOperand current only supports d-form
4865 void MacroAssembler::StoreByte(Register src, const MemOperand& mem,
4866 Register scratch, bool updateForm) {
4867 Register base = mem.ra();
4868 int offset = mem.offset();
4869
4870 bool use_dform = true;
4871 if (!is_int16(offset)) {
4872 use_dform = false;
4873 LoadIntLiteral(scratch, offset);
4874 }
4875
4876 if (!updateForm) {
4877 if (use_dform) {
4878 stb(src, mem);
4879 } else {
4880 stbx(src, MemOperand(base, scratch));
4881 }
4882 } else {
4883 // If updateForm is ever true, then stbu will
4884 // need to be implemented
4885 assert(0);
4886 #if 0 // StoreByte w\ update not yet needed
4887 if (use_dform) {
4888 stbu(src, mem);
4889 } else {
4890 stbux(src, MemOperand(base, scratch));
4891 }
4892 #endif
4893 }
4894 }
4895
4896
4897 void MacroAssembler::LoadRepresentation(Register dst,
4898 const MemOperand& mem,
4899 Representation r,
4900 Register scratch) {
4901 DCHECK(!r.IsDouble());
4902 if (r.IsInteger8()) {
4903 LoadByte(dst, mem, scratch);
4904 extsb(dst, dst);
4905 } else if (r.IsUInteger8()) {
4906 LoadByte(dst, mem, scratch);
4907 } else if (r.IsInteger16()) {
4908 LoadHalfWord(dst, mem, scratch);
4909 extsh(dst, dst);
4910 } else if (r.IsUInteger16()) {
4911 LoadHalfWord(dst, mem, scratch);
4912 #if V8_TARGET_ARCH_PPC64
4913 } else if (r.IsInteger32()) {
4914 LoadWord(dst, mem, scratch);
4915 #endif
4916 } else {
4917 LoadP(dst, mem, scratch);
4918 }
4919 }
4920
4921
4922 void MacroAssembler::StoreRepresentation(Register src,
4923 const MemOperand& mem,
4924 Representation r,
4925 Register scratch) {
4926 DCHECK(!r.IsDouble());
4927 if (r.IsInteger8() || r.IsUInteger8()) {
4928 StoreByte(src, mem, scratch);
4929 } else if (r.IsInteger16() || r.IsUInteger16()) {
4930 StoreHalfWord(src, mem, scratch);
4931 #if V8_TARGET_ARCH_PPC64
4932 } else if (r.IsInteger32()) {
4933 StoreWord(src, mem, scratch);
4934 #endif
4935 } else {
4936 if (r.IsHeapObject()) {
4937 AssertNotSmi(src);
4938 } else if (r.IsSmi()) {
4939 AssertSmi(src);
4940 }
4941 StoreP(src, mem, scratch);
4942 }
4943 }
4944
4945
3946 void MacroAssembler::TestJSArrayForAllocationMemento( 4946 void MacroAssembler::TestJSArrayForAllocationMemento(
3947 Register receiver_reg, 4947 Register receiver_reg,
3948 Register scratch_reg, 4948 Register scratch_reg,
3949 Label* no_memento_found) { 4949 Label* no_memento_found) {
3950 ExternalReference new_space_start = 4950 ExternalReference new_space_start =
3951 ExternalReference::new_space_start(isolate()); 4951 ExternalReference::new_space_start(isolate());
3952 ExternalReference new_space_allocation_top = 4952 ExternalReference new_space_allocation_top =
3953 ExternalReference::new_space_allocation_top_address(isolate()); 4953 ExternalReference::new_space_allocation_top_address(isolate());
3954 add(scratch_reg, receiver_reg, 4954 addi(scratch_reg, receiver_reg,
3955 Operand(JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag)); 4955 Operand(JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag));
3956 cmp(scratch_reg, Operand(new_space_start)); 4956 Cmpi(scratch_reg, Operand(new_space_start), r0);
3957 b(lt, no_memento_found); 4957 blt(no_memento_found);
3958 mov(ip, Operand(new_space_allocation_top)); 4958 mov(ip, Operand(new_space_allocation_top));
3959 ldr(ip, MemOperand(ip)); 4959 LoadP(ip, MemOperand(ip));
3960 cmp(scratch_reg, ip); 4960 cmp(scratch_reg, ip);
3961 b(gt, no_memento_found); 4961 bgt(no_memento_found);
3962 ldr(scratch_reg, MemOperand(scratch_reg, -AllocationMemento::kSize)); 4962 LoadP(scratch_reg, MemOperand(scratch_reg, -AllocationMemento::kSize));
3963 cmp(scratch_reg, 4963 Cmpi(scratch_reg,
3964 Operand(isolate()->factory()->allocation_memento_map())); 4964 Operand(isolate()->factory()->allocation_memento_map()), r0);
3965 } 4965 }
3966 4966
3967 4967
3968 Register GetRegisterThatIsNotOneOf(Register reg1, 4968 Register GetRegisterThatIsNotOneOf(Register reg1,
3969 Register reg2, 4969 Register reg2,
3970 Register reg3, 4970 Register reg3,
3971 Register reg4, 4971 Register reg4,
3972 Register reg5, 4972 Register reg5,
3973 Register reg6) { 4973 Register reg6) {
3974 RegList regs = 0; 4974 RegList regs = 0;
(...skipping 18 matching lines...) Expand all
3993 Register object, 4993 Register object,
3994 Register scratch0, 4994 Register scratch0,
3995 Register scratch1, 4995 Register scratch1,
3996 Label* found) { 4996 Label* found) {
3997 DCHECK(!scratch1.is(scratch0)); 4997 DCHECK(!scratch1.is(scratch0));
3998 Factory* factory = isolate()->factory(); 4998 Factory* factory = isolate()->factory();
3999 Register current = scratch0; 4999 Register current = scratch0;
4000 Label loop_again; 5000 Label loop_again;
4001 5001
4002 // scratch contained elements pointer. 5002 // scratch contained elements pointer.
4003 mov(current, object); 5003 mr(current, object);
4004 5004
4005 // Loop based on the map going up the prototype chain. 5005 // Loop based on the map going up the prototype chain.
4006 bind(&loop_again); 5006 bind(&loop_again);
4007 ldr(current, FieldMemOperand(current, HeapObject::kMapOffset)); 5007 LoadP(current, FieldMemOperand(current, HeapObject::kMapOffset));
4008 ldr(scratch1, FieldMemOperand(current, Map::kBitField2Offset)); 5008 lbz(scratch1, FieldMemOperand(current, Map::kBitField2Offset));
4009 DecodeField<Map::ElementsKindBits>(scratch1); 5009 DecodeField<Map::ElementsKindBits>(scratch1);
4010 cmp(scratch1, Operand(DICTIONARY_ELEMENTS)); 5010 cmpi(scratch1, Operand(DICTIONARY_ELEMENTS));
4011 b(eq, found); 5011 beq(found);
4012 ldr(current, FieldMemOperand(current, Map::kPrototypeOffset)); 5012 LoadP(current, FieldMemOperand(current, Map::kPrototypeOffset));
4013 cmp(current, Operand(factory->null_value())); 5013 Cmpi(current, Operand(factory->null_value()), r0);
4014 b(ne, &loop_again); 5014 bne(&loop_again);
4015 } 5015 }
4016 5016
4017 5017
4018 #ifdef DEBUG 5018 #ifdef DEBUG
4019 bool AreAliased(Register reg1, 5019 bool AreAliased(Register reg1,
4020 Register reg2, 5020 Register reg2,
4021 Register reg3, 5021 Register reg3,
4022 Register reg4, 5022 Register reg4,
4023 Register reg5, 5023 Register reg5,
4024 Register reg6, 5024 Register reg6,
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
4068 DCHECK(masm_.pc_ == address_ + size_); 5068 DCHECK(masm_.pc_ == address_ + size_);
4069 DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 5069 DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
4070 } 5070 }
4071 5071
4072 5072
4073 void CodePatcher::Emit(Instr instr) { 5073 void CodePatcher::Emit(Instr instr) {
4074 masm()->emit(instr); 5074 masm()->emit(instr);
4075 } 5075 }
4076 5076
4077 5077
4078 void CodePatcher::Emit(Address addr) {
4079 masm()->emit(reinterpret_cast<Instr>(addr));
4080 }
4081
4082
4083 void CodePatcher::EmitCondition(Condition cond) { 5078 void CodePatcher::EmitCondition(Condition cond) {
4084 Instr instr = Assembler::instr_at(masm_.pc_); 5079 Instr instr = Assembler::instr_at(masm_.pc_);
4085 instr = (instr & ~kCondMask) | cond; 5080 switch (cond) {
5081 case eq:
5082 instr = (instr & ~kCondMask) | BT;
5083 break;
5084 case ne:
5085 instr = (instr & ~kCondMask) | BF;
5086 break;
5087 default:
5088 UNIMPLEMENTED();
5089 }
4086 masm_.emit(instr); 5090 masm_.emit(instr);
4087 } 5091 }
4088 5092
4089 5093
4090 void MacroAssembler::TruncatingDiv(Register result, 5094 void MacroAssembler::TruncatingDiv(Register result,
4091 Register dividend, 5095 Register dividend,
4092 int32_t divisor) { 5096 int32_t divisor) {
4093 DCHECK(!dividend.is(result)); 5097 DCHECK(!dividend.is(result));
4094 DCHECK(!dividend.is(ip)); 5098 DCHECK(!dividend.is(r0));
4095 DCHECK(!result.is(ip)); 5099 DCHECK(!result.is(r0));
4096 MultiplierAndShift ms(divisor); 5100 MultiplierAndShift ms(divisor);
4097 mov(ip, Operand(ms.multiplier())); 5101 mov(r0, Operand(ms.multiplier()));
4098 smull(ip, result, dividend, ip); 5102 mulhw(result, dividend, r0);
4099 if (divisor > 0 && ms.multiplier() < 0) { 5103 if (divisor > 0 && ms.multiplier() < 0) {
4100 add(result, result, Operand(dividend)); 5104 add(result, result, dividend);
4101 } 5105 }
4102 if (divisor < 0 && ms.multiplier() > 0) { 5106 if (divisor < 0 && ms.multiplier() > 0) {
4103 sub(result, result, Operand(dividend)); 5107 sub(result, result, dividend);
4104 } 5108 }
4105 if (ms.shift() > 0) mov(result, Operand(result, ASR, ms.shift())); 5109 if (ms.shift() > 0) srawi(result, result, ms.shift());
4106 add(result, result, Operand(dividend, LSR, 31)); 5110 ExtractBit(r0, dividend, 31);
5111 add(result, result, r0);
4107 } 5112 }
4108 5113
4109 5114
4110 } } // namespace v8::internal 5115 } } // namespace v8::internal
4111 5116
4112 #endif // V8_TARGET_ARCH_ARM 5117 #endif // V8_TARGET_ARCH_PPC
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698