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

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

Issue 11275184: First draft of the sh4 port Base URL: http://github.com/v8/v8.git@master
Patch Set: Use GYP and fixe some typos Created 8 years, 1 month 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
« no previous file with comments | « src/sh4/macro-assembler-sh4.h ('k') | src/sh4/map-sh4.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2011-2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include <limits.h> // For LONG_MIN, LONG_MAX.
29
30 #include "v8.h" 28 #include "v8.h"
31 29
32 #if defined(V8_TARGET_ARCH_ARM) 30 #if defined(V8_TARGET_ARCH_SH4)
33 31
34 #include "bootstrapper.h" 32 #include "bootstrapper.h"
35 #include "codegen.h" 33 #include "codegen.h"
36 #include "debug.h" 34 #include "debug.h"
37 #include "runtime.h" 35 #include "runtime.h"
38 36
37 #include "map-sh4.h" // Define register map
38
39 namespace v8 { 39 namespace v8 {
40 namespace internal { 40 namespace internal {
41 41
42 #ifdef DEBUG
43 #define RECORD_LINE() RecordFunctionLine(__FUNCTION__, __LINE__)
44 #else
45 #define RECORD_LINE() ((void)0)
46 #endif
47
42 MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size) 48 MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
43 : Assembler(arg_isolate, buffer, size), 49 : Assembler(arg_isolate, buffer, size),
44 generating_stub_(false), 50 generating_stub_(false),
45 allow_stub_calls_(true), 51 allow_stub_calls_(true),
46 has_frame_(false) { 52 has_frame_(false) {
47 if (isolate() != NULL) { 53 if (isolate() != NULL) {
48 code_object_ = Handle<Object>(isolate()->heap()->undefined_value(), 54 code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
49 isolate()); 55 isolate());
50 } 56 }
51 } 57 }
52 58
53 59
54 // We always generate arm code, never thumb code, even if V8 is compiled to 60 void MacroAssembler::Jump(Register Rd) {
55 // thumb, so we require inter-working support 61 jmp(Rd);
56 #if defined(__thumb__) && !defined(USE_THUMB_INTERWORK)
57 #error "flag -mthumb-interwork missing"
58 #endif
59
60
61 // We do not support thumb inter-working with an arm architecture not supporting
62 // the blx instruction (below v5t). If you know what CPU you are compiling for
63 // you can use -march=armv7 or similar.
64 #if defined(USE_THUMB_INTERWORK) && !defined(CAN_USE_THUMB_INSTRUCTIONS)
65 # error "For thumb inter-working we require an architecture which supports blx"
66 #endif
67
68
69 // Using bx does not yield better code, so use it only when required
70 #if defined(USE_THUMB_INTERWORK)
71 #define USE_BX 1
72 #endif
73
74
75 void MacroAssembler::Jump(Register target, Condition cond) {
76 #if USE_BX
77 bx(target, cond);
78 #else
79 mov(pc, Operand(target), LeaveCC, cond);
80 #endif
81 } 62 }
82 63
83 64
84 void MacroAssembler::Jump(intptr_t target, RelocInfo::Mode rmode, 65 void MacroAssembler::Jump(intptr_t target, RelocInfo::Mode rmode) {
85 Condition cond) { 66 RECORD_LINE();
86 #if USE_BX 67 mov(sh4_ip, Operand(target, rmode));
87 mov(ip, Operand(target, rmode)); 68 jmp(sh4_ip);
88 bx(ip, cond);
89 #else
90 mov(pc, Operand(target, rmode), LeaveCC, cond);
91 #endif
92 } 69 }
93 70
94 71
95 void MacroAssembler::Jump(Address target, RelocInfo::Mode rmode, 72 void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode) {
96 Condition cond) {
97 ASSERT(!RelocInfo::IsCodeTarget(rmode));
98 Jump(reinterpret_cast<intptr_t>(target), rmode, cond);
99 }
100
101
102 void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode,
103 Condition cond) {
104 ASSERT(RelocInfo::IsCodeTarget(rmode)); 73 ASSERT(RelocInfo::IsCodeTarget(rmode));
105 // 'code' is always generated ARM code, never THUMB code 74 RECORD_LINE();
106 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond); 75 Jump(reinterpret_cast<intptr_t>(code.location()), rmode);
107 }
108
109
110 int MacroAssembler::CallSize(Register target, Condition cond) {
111 #ifdef USE_BLX
112 return kInstrSize;
113 #else
114 return 2 * kInstrSize;
115 #endif
116 }
117
118
119 void MacroAssembler::Call(Register target, Condition cond) {
120 // Block constant pool for the call instruction sequence.
121 BlockConstPoolScope block_const_pool(this);
122 Label start;
123 bind(&start);
124 #ifdef USE_BLX
125 blx(target, cond);
126 #else
127 // set lr for return at current pc + 8
128 mov(lr, Operand(pc), LeaveCC, cond);
129 mov(pc, Operand(target), LeaveCC, cond);
130 #endif
131 ASSERT_EQ(CallSize(target, cond), SizeOfCodeGeneratedSince(&start));
132 }
133
134
135 int MacroAssembler::CallSize(
136 Address target, RelocInfo::Mode rmode, Condition cond) {
137 int size = 2 * kInstrSize;
138 Instr mov_instr = cond | MOV | LeaveCC;
139 intptr_t immediate = reinterpret_cast<intptr_t>(target);
140 if (!Operand(immediate, rmode).is_single_instruction(this, mov_instr)) {
141 size += kInstrSize;
142 }
143 return size;
144 }
145
146
147 int MacroAssembler::CallSizeNotPredictableCodeSize(
148 Address target, RelocInfo::Mode rmode, Condition cond) {
149 int size = 2 * kInstrSize;
150 Instr mov_instr = cond | MOV | LeaveCC;
151 intptr_t immediate = reinterpret_cast<intptr_t>(target);
152 if (!Operand(immediate, rmode).is_single_instruction(NULL, mov_instr)) {
153 size += kInstrSize;
154 }
155 return size;
156 }
157
158
159 void MacroAssembler::Call(Address target,
160 RelocInfo::Mode rmode,
161 Condition cond,
162 TargetAddressStorageMode mode) {
163 // Block constant pool for the call instruction sequence.
164 BlockConstPoolScope block_const_pool(this);
165 Label start;
166 bind(&start);
167
168 bool old_predictable_code_size = predictable_code_size();
169 if (mode == NEVER_INLINE_TARGET_ADDRESS) {
170 set_predictable_code_size(true);
171 }
172
173 #ifdef USE_BLX
174 // Call sequence on V7 or later may be :
175 // movw ip, #... @ call address low 16
176 // movt ip, #... @ call address high 16
177 // blx ip
178 // @ return address
179 // Or for pre-V7 or values that may be back-patched
180 // to avoid ICache flushes:
181 // ldr ip, [pc, #...] @ call address
182 // blx ip
183 // @ return address
184
185 // Statement positions are expected to be recorded when the target
186 // address is loaded. The mov method will automatically record
187 // positions when pc is the target, since this is not the case here
188 // we have to do it explicitly.
189 positions_recorder()->WriteRecordedPositions();
190
191 mov(ip, Operand(reinterpret_cast<int32_t>(target), rmode));
192 blx(ip, cond);
193
194 #else
195 // Set lr for return at current pc + 8.
196 mov(lr, Operand(pc), LeaveCC, cond);
197 // Emit a ldr<cond> pc, [pc + offset of target in constant pool].
198 mov(pc, Operand(reinterpret_cast<int32_t>(target), rmode), LeaveCC, cond);
199 #endif
200 ASSERT_EQ(CallSize(target, rmode, cond), SizeOfCodeGeneratedSince(&start));
201 if (mode == NEVER_INLINE_TARGET_ADDRESS) {
202 set_predictable_code_size(old_predictable_code_size);
203 }
204 }
205
206
207 int MacroAssembler::CallSize(Handle<Code> code,
208 RelocInfo::Mode rmode,
209 TypeFeedbackId ast_id,
210 Condition cond) {
211 return CallSize(reinterpret_cast<Address>(code.location()), rmode, cond);
212 } 76 }
213 77
214 78
215 void MacroAssembler::Call(Handle<Code> code, 79 void MacroAssembler::Call(Handle<Code> code,
216 RelocInfo::Mode rmode, 80 RelocInfo::Mode rmode,
217 TypeFeedbackId ast_id, 81 TypeFeedbackId ast_id) {
218 Condition cond, 82 // TODO(stm): check whether this is necessary
219 TargetAddressStorageMode mode) { 83 // Label start;
220 Label start; 84 // bind(&start);
221 bind(&start); 85
86 RECORD_LINE();
222 ASSERT(RelocInfo::IsCodeTarget(rmode)); 87 ASSERT(RelocInfo::IsCodeTarget(rmode));
223 if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) { 88 if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) {
224 SetRecordedAstId(ast_id); 89 SetRecordedAstId(ast_id);
225 rmode = RelocInfo::CODE_TARGET_WITH_ID; 90 rmode = RelocInfo::CODE_TARGET_WITH_ID;
226 } 91 }
227 // 'code' is always generated ARM code, never THUMB code 92 jsr(code, rmode, sh4_ip);
228 Call(reinterpret_cast<Address>(code.location()), rmode, cond, mode); 93
94 // TODO(stm): check whether this is necessary
95 // ASSERT_EQ(CallSize(code, rmode, ast_id, cond),
96 // SizeOfCodeGeneratedSince(&start));
229 } 97 }
230 98
231 99
232 void MacroAssembler::Ret(Condition cond) { 100 void MacroAssembler::Ret(int drop) {
233 #if USE_BX 101 Drop(drop);
234 bx(lr, cond); 102 Ret();
235 #else
236 mov(pc, Operand(lr), LeaveCC, cond);
237 #endif
238 } 103 }
239 104
240 105
241 void MacroAssembler::Drop(int count, Condition cond) { 106 void MacroAssembler::Move(Register dst, Handle<Object> value) {
242 if (count > 0) { 107 RECORD_LINE();
243 add(sp, sp, Operand(count * kPointerSize), LeaveCC, cond); 108 mov(dst, Operand(value));
109 }
110
111
112 void MacroAssembler::Move(Register dst, Register src) {
113 if (!dst.is(src)) {
114 RECORD_LINE();
115 mov(dst, src);
244 } 116 }
245 } 117 }
246 118
247 119
248 void MacroAssembler::Ret(int drop, Condition cond) { 120 void MacroAssembler::Ubfx(Register dst, Register src, int lsb, int width) {
249 Drop(drop, cond); 121 ASSERT(!dst.is(sh4_rtmp) && !src.is(sh4_rtmp));
250 Ret(cond); 122 ASSERT(lsb >= 0 && lsb < 32);
251 } 123 ASSERT(width > 0 && width <= 32);
252 124 ASSERT(width + lsb <= 32);
253 125 // Extract unsigned value from bits src1[lsb..lsb+width-1] into dst
254 void MacroAssembler::Swap(Register reg1, 126 int32_t mask1 = width < 32 ? (1<<width)-1 : -1;
255 Register reg2, 127 int32_t mask = mask1 << lsb;
256 Register scratch, 128 RECORD_LINE();
257 Condition cond) { 129 land(dst, src, Operand(mask));
258 if (scratch.is(no_reg)) { 130 if (lsb != 0) {
259 eor(reg1, reg1, Operand(reg2), LeaveCC, cond); 131 RECORD_LINE();
260 eor(reg2, reg2, Operand(reg1), LeaveCC, cond); 132 lsr(dst, dst, Operand(lsb));
261 eor(reg1, reg1, Operand(reg2), LeaveCC, cond);
262 } else {
263 mov(scratch, reg1, LeaveCC, cond);
264 mov(reg1, reg2, LeaveCC, cond);
265 mov(reg2, scratch, LeaveCC, cond);
266 } 133 }
267 } 134 }
268 135
269 136
270 void MacroAssembler::Call(Label* target) { 137 void MacroAssembler::Sbfx(Register dst, Register src1, int lsb, int width) {
271 bl(target); 138 ASSERT(!dst.is(sh4_rtmp) && !src1.is(sh4_rtmp));
272 } 139 ASSERT(lsb >= 0 && lsb < 32);
273 140 ASSERT(width > 0 && width <= 32);
274 141 ASSERT(width + lsb <= 32);
275 void MacroAssembler::Push(Handle<Object> handle) { 142 int32_t mask1 = width < 32 ? (1<<width)-1 : -1;
276 mov(ip, Operand(handle)); 143 int32_t mask = mask1 << lsb;
277 push(ip); 144 land(dst, src1, Operand(mask));
278 } 145 int shift_up = 32 - lsb - width;
279 146 int shift_down = lsb + shift_up;
280 147 if (shift_up != 0) {
281 void MacroAssembler::Move(Register dst, Handle<Object> value) { 148 lsl(dst, dst, Operand(shift_up));
282 mov(dst, Operand(value)); 149 }
283 } 150 if (shift_down != 0) {
284 151 asr(dst, dst, Operand(shift_down));
285
286 void MacroAssembler::Move(Register dst, Register src, Condition cond) {
287 if (!dst.is(src)) {
288 mov(dst, src, LeaveCC, cond);
289 } 152 }
290 } 153 }
291 154
292
293 void MacroAssembler::Move(DoubleRegister dst, DoubleRegister src) {
294 ASSERT(CpuFeatures::IsSupported(VFP2));
295 CpuFeatures::Scope scope(VFP2);
296 if (!dst.is(src)) {
297 vmov(dst, src);
298 }
299 }
300
301
302 void MacroAssembler::And(Register dst, Register src1, const Operand& src2,
303 Condition cond) {
304 if (!src2.is_reg() &&
305 !src2.must_output_reloc_info(this) &&
306 src2.immediate() == 0) {
307 mov(dst, Operand(0, RelocInfo::NONE), LeaveCC, cond);
308 } else if (!src2.is_single_instruction(this) &&
309 !src2.must_output_reloc_info(this) &&
310 CpuFeatures::IsSupported(ARMv7) &&
311 IsPowerOf2(src2.immediate() + 1)) {
312 ubfx(dst, src1, 0,
313 WhichPowerOf2(static_cast<uint32_t>(src2.immediate()) + 1), cond);
314 } else {
315 and_(dst, src1, src2, LeaveCC, cond);
316 }
317 }
318
319
320 void MacroAssembler::Ubfx(Register dst, Register src1, int lsb, int width,
321 Condition cond) {
322 ASSERT(lsb < 32);
323 if (!CpuFeatures::IsSupported(ARMv7) || predictable_code_size()) {
324 int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
325 and_(dst, src1, Operand(mask), LeaveCC, cond);
326 if (lsb != 0) {
327 mov(dst, Operand(dst, LSR, lsb), LeaveCC, cond);
328 }
329 } else {
330 ubfx(dst, src1, lsb, width, cond);
331 }
332 }
333
334
335 void MacroAssembler::Sbfx(Register dst, Register src1, int lsb, int width,
336 Condition cond) {
337 ASSERT(lsb < 32);
338 if (!CpuFeatures::IsSupported(ARMv7) || predictable_code_size()) {
339 int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
340 and_(dst, src1, Operand(mask), LeaveCC, cond);
341 int shift_up = 32 - lsb - width;
342 int shift_down = lsb + shift_up;
343 if (shift_up != 0) {
344 mov(dst, Operand(dst, LSL, shift_up), LeaveCC, cond);
345 }
346 if (shift_down != 0) {
347 mov(dst, Operand(dst, ASR, shift_down), LeaveCC, cond);
348 }
349 } else {
350 sbfx(dst, src1, lsb, width, cond);
351 }
352 }
353
354 155
355 void MacroAssembler::Bfi(Register dst, 156 void MacroAssembler::Bfi(Register dst,
356 Register src, 157 Register src,
357 Register scratch, 158 Register scratch,
358 int lsb, 159 int lsb,
359 int width, 160 int width) {
360 Condition cond) {
361 ASSERT(0 <= lsb && lsb < 32); 161 ASSERT(0 <= lsb && lsb < 32);
362 ASSERT(0 <= width && width < 32); 162 ASSERT(0 <= width && width <= 32);
363 ASSERT(lsb + width < 32); 163 ASSERT(lsb + width <= 32);
364 ASSERT(!scratch.is(dst)); 164 ASSERT(!dst.is(src) && !dst.is(scratch));
365 if (width == 0) return; 165 if (width == 0) return;
366 if (!CpuFeatures::IsSupported(ARMv7) || predictable_code_size()) { 166 if (width == 32) {
367 int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1); 167 mov(dst, src);
368 bic(dst, dst, Operand(mask)); 168 return;
369 and_(scratch, src, Operand((1 << width) - 1));
370 mov(scratch, Operand(scratch, LSL, lsb));
371 orr(dst, dst, scratch);
372 } else {
373 bfi(dst, src, lsb, width, cond);
374 } 169 }
170 int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
171 bic(dst, dst, Operand(mask));
172 land(scratch, src, Operand((1 << width) - 1));
173 lsl(scratch, scratch, Operand(lsb));
174 orr(dst, dst, scratch);
375 } 175 }
376 176
377 177
378 void MacroAssembler::Bfc(Register dst, Register src, int lsb, int width, 178 void MacroAssembler::Bfc(Register dst, int lsb, int width) {
379 Condition cond) { 179 ASSERT(!dst.is(sh4_rtmp));
380 ASSERT(lsb < 32); 180 ASSERT(lsb >= 0 && lsb < 32);
381 if (!CpuFeatures::IsSupported(ARMv7) || predictable_code_size()) { 181 ASSERT(width > 0 && width <= 32);
382 int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1); 182 ASSERT(width + lsb <= 32);
383 bic(dst, src, Operand(mask)); 183 // Clear bits [lsb..lsb+width-1] of dst
384 } else { 184 int32_t mask1 = width < 32 ? (1<<width)-1 : -1;
385 Move(dst, src, cond); 185 int32_t mask = mask1 << lsb;
386 bfc(dst, lsb, width, cond); 186 RECORD_LINE();
387 } 187 land(dst, dst, Operand(~mask));
388 } 188 }
389 189
390 190
391 void MacroAssembler::Usat(Register dst, int satpos, const Operand& src, 191 void MacroAssembler::Usat(Register dst, int satpos, Register src) {
392 Condition cond) { 192 ASSERT((satpos > 0) && (satpos <= 31));
393 if (!CpuFeatures::IsSupported(ARMv7) || predictable_code_size()) {
394 ASSERT(!dst.is(pc) && !src.rm().is(pc));
395 ASSERT((satpos >= 0) && (satpos <= 31));
396 193
397 // These asserts are required to ensure compatibility with the ARMv7
398 // implementation.
399 ASSERT((src.shift_op() == ASR) || (src.shift_op() == LSL));
400 ASSERT(src.rs().is(no_reg));
401
402 Label done;
403 int satval = (1 << satpos) - 1; 194 int satval = (1 << satpos) - 1;
404 195
405 if (cond != al) { 196 if (!src.is(dst)) {
406 b(NegateCondition(cond), &done); // Skip saturate if !condition.
407 }
408 if (!(src.is_reg() && dst.is(src.rm()))) {
409 mov(dst, src); 197 mov(dst, src);
410 } 198 }
411 tst(dst, Operand(~satval)); 199 cmpge(dst, Operand(0));
412 b(eq, &done); 200 mov(dst, Operand(0), f); // 0 if negative.
413 mov(dst, Operand(0, RelocInfo::NONE), LeaveCC, mi); // 0 if negative. 201 cmpgt(dst, Operand(satval));
414 mov(dst, Operand(satval), LeaveCC, pl); // satval if positive. 202 mov(dst, Operand(satval), t); // satval if > satval
415 bind(&done);
416 } else {
417 usat(dst, satpos, src, cond);
418 }
419 } 203 }
420 204
421 205
422 void MacroAssembler::LoadRoot(Register destination, 206 void MacroAssembler::LoadRoot(Register destination,
423 Heap::RootListIndex index, 207 Heap::RootListIndex index) {
424 Condition cond) { 208 RECORD_LINE();
425 ldr(destination, MemOperand(kRootRegister, index << kPointerSizeLog2), cond); 209 ldr(destination, MemOperand(roots, index << kPointerSizeLog2));
426 } 210 }
427 211
428 212
429 void MacroAssembler::StoreRoot(Register source, 213 void MacroAssembler::StoreRoot(Register source,
430 Heap::RootListIndex index, 214 Heap::RootListIndex index) {
431 Condition cond) { 215 RECORD_LINE();
432 str(source, MemOperand(kRootRegister, index << kPointerSizeLog2), cond); 216 str(source, MemOperand(roots, index << kPointerSizeLog2));
433 } 217 }
434 218
435 219
436 void MacroAssembler::LoadHeapObject(Register result, 220 void MacroAssembler::LoadHeapObject(Register result,
437 Handle<HeapObject> object) { 221 Handle<HeapObject> object) {
438 if (isolate()->heap()->InNewSpace(*object)) { 222 if (isolate()->heap()->InNewSpace(*object)) {
439 Handle<JSGlobalPropertyCell> cell = 223 Handle<JSGlobalPropertyCell> cell =
440 isolate()->factory()->NewJSGlobalPropertyCell(object); 224 isolate()->factory()->NewJSGlobalPropertyCell(object);
441 mov(result, Operand(cell)); 225 mov(result, Operand(cell));
442 ldr(result, FieldMemOperand(result, JSGlobalPropertyCell::kValueOffset)); 226 ldr(result, FieldMemOperand(result, JSGlobalPropertyCell::kValueOffset));
443 } else { 227 } else {
444 mov(result, Operand(object)); 228 mov(result, Operand(object));
445 } 229 }
446 } 230 }
447 231
448 232
449 void MacroAssembler::InNewSpace(Register object, 233 void MacroAssembler::InNewSpace(Register object,
450 Register scratch, 234 Register scratch,
451 Condition cond, 235 Condition cond,
452 Label* branch) { 236 Label* branch) {
237 ASSERT(!object.is(sh4_ip) && !scratch.is(sh4_ip));
238 ASSERT(!object.is(sh4_rtmp) && !scratch.is(sh4_rtmp));
453 ASSERT(cond == eq || cond == ne); 239 ASSERT(cond == eq || cond == ne);
454 and_(scratch, object, Operand(ExternalReference::new_space_mask(isolate()))); 240 RECORD_LINE();
455 cmp(scratch, Operand(ExternalReference::new_space_start(isolate()))); 241 land(scratch, object,
242 Operand(ExternalReference::new_space_mask(isolate())));
243 mov(sh4_ip, Operand(ExternalReference::new_space_start(isolate())));
244 cmpeq(scratch, sh4_ip);
456 b(cond, branch); 245 b(cond, branch);
457 } 246 }
458 247
459 248
460 void MacroAssembler::RecordWriteField( 249 void MacroAssembler::RecordWriteField(
461 Register object, 250 Register object,
462 int offset, 251 int offset,
463 Register value, 252 Register value,
464 Register dst, 253 Register dst,
465 LinkRegisterStatus lr_status, 254 LinkRegisterStatus lr_status,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 void MacroAssembler::RecordWrite(Register object, 302 void MacroAssembler::RecordWrite(Register object,
514 Register address, 303 Register address,
515 Register value, 304 Register value,
516 LinkRegisterStatus lr_status, 305 LinkRegisterStatus lr_status,
517 SaveFPRegsMode fp_mode, 306 SaveFPRegsMode fp_mode,
518 RememberedSetAction remembered_set_action, 307 RememberedSetAction remembered_set_action,
519 SmiCheck smi_check) { 308 SmiCheck smi_check) {
520 // The compiled code assumes that record write doesn't change the 309 // The compiled code assumes that record write doesn't change the
521 // context register, so we check that none of the clobbered 310 // context register, so we check that none of the clobbered
522 // registers are cp. 311 // registers are cp.
523 ASSERT(!address.is(cp) && !value.is(cp)); 312 ASSERT(!object.is(cp) && !address.is(cp) && !value.is(cp));
313 ASSERT(!object.is(sh4_rtmp) && !address.is(sh4_rtmp) && !value.is(sh4_rtmp));
314 ASSERT(!object.is(sh4_ip) && !address.is(sh4_ip) && !value.is(sh4_ip));
524 315
525 if (emit_debug_code()) { 316 if (emit_debug_code()) {
526 ldr(ip, MemOperand(address)); 317 ldr(ip, MemOperand(address));
527 cmp(ip, value); 318 cmp(ip, value);
528 Check(eq, "Wrong address or value passed to RecordWrite"); 319 Check(eq, "Wrong address or value passed to RecordWrite");
529 } 320 }
530 321
531 Label done; 322 Label done;
532 323
533 if (smi_check == INLINE_SMI_CHECK) { 324 if (smi_check == INLINE_SMI_CHECK) {
534 ASSERT_EQ(0, kSmiTag); 325 ASSERT_EQ(0, kSmiTag);
535 tst(value, Operand(kSmiTagMask)); 326 tst(value, Operand(kSmiTagMask));
536 b(eq, &done); 327 b(eq, &done);
537 } 328 }
538 329
539 CheckPageFlag(value, 330 CheckPageFlag(value,
540 value, // Used as scratch. 331 value, // Used as scratch.
541 MemoryChunk::kPointersToHereAreInterestingMask, 332 MemoryChunk::kPointersToHereAreInterestingMask,
542 eq, 333 eq,
543 &done); 334 &done);
544 CheckPageFlag(object, 335 CheckPageFlag(object,
545 value, // Used as scratch. 336 value, // Used as scratch.
546 MemoryChunk::kPointersFromHereAreInterestingMask, 337 MemoryChunk::kPointersFromHereAreInterestingMask,
547 eq, 338 eq,
548 &done); 339 &done);
549 340
550 // Record the actual write. 341 // Record the actual write.
551 if (lr_status == kLRHasNotBeenSaved) { 342 if (lr_status == kLRHasNotBeenSaved) {
552 push(lr); 343 push(pr);
553 } 344 }
554 RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode); 345 RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode);
555 CallStub(&stub); 346 CallStub(&stub);
556 if (lr_status == kLRHasNotBeenSaved) { 347 if (lr_status == kLRHasNotBeenSaved) {
557 pop(lr); 348 pop(pr);
558 } 349 }
559 350
560 bind(&done); 351 bind(&done);
561 352
562 // Clobber clobbered registers when running with the debug-code flag 353 // Clobber clobbered registers when running with the debug-code flag
563 // turned on to provoke errors. 354 // turned on to provoke errors.
564 if (emit_debug_code()) { 355 if (emit_debug_code()) {
565 mov(address, Operand(BitCast<int32_t>(kZapValue + 12))); 356 mov(address, Operand(BitCast<int32_t>(kZapValue + 12)));
566 mov(value, Operand(BitCast<int32_t>(kZapValue + 16))); 357 mov(value, Operand(BitCast<int32_t>(kZapValue + 16)));
567 } 358 }
(...skipping 23 matching lines...) Expand all
591 str(scratch, MemOperand(ip)); 382 str(scratch, MemOperand(ip));
592 // Call stub on end of buffer. 383 // Call stub on end of buffer.
593 // Check for end of buffer. 384 // Check for end of buffer.
594 tst(scratch, Operand(StoreBuffer::kStoreBufferOverflowBit)); 385 tst(scratch, Operand(StoreBuffer::kStoreBufferOverflowBit));
595 if (and_then == kFallThroughAtEnd) { 386 if (and_then == kFallThroughAtEnd) {
596 b(eq, &done); 387 b(eq, &done);
597 } else { 388 } else {
598 ASSERT(and_then == kReturnAtEnd); 389 ASSERT(and_then == kReturnAtEnd);
599 Ret(eq); 390 Ret(eq);
600 } 391 }
601 push(lr); 392 push(pr);
602 StoreBufferOverflowStub store_buffer_overflow = 393 StoreBufferOverflowStub store_buffer_overflow =
603 StoreBufferOverflowStub(fp_mode); 394 StoreBufferOverflowStub(fp_mode);
604 CallStub(&store_buffer_overflow); 395 CallStub(&store_buffer_overflow);
605 pop(lr); 396 pop(pr);
606 bind(&done); 397 bind(&done);
607 if (and_then == kReturnAtEnd) { 398 if (and_then == kReturnAtEnd) {
608 Ret(); 399 Ret();
609 } 400 }
610 } 401 }
611 402
612 403
613 // Push and pop all registers that can hold pointers.
614 void MacroAssembler::PushSafepointRegisters() {
615 // Safepoints expect a block of contiguous register values starting with r0:
616 ASSERT(((1 << kNumSafepointSavedRegisters) - 1) == kSafepointSavedRegisters);
617 // Safepoints expect a block of kNumSafepointRegisters values on the
618 // stack, so adjust the stack for unsaved registers.
619 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
620 ASSERT(num_unsaved >= 0);
621 sub(sp, sp, Operand(num_unsaved * kPointerSize));
622 stm(db_w, sp, kSafepointSavedRegisters);
623 }
624
625
626 void MacroAssembler::PopSafepointRegisters() {
627 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
628 ldm(ia_w, sp, kSafepointSavedRegisters);
629 add(sp, sp, Operand(num_unsaved * kPointerSize));
630 }
631
632
633 void MacroAssembler::PushSafepointRegistersAndDoubles() {
634 PushSafepointRegisters();
635 sub(sp, sp, Operand(DwVfpRegister::kNumAllocatableRegisters *
636 kDoubleSize));
637 for (int i = 0; i < DwVfpRegister::kNumAllocatableRegisters; i++) {
638 vstr(DwVfpRegister::FromAllocationIndex(i), sp, i * kDoubleSize);
639 }
640 }
641
642
643 void MacroAssembler::PopSafepointRegistersAndDoubles() {
644 for (int i = 0; i < DwVfpRegister::kNumAllocatableRegisters; i++) {
645 vldr(DwVfpRegister::FromAllocationIndex(i), sp, i * kDoubleSize);
646 }
647 add(sp, sp, Operand(DwVfpRegister::kNumAllocatableRegisters *
648 kDoubleSize));
649 PopSafepointRegisters();
650 }
651
652 void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register src,
653 Register dst) {
654 str(src, SafepointRegistersAndDoublesSlot(dst));
655 }
656
657
658 void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) {
659 str(src, SafepointRegisterSlot(dst));
660 }
661
662
663 void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) { 404 void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
664 ldr(dst, SafepointRegisterSlot(src)); 405 ldr(dst, SafepointRegisterSlot(src));
665 } 406 }
666 407
667 408
668 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) { 409 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
669 // The registers are pushed starting with the highest encoding, 410 UNIMPLEMENTED();
670 // which means that lowest encodings are closest to the stack pointer. 411 return 0;
671 ASSERT(reg_code >= 0 && reg_code < kNumSafepointRegisters);
672 return reg_code;
673 } 412 }
674 413
675 414
676 MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) { 415 MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
677 return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) * kPointerSize); 416 return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
678 } 417 }
679 418
680 419
681 MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
682 // General purpose registers are pushed last on the stack.
683 int doubles_size = DwVfpRegister::kNumAllocatableRegisters * kDoubleSize;
684 int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
685 return MemOperand(sp, doubles_size + register_offset);
686 }
687
688
689 void MacroAssembler::Ldrd(Register dst1, Register dst2, 420 void MacroAssembler::Ldrd(Register dst1, Register dst2,
690 const MemOperand& src, Condition cond) { 421 const MemOperand& src) {
691 ASSERT(src.rm().is(no_reg)); 422 ASSERT(src.rn().is(no_reg));
692 ASSERT(!dst1.is(lr)); // r14.
693 ASSERT_EQ(0, dst1.code() % 2); 423 ASSERT_EQ(0, dst1.code() % 2);
694 ASSERT_EQ(dst1.code() + 1, dst2.code()); 424 ASSERT_EQ(dst1.code() + 1, dst2.code());
695 425 ASSERT(!dst1.is(sh4_ip) && !dst2.is(sh4_ip));
696 // V8 does not use this addressing mode, so the fallback code 426 ASSERT(!dst1.is(sh4_rtmp) && !dst2.is(sh4_rtmp));
697 // below doesn't support it yet.
698 ASSERT((src.am() != PreIndex) && (src.am() != NegPreIndex));
699 427
700 // Generate two ldr instructions if ldrd is not available. 428 // Generate two ldr instructions if ldrd is not available.
701 if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size()) { 429 // TODO(STM): FPU
702 CpuFeatures::Scope scope(ARMv7); 430 {
703 ldrd(dst1, dst2, src, cond); 431 MemOperand src2(src);
704 } else { 432 src2.set_offset(src2.offset() + 4);
705 if ((src.am() == Offset) || (src.am() == NegOffset)) { 433 if (dst1.is(src.rm())) {
706 MemOperand src2(src); 434 ldr(dst2, src2);
707 src2.set_offset(src2.offset() + 4); 435 ldr(dst1, src);
708 if (dst1.is(src.rn())) { 436 } else {
709 ldr(dst2, src2, cond); 437 ldr(dst1, src);
710 ldr(dst1, src, cond); 438 ldr(dst2, src2);
711 } else {
712 ldr(dst1, src, cond);
713 ldr(dst2, src2, cond);
714 }
715 } else { // PostIndex or NegPostIndex.
716 ASSERT((src.am() == PostIndex) || (src.am() == NegPostIndex));
717 if (dst1.is(src.rn())) {
718 ldr(dst2, MemOperand(src.rn(), 4, Offset), cond);
719 ldr(dst1, src, cond);
720 } else {
721 MemOperand src2(src);
722 src2.set_offset(src2.offset() - 4);
723 ldr(dst1, MemOperand(src.rn(), 4, PostIndex), cond);
724 ldr(dst2, src2, cond);
725 }
726 } 439 }
727 } 440 }
728 } 441 }
729 442
730 443
731 void MacroAssembler::Strd(Register src1, Register src2, 444 void MacroAssembler::Strd(Register src1, Register src2,
732 const MemOperand& dst, Condition cond) { 445 const MemOperand& dst) {
733 ASSERT(dst.rm().is(no_reg)); 446 ASSERT(dst.rn().is(no_reg));
734 ASSERT(!src1.is(lr)); // r14.
735 ASSERT_EQ(0, src1.code() % 2); 447 ASSERT_EQ(0, src1.code() % 2);
736 ASSERT_EQ(src1.code() + 1, src2.code()); 448 ASSERT_EQ(src1.code() + 1, src2.code());
737 449 ASSERT(!src1.is(sh4_ip) && !src2.is(sh4_ip));
738 // V8 does not use this addressing mode, so the fallback code 450 ASSERT(!src1.is(sh4_rtmp) && !src2.is(sh4_rtmp));
739 // below doesn't support it yet.
740 ASSERT((dst.am() != PreIndex) && (dst.am() != NegPreIndex));
741 451
742 // Generate two str instructions if strd is not available. 452 // Generate two str instructions if strd is not available.
743 if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size()) { 453 // TODO(STM): FPU
744 CpuFeatures::Scope scope(ARMv7); 454 {
745 strd(src1, src2, dst, cond);
746 } else {
747 MemOperand dst2(dst); 455 MemOperand dst2(dst);
748 if ((dst.am() == Offset) || (dst.am() == NegOffset)) { 456 dst2.set_offset(dst2.offset() + 4);
749 dst2.set_offset(dst2.offset() + 4); 457 str(src1, dst);
750 str(src1, dst, cond); 458 str(src2, dst2);
751 str(src2, dst2, cond);
752 } else { // PostIndex or NegPostIndex.
753 ASSERT((dst.am() == PostIndex) || (dst.am() == NegPostIndex));
754 dst2.set_offset(dst2.offset() - 4);
755 str(src1, MemOperand(dst.rn(), 4, PostIndex), cond);
756 str(src2, dst2, cond);
757 }
758 }
759 }
760
761
762 void MacroAssembler::ClearFPSCRBits(const uint32_t bits_to_clear,
763 const Register scratch,
764 const Condition cond) {
765 vmrs(scratch, cond);
766 bic(scratch, scratch, Operand(bits_to_clear), LeaveCC, cond);
767 vmsr(scratch, cond);
768 }
769
770
771 void MacroAssembler::VFPCompareAndSetFlags(const DwVfpRegister src1,
772 const DwVfpRegister src2,
773 const Condition cond) {
774 // Compare and move FPSCR flags to the normal condition flags.
775 VFPCompareAndLoadFlags(src1, src2, pc, cond);
776 }
777
778 void MacroAssembler::VFPCompareAndSetFlags(const DwVfpRegister src1,
779 const double src2,
780 const Condition cond) {
781 // Compare and move FPSCR flags to the normal condition flags.
782 VFPCompareAndLoadFlags(src1, src2, pc, cond);
783 }
784
785
786 void MacroAssembler::VFPCompareAndLoadFlags(const DwVfpRegister src1,
787 const DwVfpRegister src2,
788 const Register fpscr_flags,
789 const Condition cond) {
790 // Compare and load FPSCR.
791 vcmp(src1, src2, cond);
792 vmrs(fpscr_flags, cond);
793 }
794
795 void MacroAssembler::VFPCompareAndLoadFlags(const DwVfpRegister src1,
796 const double src2,
797 const Register fpscr_flags,
798 const Condition cond) {
799 // Compare and load FPSCR.
800 vcmp(src1, src2, cond);
801 vmrs(fpscr_flags, cond);
802 }
803
804 void MacroAssembler::Vmov(const DwVfpRegister dst,
805 const double imm,
806 const Register scratch,
807 const Condition cond) {
808 ASSERT(CpuFeatures::IsEnabled(VFP2));
809 static const DoubleRepresentation minus_zero(-0.0);
810 static const DoubleRepresentation zero(0.0);
811 DoubleRepresentation value(imm);
812 // Handle special values first.
813 if (value.bits == zero.bits) {
814 vmov(dst, kDoubleRegZero, cond);
815 } else if (value.bits == minus_zero.bits) {
816 vneg(dst, kDoubleRegZero, cond);
817 } else {
818 vmov(dst, imm, scratch, cond);
819 } 459 }
820 } 460 }
821 461
822 462
823 void MacroAssembler::EnterFrame(StackFrame::Type type) { 463 void MacroAssembler::EnterFrame(StackFrame::Type type) {
824 // r0-r3: preserved 464 // r0-r3: must be preserved
825 stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); 465 RECORD_LINE();
826 mov(ip, Operand(Smi::FromInt(type))); 466 Push(pr, fp, cp);
827 push(ip); 467 mov(sh4_ip, Operand(Smi::FromInt(type)));
828 mov(ip, Operand(CodeObject())); 468 push(sh4_ip);
829 push(ip); 469 mov(sh4_ip, Operand(CodeObject()));
470 push(sh4_ip);
830 add(fp, sp, Operand(3 * kPointerSize)); // Adjust FP to point to saved FP. 471 add(fp, sp, Operand(3 * kPointerSize)); // Adjust FP to point to saved FP.
831 } 472 }
832 473
833 474
834 void MacroAssembler::LeaveFrame(StackFrame::Type type) { 475 void MacroAssembler::LeaveFrame(StackFrame::Type type) {
835 // r0: preserved 476 // r0: preserved
836 // r1: preserved 477 // r1: preserved
837 // r2: preserved 478 // r2: preserved
838 479
839 // Drop the execution stack down to the frame pointer and restore 480 // Drop the execution stack down to the frame pointer and restore
840 // the caller frame pointer and return address. 481 // the caller frame pointer and return address.
482 RECORD_LINE();
841 mov(sp, fp); 483 mov(sp, fp);
842 ldm(ia_w, sp, fp.bit() | lr.bit()); 484 Pop(pr, fp);
843 } 485 }
844 486
845 487
846 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { 488 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space,
847 // Set up the frame structure on the stack. 489 Register scratch) {
490 // Parameters are on stack as if calling JS function
491 // ARM -> ST40 mapping: ip -> scratch (defaults sh4_ip)
492
493 // r0, r1, cp: must be preserved
494 // sp, fp: input/output
495 // Actual clobbers: scratch (r2 by default)
496
497 // Setup the frame structure on the stack
848 ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); 498 ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement);
849 ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); 499 ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset);
850 ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); 500 ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
851 Push(lr, fp); 501
852 mov(fp, Operand(sp)); // Set up new frame pointer. 502 RECORD_LINE();
853 // Reserve room for saved entry sp and code object. 503 // Save PR and FP
854 sub(sp, sp, Operand(2 * kPointerSize)); 504 Push(pr, fp);
505 // Setup a new frame pointer
506 mov(fp, sp);
507
508 // Reserve room for saved entry sp and code object
509 sub(sp, sp, Operand(2*kPointerSize));
855 if (emit_debug_code()) { 510 if (emit_debug_code()) {
856 mov(ip, Operand(0)); 511 mov(scratch, Operand(0));
857 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); 512 str(scratch, MemOperand(fp, ExitFrameConstants::kSPOffset));
858 } 513 }
859 mov(ip, Operand(CodeObject())); 514
860 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); 515 mov(scratch, Operand(CodeObject()));
516 str(scratch, MemOperand(fp, ExitFrameConstants::kCodeOffset));
861 517
862 // Save the frame pointer and the context in top. 518 // Save the frame pointer and the context in top.
863 mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); 519 mov(scratch, Operand(ExternalReference(Isolate::kCEntryFPAddress,
864 str(fp, MemOperand(ip)); 520 isolate())));
865 mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); 521 str(fp, MemOperand(scratch));
866 str(cp, MemOperand(ip)); 522 mov(scratch, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
523 str(cp, MemOperand(scratch));
867 524
868 // Optionally save all double registers. 525 // Optionally save all double registers.
869 if (save_doubles) { 526 if (save_doubles) {
870 DwVfpRegister first = d0; 527 RECORD_LINE();
871 DwVfpRegister last = 528 UNIMPLEMENTED_BREAK();
872 DwVfpRegister::from_code(DwVfpRegister::kNumRegisters - 1);
873 vstm(db_w, sp, first, last);
874 // Note that d0 will be accessible at
875 // fp - 2 * kPointerSize - DwVfpRegister::kNumRegisters * kDoubleSize,
876 // since the sp slot and code slot were pushed after the fp.
877 } 529 }
878 530
879 // Reserve place for the return address and stack space and align the frame 531 // Reserve place for the return address and stack space and align the frame
880 // preparing for calling the runtime function. 532 // preparing for calling the runtime function.
881 const int frame_alignment = MacroAssembler::ActivationFrameAlignment(); 533 const int frame_alignment = OS::ActivationFrameAlignment();
882 sub(sp, sp, Operand((stack_space + 1) * kPointerSize)); 534 sub(sp, sp, Operand((stack_space + 1) * kPointerSize));
883 if (frame_alignment > 0) { 535 if (frame_alignment > 0) {
884 ASSERT(IsPowerOf2(frame_alignment)); 536 ASSERT(IsPowerOf2(frame_alignment));
885 and_(sp, sp, Operand(-frame_alignment)); 537 land(sp, sp, Operand(-frame_alignment));
886 } 538 }
887 539
888 // Set the exit frame sp value to point just before the return address 540 // Set the exit frame sp value to point just before the return address
889 // location. 541 // location.
890 add(ip, sp, Operand(kPointerSize)); 542 add(scratch, sp, Operand(kPointerSize));
891 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); 543 str(scratch, MemOperand(fp, ExitFrameConstants::kSPOffset));
544 }
545
546
547 void MacroAssembler::LeaveExitFrame(bool save_doubles,
548 Register argument_count) {
549 ASSERT(!argument_count.is(sh4_ip));
550 ASSERT(!argument_count.is(sh4_rtmp));
551 // input: argument_count
552 // r0, r1: results must be preserved
553 // sp: stack pointer
554 // fp: frame pointer
555
556 // Actual clobbers: r3 and ip
557 // r4 should be preserved: see the end of RegExpExecStub::Generate
558
559 RECORD_LINE();
560 if (save_doubles) {
561 RECORD_LINE();
562 UNIMPLEMENTED_BREAK();
563 }
564
565 // Clear top frame.
566 mov(r3, Operand(0, RelocInfo::NONE));
567 mov(sh4_ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
568 str(r3, MemOperand(sh4_ip));
569
570 // Restore current context from top and clear it in debug mode.
571 mov(sh4_ip, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
572 ldr(cp, MemOperand(sh4_ip));
573 #ifdef DEBUG
574 str(r3, MemOperand(sh4_ip));
575 #endif
576
577 // Tear down the exit frame, pop the arguments, and return.
578 mov(sp, fp);
579
580 Pop(pr, fp);
581 if (argument_count.is_valid()) {
582 ASSERT(!argument_count.is(r3));
583 lsl(r3, argument_count, Operand(kPointerSizeLog2));
584 add(sp, sp, r3);
585 }
892 } 586 }
893 587
894 588
895 void MacroAssembler::InitializeNewString(Register string, 589 void MacroAssembler::InitializeNewString(Register string,
896 Register length, 590 Register length,
897 Heap::RootListIndex map_index, 591 Heap::RootListIndex map_index,
898 Register scratch1, 592 Register scratch1,
899 Register scratch2) { 593 Register scratch2) {
900 mov(scratch1, Operand(length, LSL, kSmiTagSize)); 594 RECORD_LINE();
595 lsl(scratch1, length, Operand(kSmiTagSize));
901 LoadRoot(scratch2, map_index); 596 LoadRoot(scratch2, map_index);
902 str(scratch1, FieldMemOperand(string, String::kLengthOffset)); 597 str(scratch1, FieldMemOperand(string, String::kLengthOffset));
903 mov(scratch1, Operand(String::kEmptyHashField)); 598 mov(scratch1, Operand(String::kEmptyHashField));
904 str(scratch2, FieldMemOperand(string, HeapObject::kMapOffset)); 599 str(scratch2, FieldMemOperand(string, HeapObject::kMapOffset));
905 str(scratch1, FieldMemOperand(string, String::kHashFieldOffset)); 600 str(scratch1, FieldMemOperand(string, String::kHashFieldOffset));
906 } 601 }
907 602
908 603
909 int MacroAssembler::ActivationFrameAlignment() {
910 #if defined(V8_HOST_ARCH_ARM)
911 // Running on the real platform. Use the alignment as mandated by the local
912 // environment.
913 // Note: This will break if we ever start generating snapshots on one ARM
914 // platform for another ARM platform with a different alignment.
915 return OS::ActivationFrameAlignment();
916 #else // defined(V8_HOST_ARCH_ARM)
917 // If we are using the simulator then we should always align to the expected
918 // alignment. As the simulator is used to generate snapshots we do not know
919 // if the target platform will need alignment, so this is controlled from a
920 // flag.
921 return FLAG_sim_stack_alignment;
922 #endif // defined(V8_HOST_ARCH_ARM)
923 }
924
925
926 void MacroAssembler::LeaveExitFrame(bool save_doubles,
927 Register argument_count) {
928 // Optionally restore all double registers.
929 if (save_doubles) {
930 // Calculate the stack location of the saved doubles and restore them.
931 const int offset = 2 * kPointerSize;
932 sub(r3, fp, Operand(offset + DwVfpRegister::kNumRegisters * kDoubleSize));
933 DwVfpRegister first = d0;
934 DwVfpRegister last =
935 DwVfpRegister::from_code(DwVfpRegister::kNumRegisters - 1);
936 vldm(ia, r3, first, last);
937 }
938
939 // Clear top frame.
940 mov(r3, Operand(0, RelocInfo::NONE));
941 mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
942 str(r3, MemOperand(ip));
943
944 // Restore current context from top and clear it in debug mode.
945 mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
946 ldr(cp, MemOperand(ip));
947 #ifdef DEBUG
948 str(r3, MemOperand(ip));
949 #endif
950
951 // Tear down the exit frame, pop the arguments, and return.
952 mov(sp, Operand(fp));
953 ldm(ia_w, sp, fp.bit() | lr.bit());
954 if (argument_count.is_valid()) {
955 add(sp, sp, Operand(argument_count, LSL, kPointerSizeLog2));
956 }
957 }
958
959 void MacroAssembler::GetCFunctionDoubleResult(const DoubleRegister dst) {
960 ASSERT(CpuFeatures::IsSupported(VFP2));
961 if (use_eabi_hardfloat()) {
962 Move(dst, d0);
963 } else {
964 vmov(dst, r0, r1);
965 }
966 }
967
968
969 void MacroAssembler::SetCallKind(Register dst, CallKind call_kind) { 604 void MacroAssembler::SetCallKind(Register dst, CallKind call_kind) {
970 // This macro takes the dst register to make the code more readable 605 // This macro takes the dst register to make the code more readable
971 // at the call sites. However, the dst register has to be r5 to 606 // at the call sites. However, the dst register has to be r5 to
972 // follow the calling convention which requires the call type to be 607 // follow the calling convention which requires the call type to be
973 // in r5. 608 // in r5.
974 ASSERT(dst.is(r5)); 609 ASSERT(dst.is(r5));
975 if (call_kind == CALL_AS_FUNCTION) { 610 if (call_kind == CALL_AS_FUNCTION) {
976 mov(dst, Operand(Smi::FromInt(1))); 611 mov(dst, Operand(Smi::FromInt(1)));
977 } else { 612 } else {
978 mov(dst, Operand(Smi::FromInt(0))); 613 mov(dst, Operand(Smi::FromInt(0)));
979 } 614 }
980 } 615 }
981 616
982 617
983 void MacroAssembler::InvokePrologue(const ParameterCount& expected, 618 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
984 const ParameterCount& actual, 619 const ParameterCount& actual,
985 Handle<Code> code_constant, 620 Handle<Code> code_constant,
986 Register code_reg, 621 Register code_reg,
987 Label* done, 622 Label* done,
988 bool* definitely_mismatches, 623 bool* definitely_mismatches,
989 InvokeFlag flag, 624 InvokeFlag flag,
990 const CallWrapper& call_wrapper, 625 const CallWrapper& call_wrapper,
991 CallKind call_kind) { 626 CallKind call_kind) {
627 ASSERT(!code_reg.is(sh4_ip));
628 ASSERT(!code_reg.is(sh4_rtmp));
992 bool definitely_matches = false; 629 bool definitely_matches = false;
993 *definitely_mismatches = false; 630 *definitely_mismatches = false;
994 Label regular_invoke; 631 Label regular_invoke;
995 632
996 // Check whether the expected and actual arguments count match. If not, 633 // Check whether the expected and actual arguments count match. If not,
997 // setup registers according to contract with ArgumentsAdaptorTrampoline: 634 // setup registers according to contract with ArgumentsAdaptorTrampoline:
635 // ARM -> SH4
998 // r0: actual arguments count 636 // r0: actual arguments count
999 // r1: function (passed through to callee) 637 // r1: function (passed through to callee)
1000 // r2: expected arguments count 638 // r2: expected arguments count
1001 // r3: callee code entry 639 // r3: callee code entry
1002 640
1003 // The code below is made a lot easier because the calling code already sets 641 // The code below is made a lot easier because the calling code already sets
1004 // up actual and expected registers according to the contract if values are 642 // up actual and expected registers according to the contract if values are
1005 // passed in registers. 643 // passed in registers.
1006 ASSERT(actual.is_immediate() || actual.reg().is(r0)); 644 ASSERT(actual.is_immediate() || actual.reg().is(r0));
1007 ASSERT(expected.is_immediate() || expected.reg().is(r2)); 645 ASSERT(expected.is_immediate() || expected.reg().is(r2));
1008 ASSERT((!code_constant.is_null() && code_reg.is(no_reg)) || code_reg.is(r3)); 646 ASSERT((!code_constant.is_null() && code_reg.is(no_reg)) || code_reg.is(r3));
1009 647
648 RECORD_LINE();
1010 if (expected.is_immediate()) { 649 if (expected.is_immediate()) {
1011 ASSERT(actual.is_immediate()); 650 ASSERT(actual.is_immediate());
1012 if (expected.immediate() == actual.immediate()) { 651 if (expected.immediate() == actual.immediate()) {
1013 definitely_matches = true; 652 definitely_matches = true;
1014 } else { 653 } else {
1015 mov(r0, Operand(actual.immediate())); 654 mov(r0, Operand(actual.immediate()));
1016 const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel; 655 const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
1017 if (expected.immediate() == sentinel) { 656 if (expected.immediate() == sentinel) {
1018 // Don't worry about adapting arguments for builtins that 657 // Don't worry about adapting arguments for builtins that
1019 // don't want that done. Skip adaption code by making it look 658 // don't want that done. Skip adaption code by making it look
1020 // like we have a match between expected and actual number of 659 // like we have a match between expected and actual number of
1021 // arguments. 660 // arguments.
1022 definitely_matches = true; 661 definitely_matches = true;
1023 } else { 662 } else {
1024 *definitely_mismatches = true; 663 *definitely_mismatches = true;
1025 mov(r2, Operand(expected.immediate())); 664 mov(r2, Operand(expected.immediate()));
1026 } 665 }
1027 } 666 }
1028 } else { 667 } else {
1029 if (actual.is_immediate()) { 668 if (actual.is_immediate()) {
1030 cmp(expected.reg(), Operand(actual.immediate())); 669 cmpeq(expected.reg(), Operand((actual.immediate())));
1031 b(eq, &regular_invoke); 670 bt(&regular_invoke);
1032 mov(r0, Operand(actual.immediate())); 671 mov(r0, Operand(actual.immediate()));
1033 } else { 672 } else {
1034 cmp(expected.reg(), Operand(actual.reg())); 673 cmpeq(expected.reg(), actual.reg());
1035 b(eq, &regular_invoke); 674 bt(&regular_invoke);
1036 } 675 }
1037 } 676 }
1038 677
678 RECORD_LINE();
1039 if (!definitely_matches) { 679 if (!definitely_matches) {
1040 if (!code_constant.is_null()) { 680 if (!code_constant.is_null()) {
1041 mov(r3, Operand(code_constant)); 681 mov(r3, Operand(code_constant));
1042 add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); 682 add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
1043 } 683 }
1044 684
1045 Handle<Code> adaptor = 685 Handle<Code> adaptor =
1046 isolate()->builtins()->ArgumentsAdaptorTrampoline(); 686 isolate()->builtins()->ArgumentsAdaptorTrampoline();
1047 if (flag == CALL_FUNCTION) { 687 if (flag == CALL_FUNCTION) {
1048 call_wrapper.BeforeCall(CallSize(adaptor)); 688 call_wrapper.BeforeCall(2 * kInstrSize);
1049 SetCallKind(r5, call_kind); 689 SetCallKind(r5, call_kind);
1050 Call(adaptor); 690 Call(adaptor);
1051 call_wrapper.AfterCall(); 691 call_wrapper.AfterCall();
1052 if (!*definitely_mismatches) { 692 if (!*definitely_mismatches) {
1053 b(done); 693 b(done);
1054 } 694 }
1055 } else { 695 } else {
1056 SetCallKind(r5, call_kind); 696 SetCallKind(r5, call_kind);
1057 Jump(adaptor, RelocInfo::CODE_TARGET); 697 Jump(adaptor, RelocInfo::CODE_TARGET);
1058 } 698 }
1059 bind(&regular_invoke); 699 bind(&regular_invoke);
1060 } 700 }
1061 } 701 }
1062 702
1063 703
1064 void MacroAssembler::InvokeCode(Register code, 704 void MacroAssembler::InvokeCode(Register code,
1065 const ParameterCount& expected, 705 const ParameterCount& expected,
1066 const ParameterCount& actual, 706 const ParameterCount& actual,
1067 InvokeFlag flag, 707 InvokeFlag flag,
1068 const CallWrapper& call_wrapper, 708 const CallWrapper& call_wrapper,
1069 CallKind call_kind) { 709 CallKind call_kind) {
1070 // You can't call a function without a valid frame. 710 // You can't call a function without a valid frame.
1071 ASSERT(flag == JUMP_FUNCTION || has_frame()); 711 ASSERT(flag == JUMP_FUNCTION || has_frame());
1072 712
1073 Label done; 713 Label done;
1074 bool definitely_mismatches = false; 714 bool definitely_mismatches = false;
715 // r1: must hold function pointer
716 // actual: must be r0 if register
717 ASSERT(actual.is_immediate() || actual.reg().is(r0));
718 ASSERT(!code.is(sh4_ip) && !code.is(sh4_rtmp) && !code.is(r5));
719
720 RECORD_LINE();
1075 InvokePrologue(expected, actual, Handle<Code>::null(), code, 721 InvokePrologue(expected, actual, Handle<Code>::null(), code,
1076 &done, &definitely_mismatches, flag, 722 &done, &definitely_mismatches, flag,
1077 call_wrapper, call_kind); 723 call_wrapper, call_kind);
1078 if (!definitely_mismatches) { 724 if (!definitely_mismatches) {
1079 if (flag == CALL_FUNCTION) { 725 if (flag == CALL_FUNCTION) {
1080 call_wrapper.BeforeCall(CallSize(code)); 726 call_wrapper.BeforeCall(2 * kInstrSize);
1081 SetCallKind(r5, call_kind); 727 SetCallKind(r5, call_kind);
1082 Call(code); 728 jsr(code);
1083 call_wrapper.AfterCall(); 729 call_wrapper.AfterCall();
1084 } else { 730 } else {
1085 ASSERT(flag == JUMP_FUNCTION); 731 ASSERT(flag == JUMP_FUNCTION);
1086 SetCallKind(r5, call_kind); 732 SetCallKind(r5, call_kind);
1087 Jump(code); 733 Jump(code);
1088 } 734 }
1089 735
1090 // Continue here if InvokePrologue does handle the invocation due to 736 // Continue here if InvokePrologue does handle the invocation due to
1091 // mismatched parameter counts. 737 // mismatched parameter counts.
1092 bind(&done); 738 bind(&done);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1131 CallKind call_kind) { 777 CallKind call_kind) {
1132 // You can't call a function without a valid frame. 778 // You can't call a function without a valid frame.
1133 ASSERT(flag == JUMP_FUNCTION || has_frame()); 779 ASSERT(flag == JUMP_FUNCTION || has_frame());
1134 780
1135 // Contract with called JS functions requires that function is passed in r1. 781 // Contract with called JS functions requires that function is passed in r1.
1136 ASSERT(fun.is(r1)); 782 ASSERT(fun.is(r1));
1137 783
1138 Register expected_reg = r2; 784 Register expected_reg = r2;
1139 Register code_reg = r3; 785 Register code_reg = r3;
1140 786
787 RECORD_LINE();
1141 ldr(code_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 788 ldr(code_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1142 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 789 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1143 ldr(expected_reg, 790 ldr(expected_reg,
1144 FieldMemOperand(code_reg, 791 FieldMemOperand(code_reg,
1145 SharedFunctionInfo::kFormalParameterCountOffset)); 792 SharedFunctionInfo::kFormalParameterCountOffset));
1146 mov(expected_reg, Operand(expected_reg, ASR, kSmiTagSize)); 793 asr(expected_reg, expected_reg, Operand(kSmiTagSize));
1147 ldr(code_reg, 794 ldr(code_reg,
1148 FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); 795 FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
1149 796
1150 ParameterCount expected(expected_reg); 797 ParameterCount expected(expected_reg);
1151 InvokeCode(code_reg, expected, actual, flag, call_wrapper, call_kind); 798 InvokeCode(code_reg, expected, actual, flag, call_wrapper, call_kind);
1152 } 799 }
1153 800
1154 801
1155 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, 802 void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
1156 const ParameterCount& actual, 803 const ParameterCount& actual,
1157 InvokeFlag flag, 804 InvokeFlag flag,
1158 const CallWrapper& call_wrapper, 805 const CallWrapper& call_wrapper,
1159 CallKind call_kind) { 806 CallKind call_kind) {
1160 // You can't call a function without a valid frame. 807 // You can't call a function without a valid frame.
1161 ASSERT(flag == JUMP_FUNCTION || has_frame()); 808 ASSERT(flag == JUMP_FUNCTION || has_frame());
1162 809
1163 // Get the function and setup the context. 810 // Get the function and setup the context.
1164 LoadHeapObject(r1, function); 811 LoadHeapObject(r1, function);
1165 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 812 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1166 813
1167 ParameterCount expected(function->shared()->formal_parameter_count()); 814 ParameterCount expected(function->shared()->formal_parameter_count());
815 // TODO(STM): only for crankshaft ?
1168 // We call indirectly through the code field in the function to 816 // We call indirectly through the code field in the function to
1169 // allow recompilation to take effect without changing any of the 817 // allow recompilation to take effect without changing any of the
1170 // call sites. 818 // call sites.
1171 ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); 819 ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
1172 InvokeCode(r3, expected, actual, flag, call_wrapper, call_kind); 820 InvokeCode(r3, expected, actual, flag, call_wrapper, call_kind);
1173 } 821 }
1174 822
1175 823
1176 void MacroAssembler::IsObjectJSObjectType(Register heap_object, 824 void MacroAssembler::IsObjectJSObjectType(Register heap_object,
1177 Register map, 825 Register map,
1178 Register scratch, 826 Register scratch,
1179 Label* fail) { 827 Label* fail) {
1180 ldr(map, FieldMemOperand(heap_object, HeapObject::kMapOffset)); 828 ldr(map, FieldMemOperand(heap_object, HeapObject::kMapOffset));
1181 IsInstanceJSObjectType(map, scratch, fail); 829 IsInstanceJSObjectType(map, scratch, fail);
1182 } 830 }
1183 831
1184 832
1185 void MacroAssembler::IsInstanceJSObjectType(Register map, 833 void MacroAssembler::IsInstanceJSObjectType(Register map,
1186 Register scratch, 834 Register scratch,
1187 Label* fail) { 835 Label* fail) {
1188 ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); 836 ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
1189 cmp(scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 837 cmpge(scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
1190 b(lt, fail); 838 bf(fail);
1191 cmp(scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); 839 cmpgt(scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
1192 b(gt, fail); 840 bt(fail);
1193 } 841 }
1194 842
1195 843
1196 void MacroAssembler::IsObjectJSStringType(Register object, 844 void MacroAssembler::IsObjectJSStringType(Register object,
1197 Register scratch, 845 Register scratch,
1198 Label* fail) { 846 Label* fail) {
1199 ASSERT(kNotStringTag != 0); 847 ASSERT(kNotStringTag != 0);
1200 848
849 ASSERT(!object.is(sh4_ip) && !scratch.is(sh4_ip));
850 ASSERT(!object.is(sh4_rtmp) && !scratch.is(sh4_rtmp));
851
1201 ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); 852 ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
1202 ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); 853 ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
1203 tst(scratch, Operand(kIsNotStringMask)); 854 tst(scratch, Operand(kIsNotStringMask));
1204 b(ne, fail); 855 bf(fail);
1205 } 856 }
1206 857
1207 858
1208 #ifdef ENABLE_DEBUGGER_SUPPORT 859 #ifdef ENABLE_DEBUGGER_SUPPORT
1209 void MacroAssembler::DebugBreak() { 860 void MacroAssembler::DebugBreak() {
1210 mov(r0, Operand(0, RelocInfo::NONE)); 861 RECORD_LINE();
1211 mov(r1, Operand(ExternalReference(Runtime::kDebugBreak, isolate()))); 862 UNIMPLEMENTED_BREAK();
1212 CEntryStub ces(1);
1213 ASSERT(AllowThisStubCall(&ces));
1214 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
1215 } 863 }
1216 #endif 864 #endif
1217 865
1218 866
1219 void MacroAssembler::PushTryHandler(StackHandler::Kind kind, 867 void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
1220 int handler_index) { 868 int handler_index) {
1221 // Adjust this code if not the case. 869 // Adjust this code if not the case.
1222 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); 870 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
1223 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); 871 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
1224 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); 872 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
1225 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); 873 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
1226 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); 874 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
1227 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); 875 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
1228 876
1229 // For the JSEntry handler, we must preserve r0-r4, r5-r7 are available. 877 // For the JSEntry handler, we must preserve r0-r4, r5-r7 are available.
1230 // We will build up the handler from the bottom by pushing on the stack. 878 // We will build up the handler from the bottom by pushing on the stack.
1231 // Set up the code object (r5) and the state (r6) for pushing. 879 // Set up the code object (r5) and the state (r6) for pushing.
1232 unsigned state = 880 unsigned state =
1233 StackHandler::IndexField::encode(handler_index) | 881 StackHandler::IndexField::encode(handler_index) |
1234 StackHandler::KindField::encode(kind); 882 StackHandler::KindField::encode(kind);
1235 mov(r5, Operand(CodeObject())); 883 mov(r5, Operand(CodeObject()));
1236 mov(r6, Operand(state)); 884 mov(r6, Operand(state));
1237 885
1238 // Push the frame pointer, context, state, and code object. 886 // Push the frame pointer, context, state, and code object.
1239 if (kind == StackHandler::JS_ENTRY) { 887 if (kind == StackHandler::JS_ENTRY) {
1240 mov(r7, Operand(Smi::FromInt(0))); // Indicates no context. 888 mov(r7, Operand(Smi::FromInt(0))); // Indicates no context.
1241 mov(ip, Operand(0, RelocInfo::NONE)); // NULL frame pointer. 889 mov(sh4_ip, Operand(0, RelocInfo::NONE)); // NULL frame pointer.
1242 stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | ip.bit()); 890 Push(sh4_ip, r7, r6, r5);
1243 } else { 891 } else {
1244 stm(db_w, sp, r5.bit() | r6.bit() | cp.bit() | fp.bit()); 892 Push(fp, cp, r6, r5);
1245 } 893 }
1246 894
1247 // Link the current handler as the next handler. 895 // Link the current handler as the next handler.
1248 mov(r6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); 896 mov(r6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
1249 ldr(r5, MemOperand(r6)); 897 ldr(r5, MemOperand(r6));
1250 push(r5); 898 push(r5);
1251 // Set this new handler as the current one. 899 // Set this new handler as the current one.
1252 str(sp, MemOperand(r6)); 900 str(sp, MemOperand(r6));
1253 } 901 }
1254 902
1255 903
1256 void MacroAssembler::PopTryHandler() { 904 void MacroAssembler::PopTryHandler() {
1257 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 905 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
906 RECORD_LINE();
1258 pop(r1); 907 pop(r1);
1259 mov(ip, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); 908 mov(sh4_ip, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
1260 add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); 909 add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
1261 str(r1, MemOperand(ip)); 910 str(r1, MemOperand(sh4_ip));
1262 } 911 }
1263 912
1264 913
1265 void MacroAssembler::JumpToHandlerEntry() { 914 void MacroAssembler::JumpToHandlerEntry() {
1266 // Compute the handler entry address and jump to it. The handler table is 915 // Compute the handler entry address and jump to it. The handler table is
1267 // a fixed array of (smi-tagged) code offsets. 916 // a fixed array of (smi-tagged) code offsets.
1268 // r0 = exception, r1 = code object, r2 = state. 917 // r0 = exception, r1 = code object, r2 = state.
1269 ldr(r3, FieldMemOperand(r1, Code::kHandlerTableOffset)); // Handler table. 918 ldr(r3, FieldMemOperand(r1, Code::kHandlerTableOffset)); // Handler table.
1270 add(r3, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 919 add(r3, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
1271 mov(r2, Operand(r2, LSR, StackHandler::kKindWidth)); // Handler index. 920 lsr(r2, r2, Operand(StackHandler::kKindWidth)); // Handler index.
1272 ldr(r2, MemOperand(r3, r2, LSL, kPointerSizeLog2)); // Smi-tagged offset. 921 lsl(r2, r2, Operand(kPointerSizeLog2));
922 ldr(r2, MemOperand(r3, r2)); // Smi-tagged offset.
1273 add(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start. 923 add(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start.
1274 add(pc, r1, Operand(r2, ASR, kSmiTagSize)); // Jump. 924 asr(sh4_ip, r2, Operand(kSmiTagSize));
925 add(sh4_ip, r1, sh4_ip);
926 jmp(sh4_ip); // Jump.
1275 } 927 }
1276 928
1277 929
1278 void MacroAssembler::Throw(Register value) { 930 void MacroAssembler::Throw(Register value) {
931 ASSERT(!value.is(sh4_ip));
932 ASSERT(!value.is(sh4_rtmp));
933
1279 // Adjust this code if not the case. 934 // Adjust this code if not the case.
1280 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); 935 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
1281 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 936 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
1282 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); 937 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
1283 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); 938 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
1284 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); 939 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
1285 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); 940 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
1286 941
1287 // The exception is expected in r0. 942 // The exception is expected in r0.
1288 if (!value.is(r0)) { 943 if (!value.is(r0)) {
1289 mov(r0, value); 944 mov(r0, value);
1290 } 945 }
1291 // Drop the stack pointer to the top of the top handler. 946 // Drop the stack pointer to the top of the top handler.
1292 mov(r3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); 947 mov(r3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
1293 ldr(sp, MemOperand(r3)); 948 ldr(sp, MemOperand(r3));
1294 // Restore the next handler. 949 // Restore the next handler.
1295 pop(r2); 950 pop(r2);
1296 str(r2, MemOperand(r3)); 951 str(r2, MemOperand(r3));
1297 952
1298 // Get the code object (r1) and state (r2). Restore the context and frame 953 // Get the code object (r1) and state (r2). Restore the context and frame
1299 // pointer. 954 // pointer.
1300 ldm(ia_w, sp, r1.bit() | r2.bit() | cp.bit() | fp.bit()); 955 Pop(fp, cp, r2, r1);
1301 956
1302 // If the handler is a JS frame, restore the context to the frame. 957 // If the handler is a JS frame, restore the context to the frame.
1303 // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp 958 // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
1304 // or cp. 959 // or cp.
960 Label skip;
1305 tst(cp, cp); 961 tst(cp, cp);
1306 str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); 962 bt(&skip);
963 str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
964 bind(&skip);
1307 965
1308 JumpToHandlerEntry(); 966 JumpToHandlerEntry();
1309 } 967 }
1310 968
1311 969
1312 void MacroAssembler::ThrowUncatchable(Register value) { 970 void MacroAssembler::ThrowUncatchable(Register value) {
1313 // Adjust this code if not the case. 971 // Adjust this code if not the case.
1314 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); 972 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
1315 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); 973 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
1316 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); 974 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
1317 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); 975 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
1318 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); 976 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
1319 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); 977 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
1320 978
1321 // The exception is expected in r0. 979 // The exception is expected in r0.
1322 if (!value.is(r0)) { 980 if (!value.is(r0)) {
981 RECORD_LINE();
1323 mov(r0, value); 982 mov(r0, value);
1324 } 983 }
984
985 RECORD_LINE();
1325 // Drop the stack pointer to the top of the top stack handler. 986 // Drop the stack pointer to the top of the top stack handler.
1326 mov(r3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); 987 mov(r3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
1327 ldr(sp, MemOperand(r3)); 988 ldr(sp, MemOperand(r3));
1328 989
1329 // Unwind the handlers until the ENTRY handler is found. 990 // Unwind the handlers until the ENTRY handler is found.
1330 Label fetch_next, check_kind; 991 Label fetch_next, check_kind;
1331 jmp(&check_kind); 992 jmp(&check_kind);
1332 bind(&fetch_next); 993 bind(&fetch_next);
1333 ldr(sp, MemOperand(sp, StackHandlerConstants::kNextOffset)); 994 ldr(sp, MemOperand(sp, StackHandlerConstants::kNextOffset));
1334 995
1335 bind(&check_kind); 996 bind(&check_kind);
1336 STATIC_ASSERT(StackHandler::JS_ENTRY == 0); 997 STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
1337 ldr(r2, MemOperand(sp, StackHandlerConstants::kStateOffset)); 998 ldr(r2, MemOperand(sp, StackHandlerConstants::kStateOffset));
1338 tst(r2, Operand(StackHandler::KindField::kMask)); 999 tst(r2, Operand(StackHandler::KindField::kMask));
1339 b(ne, &fetch_next); 1000 b(ne, &fetch_next);
1340 1001
1341 // Set the top handler address to next handler past the top ENTRY handler. 1002 // Set the top handler address to next handler past the top ENTRY handler.
1342 pop(r2); 1003 pop(r2);
1343 str(r2, MemOperand(r3)); 1004 str(r2, MemOperand(r3));
1344 // Get the code object (r1) and state (r2). Clear the context and frame 1005 // Get the code object (r1) and state (r2). Clear the context and frame
1345 // pointer (0 was saved in the handler). 1006 // pointer (0 was saved in the handler).
1346 ldm(ia_w, sp, r1.bit() | r2.bit() | cp.bit() | fp.bit()); 1007 Pop(fp, cp, r2, r1);
1347 1008
1348 JumpToHandlerEntry(); 1009 JumpToHandlerEntry();
1349 } 1010 }
1350 1011
1351 1012
1352 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, 1013 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
1353 Register scratch, 1014 Register scratch,
1354 Label* miss) { 1015 Label* miss) {
1355 Label same_contexts; 1016 Label same_contexts;
1356 1017
(...skipping 24 matching lines...) Expand all
1381 // Read the first word and compare to the native_context_map. 1042 // Read the first word and compare to the native_context_map.
1382 ldr(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset)); 1043 ldr(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
1383 LoadRoot(ip, Heap::kNativeContextMapRootIndex); 1044 LoadRoot(ip, Heap::kNativeContextMapRootIndex);
1384 cmp(holder_reg, ip); 1045 cmp(holder_reg, ip);
1385 Check(eq, "JSGlobalObject::native_context should be a native context."); 1046 Check(eq, "JSGlobalObject::native_context should be a native context.");
1386 pop(holder_reg); // Restore holder. 1047 pop(holder_reg); // Restore holder.
1387 } 1048 }
1388 1049
1389 // Check if both contexts are the same. 1050 // Check if both contexts are the same.
1390 ldr(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); 1051 ldr(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
1391 cmp(scratch, Operand(ip)); 1052 cmp(scratch, ip);
1392 b(eq, &same_contexts); 1053 b(eq, &same_contexts);
1393 1054
1394 // Check the context is a native context. 1055 // Check the context is a native context.
1395 if (emit_debug_code()) { 1056 if (emit_debug_code()) {
1396 // TODO(119): avoid push(holder_reg)/pop(holder_reg) 1057 // TODO(119): avoid push(holder_reg)/pop(holder_reg)
1397 // Cannot use ip as a temporary in this verification code. Due to the fact 1058 // Cannot use ip as a temporary in this verification code. Due to the fact
1398 // that ip is clobbered as part of cmp with an object Operand. 1059 // that ip is clobbered as part of cmp with an object Operand.
1399 push(holder_reg); // Temporarily save holder on the stack. 1060 push(holder_reg); // Temporarily save holder on the stack.
1400 mov(holder_reg, ip); // Move ip to its holding place. 1061 mov(holder_reg, ip); // Move ip to its holding place.
1401 LoadRoot(ip, Heap::kNullValueRootIndex); 1062 LoadRoot(ip, Heap::kNullValueRootIndex);
(...skipping 11 matching lines...) Expand all
1413 } 1074 }
1414 1075
1415 // Check that the security token in the calling global object is 1076 // Check that the security token in the calling global object is
1416 // compatible with the security token in the receiving global 1077 // compatible with the security token in the receiving global
1417 // object. 1078 // object.
1418 int token_offset = Context::kHeaderSize + 1079 int token_offset = Context::kHeaderSize +
1419 Context::SECURITY_TOKEN_INDEX * kPointerSize; 1080 Context::SECURITY_TOKEN_INDEX * kPointerSize;
1420 1081
1421 ldr(scratch, FieldMemOperand(scratch, token_offset)); 1082 ldr(scratch, FieldMemOperand(scratch, token_offset));
1422 ldr(ip, FieldMemOperand(ip, token_offset)); 1083 ldr(ip, FieldMemOperand(ip, token_offset));
1423 cmp(scratch, Operand(ip)); 1084 cmp(scratch, ip);
1424 b(ne, miss); 1085 b(ne, miss);
1425 1086
1426 bind(&same_contexts); 1087 bind(&same_contexts);
1427 } 1088 }
1428 1089
1429 1090
1430 void MacroAssembler::GetNumberHash(Register t0, Register scratch) { 1091 void MacroAssembler::GetNumberHash(Register t0, Register scratch) {
1431 // First of all we assign the hash seed to scratch. 1092 // First of all we assign the hash seed to scratch.
1432 LoadRoot(scratch, Heap::kHashSeedRootIndex); 1093 LoadRoot(scratch, Heap::kHashSeedRootIndex);
1433 SmiUntag(scratch); 1094 SmiUntag(scratch);
1434 1095
1435 // Xor original key with a seed. 1096 // Xor original key with a seed.
1436 eor(t0, t0, Operand(scratch)); 1097 eor(t0, t0, scratch);
1437 1098
1438 // Compute the hash code from the untagged key. This must be kept in sync 1099 // Compute the hash code from the untagged key. This must be kept in sync
1439 // with ComputeIntegerHash in utils.h. 1100 // with ComputeIntegerHash in utils.h.
1440 // 1101 //
1441 // hash = ~hash + (hash << 15); 1102 // hash = ~hash + (hash << 15);
1442 mvn(scratch, Operand(t0)); 1103 mvn(scratch, t0);
1443 add(t0, scratch, Operand(t0, LSL, 15)); 1104 lsl(t0, t0, Operand(15));
1105 add(t0, scratch, t0);
1444 // hash = hash ^ (hash >> 12); 1106 // hash = hash ^ (hash >> 12);
1445 eor(t0, t0, Operand(t0, LSR, 12)); 1107 lsr(scratch, t0, Operand(12));
1108 eor(t0, t0, scratch);
1446 // hash = hash + (hash << 2); 1109 // hash = hash + (hash << 2);
1447 add(t0, t0, Operand(t0, LSL, 2)); 1110 lsl(scratch, t0, Operand(2));
1111 add(t0, t0, scratch);
1448 // hash = hash ^ (hash >> 4); 1112 // hash = hash ^ (hash >> 4);
1449 eor(t0, t0, Operand(t0, LSR, 4)); 1113 lsr(scratch, t0, Operand(4));
1114 eor(t0, t0, scratch);
1450 // hash = hash * 2057; 1115 // hash = hash * 2057;
1451 mov(scratch, Operand(t0, LSL, 11)); 1116 lsl(scratch, t0, Operand(11));
1452 add(t0, t0, Operand(t0, LSL, 3)); 1117 lsl(sh4_ip, t0, Operand(3));
1118 add(t0, t0, sh4_ip);
1453 add(t0, t0, scratch); 1119 add(t0, t0, scratch);
1454 // hash = hash ^ (hash >> 16); 1120 // hash = hash ^ (hash >> 16);
1455 eor(t0, t0, Operand(t0, LSR, 16)); 1121 lsr(scratch, t0, Operand(16));
1122 eor(t0, t0, scratch);
1456 } 1123 }
1457 1124
1458 1125
1459 void MacroAssembler::LoadFromNumberDictionary(Label* miss, 1126 void MacroAssembler::LoadFromNumberDictionary(Label* miss,
1460 Register elements, 1127 Register elements,
1461 Register key, 1128 Register key,
1462 Register result, 1129 Register result,
1463 Register t0, 1130 Register t0,
1464 Register t1, 1131 Register t1,
1465 Register t2) { 1132 Register t2) {
(...skipping 16 matching lines...) Expand all
1482 // 1149 //
1483 // t1 - used to hold the capacity mask of the dictionary 1150 // t1 - used to hold the capacity mask of the dictionary
1484 // 1151 //
1485 // t2 - used for the index into the dictionary. 1152 // t2 - used for the index into the dictionary.
1486 Label done; 1153 Label done;
1487 1154
1488 GetNumberHash(t0, t1); 1155 GetNumberHash(t0, t1);
1489 1156
1490 // Compute the capacity mask. 1157 // Compute the capacity mask.
1491 ldr(t1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset)); 1158 ldr(t1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset));
1492 mov(t1, Operand(t1, ASR, kSmiTagSize)); // convert smi to int 1159 asr(t1, t1, Operand(kSmiTagSize)); // convert smi to int
1493 sub(t1, t1, Operand(1)); 1160 sub(t1, t1, Operand(1));
1494 1161
1495 // Generate an unrolled loop that performs a few probes before giving up. 1162 // Generate an unrolled loop that performs a few probes before giving up.
1496 static const int kProbes = 4; 1163 static const int kProbes = 4;
1497 for (int i = 0; i < kProbes; i++) { 1164 for (int i = 0; i < kProbes; i++) {
1498 // Use t2 for index calculations and keep the hash intact in t0. 1165 // Use t2 for index calculations and keep the hash intact in t0.
1499 mov(t2, t0); 1166 mov(t2, t0);
1500 // Compute the masked index: (hash + i + i * i) & mask. 1167 // Compute the masked index: (hash + i + i * i) & mask.
1501 if (i > 0) { 1168 if (i > 0) {
1502 add(t2, t2, Operand(SeededNumberDictionary::GetProbeOffset(i))); 1169 add(t2, t2, Operand(SeededNumberDictionary::GetProbeOffset(i)));
1503 } 1170 }
1504 and_(t2, t2, Operand(t1)); 1171 land(t2, t2, t1);
1505 1172
1506 // Scale the index by multiplying by the element size. 1173 // Scale the index by multiplying by the element size.
1507 ASSERT(SeededNumberDictionary::kEntrySize == 3); 1174 ASSERT(SeededNumberDictionary::kEntrySize == 3);
1508 add(t2, t2, Operand(t2, LSL, 1)); // t2 = t2 * 3 1175 lsl(ip, t2, Operand(1));
1176 add(t2, t2, ip); // t2 = t2 * 3
1509 1177
1510 // Check if the key is identical to the name. 1178 // Check if the key is identical to the name.
1511 add(t2, elements, Operand(t2, LSL, kPointerSizeLog2)); 1179 lsl(ip, t2, Operand(kPointerSizeLog2));
1180 add(t2, elements, ip);
1512 ldr(ip, FieldMemOperand(t2, SeededNumberDictionary::kElementsStartOffset)); 1181 ldr(ip, FieldMemOperand(t2, SeededNumberDictionary::kElementsStartOffset));
1513 cmp(key, Operand(ip)); 1182 cmp(key, ip);
1514 if (i != kProbes - 1) { 1183 if (i != kProbes - 1) {
1515 b(eq, &done); 1184 b(eq, &done);
1516 } else { 1185 } else {
1517 b(ne, miss); 1186 b(ne, miss);
1518 } 1187 }
1519 } 1188 }
1520 1189
1521 bind(&done); 1190 bind(&done);
1522 // Check that the value is a normal property. 1191 // Check that the value is a normal property.
1523 // t2: elements + (index * kPointerSize) 1192 // t2: elements + (index * kPointerSize)
1524 const int kDetailsOffset = 1193 const int kDetailsOffset =
1525 SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; 1194 SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
1526 ldr(t1, FieldMemOperand(t2, kDetailsOffset)); 1195 ldr(t1, FieldMemOperand(t2, kDetailsOffset));
1527 tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask))); 1196 tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask)));
1528 b(ne, miss); 1197 b(ne, miss);
1529 1198
1530 // Get the value at the masked, scaled index and return. 1199 // Get the value at the masked, scaled index and return.
1531 const int kValueOffset = 1200 const int kValueOffset =
1532 SeededNumberDictionary::kElementsStartOffset + kPointerSize; 1201 SeededNumberDictionary::kElementsStartOffset + kPointerSize;
1533 ldr(result, FieldMemOperand(t2, kValueOffset)); 1202 ldr(result, FieldMemOperand(t2, kValueOffset));
1534 } 1203 }
1535 1204
1536 1205
1537 void MacroAssembler::AllocateInNewSpace(int object_size, 1206 void MacroAssembler::AllocateInNewSpace(int object_size,
1538 Register result, 1207 Register result,
1539 Register scratch1, 1208 Register scratch1,
1540 Register scratch2, 1209 Register scratch2,
1541 Label* gc_required, 1210 Label* gc_required,
1542 AllocationFlags flags) { 1211 AllocationFlags flags) {
1212 RECORD_LINE();
1543 if (!FLAG_inline_new) { 1213 if (!FLAG_inline_new) {
1544 if (emit_debug_code()) { 1214 if (emit_debug_code()) {
1545 // Trash the registers to simulate an allocation failure. 1215 // Trash the registers to simulate an allocation failure.
1216 RECORD_LINE();
1546 mov(result, Operand(0x7091)); 1217 mov(result, Operand(0x7091));
1547 mov(scratch1, Operand(0x7191)); 1218 mov(scratch1, Operand(0x7191));
1548 mov(scratch2, Operand(0x7291)); 1219 mov(scratch2, Operand(0x7291));
1549 } 1220 }
1221 RECORD_LINE();
1550 jmp(gc_required); 1222 jmp(gc_required);
1551 return; 1223 return;
1552 } 1224 }
1553 1225
1554 ASSERT(!result.is(scratch1)); 1226 // Assert that the register arguments are different and that none of
1555 ASSERT(!result.is(scratch2)); 1227 // them are ip. ip is used explicitly in the code generated below.
1556 ASSERT(!scratch1.is(scratch2)); 1228 ASSERT(!result.is(scratch1) && !result.is(scratch2) &&
1557 ASSERT(!scratch1.is(ip)); 1229 !scratch1.is(scratch2));
1558 ASSERT(!scratch2.is(ip)); 1230 ASSERT(!result.is(sh4_ip) && !scratch1.is(sh4_ip) &&
1231 !scratch2.is(sh4_ip));
1232 ASSERT(!result.is(sh4_rtmp) && !scratch1.is(sh4_rtmp) &&
1233 !scratch2.is(sh4_rtmp));
1559 1234
1560 // Make object size into bytes. 1235 // Make object size into bytes.
1561 if ((flags & SIZE_IN_WORDS) != 0) { 1236 if ((flags & SIZE_IN_WORDS) != 0) {
1562 object_size *= kPointerSize; 1237 object_size *= kPointerSize;
1563 } 1238 }
1564 ASSERT_EQ(0, object_size & kObjectAlignmentMask); 1239 ASSERT_EQ(0, object_size & kObjectAlignmentMask);
1565 1240
1566 // Check relative positions of allocation top and limit addresses. 1241 // Check relative positions of allocation top and limit addresses.
1567 // The values must be adjacent in memory to allow the use of LDM. 1242 // The values must be adjacent in memory to allow the use of LDM.
1568 // Also, assert that the registers are numbered such that the values 1243 // Also, assert that the registers are numbered such that the values
1569 // are loaded in the correct order. 1244 // are loaded in the correct order.
1570 ExternalReference new_space_allocation_top = 1245 ExternalReference new_space_allocation_top =
1571 ExternalReference::new_space_allocation_top_address(isolate()); 1246 ExternalReference::new_space_allocation_top_address(isolate());
1572 ExternalReference new_space_allocation_limit = 1247 ExternalReference new_space_allocation_limit =
1573 ExternalReference::new_space_allocation_limit_address(isolate()); 1248 ExternalReference::new_space_allocation_limit_address(isolate());
1574 intptr_t top = 1249 intptr_t top =
1575 reinterpret_cast<intptr_t>(new_space_allocation_top.address()); 1250 reinterpret_cast<intptr_t>(new_space_allocation_top.address());
1576 intptr_t limit = 1251 intptr_t limit =
1577 reinterpret_cast<intptr_t>(new_space_allocation_limit.address()); 1252 reinterpret_cast<intptr_t>(new_space_allocation_limit.address());
1578 ASSERT((limit - top) == kPointerSize); 1253 ASSERT((limit - top) == kPointerSize);
1579 ASSERT(result.code() < ip.code()); 1254 ASSERT(result.code() < ip.code());
1580 1255
1581 // Set up allocation top address and object size registers. 1256 // Set up allocation top address and object size registers.
1582 Register topaddr = scratch1; 1257 Register topaddr = scratch1;
1583 Register obj_size_reg = scratch2; 1258 Register obj_size_reg = scratch2;
1259 RECORD_LINE();
1584 mov(topaddr, Operand(new_space_allocation_top)); 1260 mov(topaddr, Operand(new_space_allocation_top));
1585 Operand obj_size_operand = Operand(object_size); 1261 mov(obj_size_reg, Operand(object_size));
1586 if (!obj_size_operand.is_single_instruction(this)) {
1587 // We are about to steal IP, so we need to load this value first
1588 mov(obj_size_reg, obj_size_operand);
1589 }
1590 1262
1591 // This code stores a temporary value in ip. This is OK, as the code below 1263 // This code stores a temporary value in ip. This is OK, as the code below
1592 // does not need ip for implicit literal generation. 1264 // does not need ip for implicit literal generation.
1593 if ((flags & RESULT_CONTAINS_TOP) == 0) { 1265 if ((flags & RESULT_CONTAINS_TOP) == 0) {
1266 RECORD_LINE();
1594 // Load allocation top into result and allocation limit into ip. 1267 // Load allocation top into result and allocation limit into ip.
1595 ldm(ia, topaddr, result.bit() | ip.bit()); 1268 ldr(result, MemOperand(topaddr));
1269 ldr(ip, MemOperand(topaddr, 4));
1596 } else { 1270 } else {
1597 if (emit_debug_code()) { 1271 if (emit_debug_code()) {
1272 RECORD_LINE();
1598 // Assert that result actually contains top on entry. ip is used 1273 // Assert that result actually contains top on entry. ip is used
1599 // immediately below so this use of ip does not cause difference with 1274 // immediately below so this use of ip does not cause difference with
1600 // respect to register content between debug and release mode. 1275 // respect to register content between debug and release mode.
1601 ldr(ip, MemOperand(topaddr)); 1276 ldr(ip, MemOperand(topaddr));
1602 cmp(result, ip); 1277 cmp(result, ip);
1603 Check(eq, "Unexpected allocation top"); 1278 Check(eq, "Unexpected allocation top");
1604 } 1279 }
1280 RECORD_LINE();
1605 // Load allocation limit into ip. Result already contains allocation top. 1281 // Load allocation limit into ip. Result already contains allocation top.
1606 ldr(ip, MemOperand(topaddr, limit - top)); 1282 ldr(ip, MemOperand(topaddr, limit - top));
1607 } 1283 }
1608 1284
1285 RECORD_LINE();
1609 // Calculate new top and bail out if new space is exhausted. Use result 1286 // Calculate new top and bail out if new space is exhausted. Use result
1610 // to calculate the new top. 1287 // to calculate the new top.
1611 if (obj_size_operand.is_single_instruction(this)) { 1288 addc(scratch2, result, obj_size_reg);
1612 // We can add the size as an immediate 1289 b(t, gc_required);
1613 add(scratch2, result, obj_size_operand, SetCC); 1290
1614 } else { 1291 RECORD_LINE();
1615 // Doesn't fit in an immediate, we have to use the register 1292 cmphi(scratch2, sh4_ip);
1616 add(scratch2, result, obj_size_reg, SetCC); 1293 bt(gc_required);
1617 } 1294
1618 b(cs, gc_required); 1295 RECORD_LINE();
1619 cmp(scratch2, Operand(ip));
1620 b(hi, gc_required);
1621 str(scratch2, MemOperand(topaddr)); 1296 str(scratch2, MemOperand(topaddr));
1622 1297
1623 // Tag object if requested. 1298 // Tag object if requested.
1624 if ((flags & TAG_OBJECT) != 0) { 1299 if ((flags & TAG_OBJECT) != 0) {
1300 RECORD_LINE();
1625 add(result, result, Operand(kHeapObjectTag)); 1301 add(result, result, Operand(kHeapObjectTag));
1626 } 1302 }
1627 } 1303 }
1628 1304
1629 1305
1630 void MacroAssembler::AllocateInNewSpace(Register object_size, 1306 void MacroAssembler::AllocateInNewSpace(Register object_size,
1631 Register result, 1307 Register result,
1632 Register scratch1, 1308 Register scratch1,
1633 Register scratch2, 1309 Register scratch2,
1634 Label* gc_required, 1310 Label* gc_required,
1635 AllocationFlags flags) { 1311 AllocationFlags flags) {
1312 RECORD_LINE();
1636 if (!FLAG_inline_new) { 1313 if (!FLAG_inline_new) {
1637 if (emit_debug_code()) { 1314 if (emit_debug_code()) {
1638 // Trash the registers to simulate an allocation failure. 1315 // Trash the registers to simulate an allocation failure.
1316 RECORD_LINE();
1639 mov(result, Operand(0x7091)); 1317 mov(result, Operand(0x7091));
1640 mov(scratch1, Operand(0x7191)); 1318 mov(scratch1, Operand(0x7191));
1641 mov(scratch2, Operand(0x7291)); 1319 mov(scratch2, Operand(0x7291));
1642 } 1320 }
1321 RECORD_LINE();
1643 jmp(gc_required); 1322 jmp(gc_required);
1644 return; 1323 return;
1645 } 1324 }
1646 1325
1647 // Assert that the register arguments are different and that none of 1326 // Assert that the register arguments are different and that none of
1648 // them are ip. ip is used explicitly in the code generated below. 1327 // them are ip. ip is used explicitly in the code generated below.
1328 // Also assert that rtmp is not used as it is used in assembler-sh4.cc.
1649 ASSERT(!result.is(scratch1)); 1329 ASSERT(!result.is(scratch1));
1650 ASSERT(!result.is(scratch2)); 1330 ASSERT(!result.is(scratch2));
1651 ASSERT(!scratch1.is(scratch2)); 1331 ASSERT(!scratch1.is(scratch2));
1652 ASSERT(!object_size.is(ip)); 1332 ASSERT(!result.is(sh4_ip));
1653 ASSERT(!result.is(ip)); 1333 ASSERT(!scratch1.is(sh4_ip));
1654 ASSERT(!scratch1.is(ip)); 1334 ASSERT(!scratch2.is(sh4_ip));
1655 ASSERT(!scratch2.is(ip)); 1335 ASSERT(!result.is(sh4_rtmp));
1336 ASSERT(!scratch1.is(sh4_rtmp));
1337 ASSERT(!scratch2.is(sh4_rtmp));
1656 1338
1657 // Check relative positions of allocation top and limit addresses. 1339 // Check relative positions of allocation top and limit addresses.
1658 // The values must be adjacent in memory to allow the use of LDM. 1340 // The values must be adjacent in memory to allow the use of LDM.
1659 // Also, assert that the registers are numbered such that the values 1341 // Also, assert that the registers are numbered such that the values
1660 // are loaded in the correct order. 1342 // are loaded in the correct order.
1661 ExternalReference new_space_allocation_top = 1343 ExternalReference new_space_allocation_top =
1662 ExternalReference::new_space_allocation_top_address(isolate()); 1344 ExternalReference::new_space_allocation_top_address(isolate());
1663 ExternalReference new_space_allocation_limit = 1345 ExternalReference new_space_allocation_limit =
1664 ExternalReference::new_space_allocation_limit_address(isolate()); 1346 ExternalReference::new_space_allocation_limit_address(isolate());
1665 intptr_t top = 1347 intptr_t top =
1666 reinterpret_cast<intptr_t>(new_space_allocation_top.address()); 1348 reinterpret_cast<intptr_t>(new_space_allocation_top.address());
1667 intptr_t limit = 1349 intptr_t limit =
1668 reinterpret_cast<intptr_t>(new_space_allocation_limit.address()); 1350 reinterpret_cast<intptr_t>(new_space_allocation_limit.address());
1669 ASSERT((limit - top) == kPointerSize); 1351 ASSERT((limit - top) == kPointerSize);
1670 ASSERT(result.code() < ip.code()); 1352 ASSERT(result.code() < ip.code());
1671 1353
1672 // Set up allocation top address. 1354 // Set up allocation top address.
1673 Register topaddr = scratch1; 1355 Register topaddr = scratch1;
1356
1357 RECORD_LINE();
1674 mov(topaddr, Operand(new_space_allocation_top)); 1358 mov(topaddr, Operand(new_space_allocation_top));
1675 1359
1676 // This code stores a temporary value in ip. This is OK, as the code below 1360 // This code stores a temporary value in ip. This is OK, as the code below
1677 // does not need ip for implicit literal generation. 1361 // does not need ip for implicit literal generation.
1678 if ((flags & RESULT_CONTAINS_TOP) == 0) { 1362 if ((flags & RESULT_CONTAINS_TOP) == 0) {
1363 RECORD_LINE();
1679 // Load allocation top into result and allocation limit into ip. 1364 // Load allocation top into result and allocation limit into ip.
1680 ldm(ia, topaddr, result.bit() | ip.bit()); 1365 ldr(result, MemOperand(topaddr));
1366 ldr(ip, MemOperand(topaddr, 4));
1681 } else { 1367 } else {
1682 if (emit_debug_code()) { 1368 if (emit_debug_code()) {
1369 RECORD_LINE();
1683 // Assert that result actually contains top on entry. ip is used 1370 // Assert that result actually contains top on entry. ip is used
1684 // immediately below so this use of ip does not cause difference with 1371 // immediately below so this use of ip does not cause difference with
1685 // respect to register content between debug and release mode. 1372 // respect to register content between debug and release mode.
1686 ldr(ip, MemOperand(topaddr)); 1373 ldr(ip, MemOperand(topaddr));
1687 cmp(result, ip); 1374 cmp(result, ip);
1688 Check(eq, "Unexpected allocation top"); 1375 Check(eq, "Unexpected allocation top");
1689 } 1376 }
1377 RECORD_LINE();
1690 // Load allocation limit into ip. Result already contains allocation top. 1378 // Load allocation limit into ip. Result already contains allocation top.
1691 ldr(ip, MemOperand(topaddr, limit - top)); 1379 ldr(ip, MemOperand(topaddr, limit - top));
1692 } 1380 }
1693 1381
1382 RECORD_LINE();
1694 // Calculate new top and bail out if new space is exhausted. Use result 1383 // Calculate new top and bail out if new space is exhausted. Use result
1695 // to calculate the new top. Object size may be in words so a shift is 1384 // to calculate the new top. Object size may be in words so a shift is
1696 // required to get the number of bytes. 1385 // required to get the number of bytes.
1697 if ((flags & SIZE_IN_WORDS) != 0) { 1386 if ((flags & SIZE_IN_WORDS) != 0) {
1698 add(scratch2, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC); 1387 RECORD_LINE();
1388 lsl(scratch2, object_size, Operand(kPointerSizeLog2));
1389 addc(scratch2, result, scratch2);
1699 } else { 1390 } else {
1700 add(scratch2, result, Operand(object_size), SetCC); 1391 RECORD_LINE();
1392 addc(scratch2, result, object_size);
1701 } 1393 }
1702 b(cs, gc_required); 1394 RECORD_LINE();
1703 cmp(scratch2, Operand(ip)); 1395 b(t, gc_required);
1704 b(hi, gc_required); 1396 RECORD_LINE();
1397 cmphi(scratch2, sh4_ip);
1398 bt(gc_required);
1399 RECORD_LINE();
1705 1400
1706 // Update allocation top. result temporarily holds the new top. 1401 // Update allocation top. result temporarily holds the new top.
1707 if (emit_debug_code()) { 1402 if (emit_debug_code()) {
1403 RECORD_LINE();
1708 tst(scratch2, Operand(kObjectAlignmentMask)); 1404 tst(scratch2, Operand(kObjectAlignmentMask));
1709 Check(eq, "Unaligned allocation in new space"); 1405 Check(eq, "Unaligned allocation in new space");
1710 } 1406 }
1407 RECORD_LINE();
1711 str(scratch2, MemOperand(topaddr)); 1408 str(scratch2, MemOperand(topaddr));
1712 1409
1713 // Tag object if requested. 1410 // Tag object if requested.
1714 if ((flags & TAG_OBJECT) != 0) { 1411 if ((flags & TAG_OBJECT) != 0) {
1412 RECORD_LINE();
1715 add(result, result, Operand(kHeapObjectTag)); 1413 add(result, result, Operand(kHeapObjectTag));
1716 } 1414 }
1717 } 1415 }
1718 1416
1719 1417
1720 void MacroAssembler::UndoAllocationInNewSpace(Register object, 1418 void MacroAssembler::UndoAllocationInNewSpace(Register object,
1721 Register scratch) { 1419 Register scratch) {
1722 ExternalReference new_space_allocation_top = 1420 ExternalReference new_space_allocation_top =
1723 ExternalReference::new_space_allocation_top_address(isolate()); 1421 ExternalReference::new_space_allocation_top_address(isolate());
1724 1422
1725 // Make sure the object has no tag before resetting top. 1423 // Make sure the object has no tag before resetting top.
1726 and_(object, object, Operand(~kHeapObjectTagMask)); 1424 land(object, object, Operand(~kHeapObjectTagMask));
1727 #ifdef DEBUG 1425 #ifdef DEBUG
1728 // Check that the object un-allocated is below the current top. 1426 // Check that the object un-allocated is below the current top.
1729 mov(scratch, Operand(new_space_allocation_top)); 1427 mov(scratch, Operand(new_space_allocation_top));
1730 ldr(scratch, MemOperand(scratch)); 1428 ldr(scratch, MemOperand(scratch));
1731 cmp(object, scratch); 1429 cmpge(object, scratch);
1732 Check(lt, "Undo allocation of non allocated memory"); 1430 Check(ne, "Undo allocation of non allocated memory");
1733 #endif 1431 #endif
1734 // Write the address of the object to un-allocate as the current top. 1432 // Write the address of the object to un-allocate as the current top.
1735 mov(scratch, Operand(new_space_allocation_top)); 1433 mov(scratch, Operand(new_space_allocation_top));
1736 str(object, MemOperand(scratch)); 1434 str(object, MemOperand(scratch));
1737 } 1435 }
1738 1436
1739 1437
1740 void MacroAssembler::AllocateTwoByteString(Register result, 1438 void MacroAssembler::AllocateTwoByteString(Register result,
1741 Register length, 1439 Register length,
1742 Register scratch1, 1440 Register scratch1,
1743 Register scratch2, 1441 Register scratch2,
1744 Register scratch3, 1442 Register scratch3,
1745 Label* gc_required) { 1443 Label* gc_required) {
1746 // Calculate the number of bytes needed for the characters in the string while 1444 // Calculate the number of bytes needed for the characters in the string while
1747 // observing object alignment. 1445 // observing object alignment.
1748 ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); 1446 ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
1749 mov(scratch1, Operand(length, LSL, 1)); // Length in bytes, not chars. 1447 RECORD_LINE();
1448 lsl(scratch1, length, Operand(1)); // Length in bytes, not chars.
1750 add(scratch1, scratch1, 1449 add(scratch1, scratch1,
1751 Operand(kObjectAlignmentMask + SeqTwoByteString::kHeaderSize)); 1450 Operand(kObjectAlignmentMask + SeqTwoByteString::kHeaderSize));
1752 and_(scratch1, scratch1, Operand(~kObjectAlignmentMask)); 1451 land(scratch1, scratch1, Operand(~kObjectAlignmentMask));
1753 1452
1754 // Allocate two-byte string in new space. 1453 // Allocate two-byte string in new space.
1755 AllocateInNewSpace(scratch1, 1454 AllocateInNewSpace(scratch1,
1756 result, 1455 result,
1757 scratch2, 1456 scratch2,
1758 scratch3, 1457 scratch3,
1759 gc_required, 1458 gc_required,
1760 TAG_OBJECT); 1459 TAG_OBJECT);
1761 1460
1762 // Set the map, length and hash field. 1461 // Set the map, length and hash field.
1462 RECORD_LINE();
1763 InitializeNewString(result, 1463 InitializeNewString(result,
1764 length, 1464 length,
1765 Heap::kStringMapRootIndex, 1465 Heap::kStringMapRootIndex,
1766 scratch1, 1466 scratch1,
1767 scratch2); 1467 scratch2);
1768 } 1468 }
1769 1469
1770 1470
1771 void MacroAssembler::AllocateAsciiString(Register result, 1471 void MacroAssembler::AllocateAsciiString(Register result,
1772 Register length, 1472 Register length,
1773 Register scratch1, 1473 Register scratch1,
1774 Register scratch2, 1474 Register scratch2,
1775 Register scratch3, 1475 Register scratch3,
1776 Label* gc_required) { 1476 Label* gc_required) {
1777 // Calculate the number of bytes needed for the characters in the string while 1477 // Calculate the number of bytes needed for the characters in the string while
1778 // observing object alignment. 1478 // observing object alignment.
1779 ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); 1479 ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0);
1780 ASSERT(kCharSize == 1); 1480 ASSERT(kCharSize == 1);
1481 RECORD_LINE();
1781 add(scratch1, length, 1482 add(scratch1, length,
1782 Operand(kObjectAlignmentMask + SeqAsciiString::kHeaderSize)); 1483 Operand(kObjectAlignmentMask + SeqAsciiString::kHeaderSize));
1783 and_(scratch1, scratch1, Operand(~kObjectAlignmentMask)); 1484 land(scratch1, scratch1, Operand(~kObjectAlignmentMask));
1784 1485
1785 // Allocate ASCII string in new space. 1486 // Allocate ASCII string in new space.
1786 AllocateInNewSpace(scratch1, 1487 AllocateInNewSpace(scratch1,
1787 result, 1488 result,
1788 scratch2, 1489 scratch2,
1789 scratch3, 1490 scratch3,
1790 gc_required, 1491 gc_required,
1791 TAG_OBJECT); 1492 TAG_OBJECT);
1792 1493
1494 RECORD_LINE();
1793 // Set the map, length and hash field. 1495 // Set the map, length and hash field.
1794 InitializeNewString(result, 1496 InitializeNewString(result,
1795 length, 1497 length,
1796 Heap::kAsciiStringMapRootIndex, 1498 Heap::kAsciiStringMapRootIndex,
1797 scratch1, 1499 scratch1,
1798 scratch2); 1500 scratch2);
1799 } 1501 }
1800 1502
1801 1503
1802 void MacroAssembler::AllocateTwoByteConsString(Register result, 1504 void MacroAssembler::AllocateTwoByteConsString(Register result,
1803 Register length, 1505 Register length,
1804 Register scratch1, 1506 Register scratch1,
1805 Register scratch2, 1507 Register scratch2,
1806 Label* gc_required) { 1508 Label* gc_required) {
1509 RECORD_LINE();
1807 AllocateInNewSpace(ConsString::kSize, 1510 AllocateInNewSpace(ConsString::kSize,
1808 result, 1511 result,
1809 scratch1, 1512 scratch1,
1810 scratch2, 1513 scratch2,
1811 gc_required, 1514 gc_required,
1812 TAG_OBJECT); 1515 TAG_OBJECT);
1813 1516
1517 RECORD_LINE();
1814 InitializeNewString(result, 1518 InitializeNewString(result,
1815 length, 1519 length,
1816 Heap::kConsStringMapRootIndex, 1520 Heap::kConsStringMapRootIndex,
1817 scratch1, 1521 scratch1,
1818 scratch2); 1522 scratch2);
1819 } 1523 }
1820 1524
1821 1525
1822 void MacroAssembler::AllocateAsciiConsString(Register result, 1526 void MacroAssembler::AllocateAsciiConsString(Register result,
1823 Register length, 1527 Register length,
1824 Register scratch1, 1528 Register scratch1,
1825 Register scratch2, 1529 Register scratch2,
1826 Label* gc_required) { 1530 Label* gc_required) {
1531 RECORD_LINE();
1827 AllocateInNewSpace(ConsString::kSize, 1532 AllocateInNewSpace(ConsString::kSize,
1828 result, 1533 result,
1829 scratch1, 1534 scratch1,
1830 scratch2, 1535 scratch2,
1831 gc_required, 1536 gc_required,
1832 TAG_OBJECT); 1537 TAG_OBJECT);
1833 1538
1539 RECORD_LINE();
1834 InitializeNewString(result, 1540 InitializeNewString(result,
1835 length, 1541 length,
1836 Heap::kConsAsciiStringMapRootIndex, 1542 Heap::kConsAsciiStringMapRootIndex,
1837 scratch1, 1543 scratch1,
1838 scratch2); 1544 scratch2);
1839 } 1545 }
1840 1546
1841 1547
1842 void MacroAssembler::AllocateTwoByteSlicedString(Register result, 1548 void MacroAssembler::AllocateTwoByteSlicedString(Register result,
1843 Register length, 1549 Register length,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1875 length, 1581 length,
1876 Heap::kSlicedAsciiStringMapRootIndex, 1582 Heap::kSlicedAsciiStringMapRootIndex,
1877 scratch1, 1583 scratch1,
1878 scratch2); 1584 scratch2);
1879 } 1585 }
1880 1586
1881 1587
1882 void MacroAssembler::CompareObjectType(Register object, 1588 void MacroAssembler::CompareObjectType(Register object,
1883 Register map, 1589 Register map,
1884 Register type_reg, 1590 Register type_reg,
1885 InstanceType type) { 1591 InstanceType type,
1592 Condition cond) {
1593 ASSERT(!object.is(sh4_ip) && !map.is(sh4_ip) && !type_reg.is(sh4_ip));
1594 ASSERT(!object.is(sh4_rtmp) && !map.is(sh4_rtmp) && !type_reg.is(sh4_rtmp));
1595
1596 RECORD_LINE();
1886 ldr(map, FieldMemOperand(object, HeapObject::kMapOffset)); 1597 ldr(map, FieldMemOperand(object, HeapObject::kMapOffset));
1887 CompareInstanceType(map, type_reg, type); 1598 CompareInstanceType(map, type_reg, type, cond);
1888 } 1599 }
1889 1600
1890 1601
1891 void MacroAssembler::CompareInstanceType(Register map, 1602 void MacroAssembler::CompareInstanceType(Register map,
1892 Register type_reg, 1603 Register type_reg,
1893 InstanceType type) { 1604 InstanceType type,
1605 Condition cond) {
1606 ASSERT(!map.is(sh4_rtmp) && !type_reg.is(sh4_rtmp));
1607
1608 RECORD_LINE();
1894 ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset)); 1609 ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
1895 cmp(type_reg, Operand(type)); 1610 switch (cond) {
1611 case eq:
1612 RECORD_LINE();
1613 cmpeq(type_reg, Operand(type));
1614 break;
1615 case ge:
1616 RECORD_LINE();
1617 cmpge(type_reg, Operand(type));
1618 break;
1619 case hs:
1620 RECORD_LINE();
1621 cmphs(type_reg, Operand(type));
1622 break;
1623 case gt:
1624 RECORD_LINE();
1625 cmpgt(type_reg, Operand(type));
1626 break;
1627 default:
1628 UNIMPLEMENTED();
1629 }
1896 } 1630 }
1897 1631
1898 1632
1899 void MacroAssembler::CompareRoot(Register obj, 1633 void MacroAssembler::CompareRoot(Register obj,
1900 Heap::RootListIndex index) { 1634 Heap::RootListIndex index) {
1901 ASSERT(!obj.is(ip)); 1635 ASSERT(!obj.is(sh4_ip));
1636 ASSERT(!obj.is(sh4_rtmp));
1637 RECORD_LINE();
1902 LoadRoot(ip, index); 1638 LoadRoot(ip, index);
1903 cmp(obj, ip); 1639 cmpeq(obj, ip);
1904 } 1640 }
1905 1641
1906 1642
1907 void MacroAssembler::CheckFastElements(Register map, 1643 void MacroAssembler::CheckFastElements(Register map,
1908 Register scratch, 1644 Register scratch,
1909 Label* fail) { 1645 Label* fail) {
1910 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); 1646 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
1911 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 1647 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
1912 STATIC_ASSERT(FAST_ELEMENTS == 2); 1648 STATIC_ASSERT(FAST_ELEMENTS == 2);
1913 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); 1649 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
1914 ldrb(scratch, FieldMemOperand(map, Map::kBitField2Offset)); 1650 ldrb(scratch, FieldMemOperand(map, Map::kBitField2Offset));
1915 cmp(scratch, Operand(Map::kMaximumBitField2FastHoleyElementValue)); 1651 cmphi(scratch, Operand(Map::kMaximumBitField2FastHoleyElementValue));
1916 b(hi, fail); 1652 bt(fail);
1917 } 1653 }
1918 1654
1919 1655
1920 void MacroAssembler::CheckFastObjectElements(Register map, 1656 void MacroAssembler::CheckFastObjectElements(Register map,
1921 Register scratch, 1657 Register scratch,
1922 Label* fail) { 1658 Label* fail) {
1923 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); 1659 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
1924 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 1660 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
1925 STATIC_ASSERT(FAST_ELEMENTS == 2); 1661 STATIC_ASSERT(FAST_ELEMENTS == 2);
1926 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); 1662 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
1927 ldrb(scratch, FieldMemOperand(map, Map::kBitField2Offset)); 1663 ldrb(scratch, FieldMemOperand(map, Map::kBitField2Offset));
1928 cmp(scratch, Operand(Map::kMaximumBitField2FastHoleySmiElementValue)); 1664 cmpgt(scratch, Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
1929 b(ls, fail); 1665 bf(fail);
1930 cmp(scratch, Operand(Map::kMaximumBitField2FastHoleyElementValue)); 1666 cmphi(scratch, Operand(Map::kMaximumBitField2FastHoleyElementValue));
1931 b(hi, fail); 1667 bt(fail);
1932 } 1668 }
1933 1669
1934
1935 void MacroAssembler::CheckFastSmiElements(Register map, 1670 void MacroAssembler::CheckFastSmiElements(Register map,
1936 Register scratch, 1671 Register scratch,
1937 Label* fail) { 1672 Label* fail) {
1938 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); 1673 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
1939 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 1674 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
1940 ldrb(scratch, FieldMemOperand(map, Map::kBitField2Offset)); 1675 ldrb(scratch, FieldMemOperand(map, Map::kBitField2Offset));
1941 cmp(scratch, Operand(Map::kMaximumBitField2FastHoleySmiElementValue)); 1676 cmphi(scratch, Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
1942 b(hi, fail); 1677 bt(fail);
1943 } 1678 }
1944 1679
1945 1680
1946 void MacroAssembler::StoreNumberToDoubleElements(Register value_reg, 1681 void MacroAssembler::StoreNumberToDoubleElements(Register value_reg,
1947 Register key_reg, 1682 Register key_reg,
1948 Register receiver_reg, 1683 Register receiver_reg,
1949 Register elements_reg, 1684 Register elements_reg,
1950 Register scratch1, 1685 Register scratch1,
1951 Register scratch2, 1686 Register scratch2,
1952 Register scratch3, 1687 Register scratch3,
1953 Register scratch4, 1688 Register scratch4,
1954 Label* fail) { 1689 Label* fail) {
1955 Label smi_value, maybe_nan, have_double_value, is_nan, done; 1690 UNIMPLEMENTED_BREAK();
1956 Register mantissa_reg = scratch2; 1691 }
1957 Register exponent_reg = scratch3;
1958 1692
1959 // Handle smi values specially.
1960 JumpIfSmi(value_reg, &smi_value);
1961
1962 // Ensure that the object is a heap number
1963 CheckMap(value_reg,
1964 scratch1,
1965 isolate()->factory()->heap_number_map(),
1966 fail,
1967 DONT_DO_SMI_CHECK);
1968
1969 // Check for nan: all NaN values have a value greater (signed) than 0x7ff00000
1970 // in the exponent.
1971 mov(scratch1, Operand(kNaNOrInfinityLowerBoundUpper32));
1972 ldr(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset));
1973 cmp(exponent_reg, scratch1);
1974 b(ge, &maybe_nan);
1975
1976 ldr(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
1977
1978 bind(&have_double_value);
1979 add(scratch1, elements_reg,
1980 Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
1981 str(mantissa_reg, FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize));
1982 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
1983 str(exponent_reg, FieldMemOperand(scratch1, offset));
1984 jmp(&done);
1985
1986 bind(&maybe_nan);
1987 // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
1988 // it's an Infinity, and the non-NaN code path applies.
1989 b(gt, &is_nan);
1990 ldr(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
1991 cmp(mantissa_reg, Operand(0));
1992 b(eq, &have_double_value);
1993 bind(&is_nan);
1994 // Load canonical NaN for storing into the double array.
1995 uint64_t nan_int64 = BitCast<uint64_t>(
1996 FixedDoubleArray::canonical_not_the_hole_nan_as_double());
1997 mov(mantissa_reg, Operand(static_cast<uint32_t>(nan_int64)));
1998 mov(exponent_reg, Operand(static_cast<uint32_t>(nan_int64 >> 32)));
1999 jmp(&have_double_value);
2000
2001 bind(&smi_value);
2002 add(scratch1, elements_reg,
2003 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
2004 add(scratch1, scratch1,
2005 Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
2006 // scratch1 is now effective address of the double element
2007
2008 FloatingPointHelper::Destination destination;
2009 if (CpuFeatures::IsSupported(VFP2)) {
2010 destination = FloatingPointHelper::kVFPRegisters;
2011 } else {
2012 destination = FloatingPointHelper::kCoreRegisters;
2013 }
2014
2015 Register untagged_value = elements_reg;
2016 SmiUntag(untagged_value, value_reg);
2017 FloatingPointHelper::ConvertIntToDouble(this,
2018 untagged_value,
2019 destination,
2020 d0,
2021 mantissa_reg,
2022 exponent_reg,
2023 scratch4,
2024 s2);
2025 if (destination == FloatingPointHelper::kVFPRegisters) {
2026 CpuFeatures::Scope scope(VFP2);
2027 vstr(d0, scratch1, 0);
2028 } else {
2029 str(mantissa_reg, MemOperand(scratch1, 0));
2030 str(exponent_reg, MemOperand(scratch1, Register::kSizeInBytes));
2031 }
2032 bind(&done);
2033 }
2034 1693
2035 1694
2036 void MacroAssembler::CompareMap(Register obj, 1695 void MacroAssembler::CompareMap(Register obj,
2037 Register scratch, 1696 Register scratch,
2038 Handle<Map> map, 1697 Handle<Map> map,
2039 Label* early_success, 1698 Label* early_success,
2040 CompareMapMode mode) { 1699 CompareMapMode mode) {
2041 ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); 1700 ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
2042 CompareMap(scratch, map, early_success, mode); 1701 CompareMap(scratch, map, early_success, mode);
2043 } 1702 }
2044 1703
2045 1704
2046 void MacroAssembler::CompareMap(Register obj_map, 1705 void MacroAssembler::CompareMap(Register obj_map,
2047 Handle<Map> map, 1706 Handle<Map> map,
2048 Label* early_success, 1707 Label* early_success,
2049 CompareMapMode mode) { 1708 CompareMapMode mode) {
2050 cmp(obj_map, Operand(map)); 1709 cmpeq(obj_map, Operand(map));
2051 if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) { 1710 if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) {
2052 ElementsKind kind = map->elements_kind(); 1711 ElementsKind kind = map->elements_kind();
2053 if (IsFastElementsKind(kind)) { 1712 if (IsFastElementsKind(kind)) {
2054 bool packed = IsFastPackedElementsKind(kind); 1713 bool packed = IsFastPackedElementsKind(kind);
2055 Map* current_map = *map; 1714 Map* current_map = *map;
2056 while (CanTransitionToMoreGeneralFastElementsKind(kind, packed)) { 1715 while (CanTransitionToMoreGeneralFastElementsKind(kind, packed)) {
2057 kind = GetNextMoreGeneralFastElementsKind(kind, packed); 1716 kind = GetNextMoreGeneralFastElementsKind(kind, packed);
2058 current_map = current_map->LookupElementsTransitionMap(kind); 1717 current_map = current_map->LookupElementsTransitionMap(kind);
2059 if (!current_map) break; 1718 if (!current_map) break;
2060 b(eq, early_success); 1719 b(eq, early_success);
2061 cmp(obj_map, Operand(Handle<Map>(current_map))); 1720 cmpeq(obj_map, Operand(Handle<Map>(current_map)));
2062 } 1721 }
2063 } 1722 }
2064 } 1723 }
2065 } 1724 }
2066 1725
2067 1726
1727
2068 void MacroAssembler::CheckMap(Register obj, 1728 void MacroAssembler::CheckMap(Register obj,
2069 Register scratch, 1729 Register scratch,
2070 Handle<Map> map, 1730 Handle<Map> map,
2071 Label* fail, 1731 Label* fail,
2072 SmiCheckType smi_check_type, 1732 SmiCheckType smi_check_type,
2073 CompareMapMode mode) { 1733 CompareMapMode mode) {
1734 ASSERT(!obj.is(sh4_ip) && !scratch.is(sh4_ip));
1735 ASSERT(!obj.is(sh4_rtmp) && !scratch.is(sh4_rtmp));
1736 RECORD_LINE();
2074 if (smi_check_type == DO_SMI_CHECK) { 1737 if (smi_check_type == DO_SMI_CHECK) {
1738 RECORD_LINE();
2075 JumpIfSmi(obj, fail); 1739 JumpIfSmi(obj, fail);
2076 } 1740 }
2077 1741
1742 RECORD_LINE();
2078 Label success; 1743 Label success;
2079 CompareMap(obj, scratch, map, &success, mode); 1744 CompareMap(obj, scratch, map, &success, mode);
2080 b(ne, fail); 1745 b(ne, fail);
2081 bind(&success); 1746 bind(&success);
2082 } 1747 }
2083 1748
2084 1749
2085 void MacroAssembler::CheckMap(Register obj, 1750 void MacroAssembler::CheckMap(Register obj,
2086 Register scratch, 1751 Register scratch,
2087 Heap::RootListIndex index, 1752 Heap::RootListIndex index,
2088 Label* fail, 1753 Label* fail,
2089 SmiCheckType smi_check_type) { 1754 SmiCheckType smi_check_type) {
1755 ASSERT(!obj.is(sh4_ip) && !scratch.is(sh4_ip));
1756 ASSERT(!obj.is(sh4_rtmp) && !scratch.is(sh4_rtmp));
1757 RECORD_LINE();
2090 if (smi_check_type == DO_SMI_CHECK) { 1758 if (smi_check_type == DO_SMI_CHECK) {
1759 RECORD_LINE();
2091 JumpIfSmi(obj, fail); 1760 JumpIfSmi(obj, fail);
2092 } 1761 }
1762 RECORD_LINE();
2093 ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); 1763 ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
2094 LoadRoot(ip, index); 1764 LoadRoot(ip, index);
2095 cmp(scratch, ip); 1765 cmp(scratch, ip);
2096 b(ne, fail); 1766 b(ne, fail);
2097 } 1767 }
2098 1768
2099 1769
2100 void MacroAssembler::DispatchMap(Register obj, 1770 void MacroAssembler::DispatchMap(Register obj,
2101 Register scratch, 1771 Register scratch,
2102 Handle<Map> map, 1772 Handle<Map> map,
2103 Handle<Code> success, 1773 Handle<Code> success,
2104 SmiCheckType smi_check_type) { 1774 SmiCheckType smi_check_type) {
2105 Label fail; 1775 Label fail;
2106 if (smi_check_type == DO_SMI_CHECK) { 1776 if (smi_check_type == DO_SMI_CHECK) {
2107 JumpIfSmi(obj, &fail); 1777 JumpIfSmi(obj, &fail, Label::kNear);
2108 } 1778 }
2109 ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); 1779 ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
2110 mov(ip, Operand(map)); 1780 mov(ip, Operand(map));
2111 cmp(scratch, ip); 1781 cmp(scratch, ip);
2112 Jump(success, RelocInfo::CODE_TARGET, eq); 1782 Label skip;
1783 bf(&skip);
1784 Jump(success, RelocInfo::CODE_TARGET);
1785 bind(&skip);
2113 bind(&fail); 1786 bind(&fail);
2114 } 1787 }
2115 1788
2116 1789
2117 void MacroAssembler::TryGetFunctionPrototype(Register function, 1790 void MacroAssembler::TryGetFunctionPrototype(Register function,
2118 Register result, 1791 Register result,
2119 Register scratch, 1792 Register scratch,
2120 Label* miss, 1793 Label* miss,
2121 bool miss_on_bound_function) { 1794 bool miss_on_bound_function) {
1795 ASSERT(!function.is(sh4_ip) && !result.is(sh4_ip) && !scratch.is(sh4_ip));
1796 ASSERT(!function.is(sh4_rtmp) && !result.is(sh4_rtmp) &&
1797 !scratch.is(sh4_rtmp));
1798
1799 RECORD_LINE();
2122 // Check that the receiver isn't a smi. 1800 // Check that the receiver isn't a smi.
2123 JumpIfSmi(function, miss); 1801 JumpIfSmi(function, miss);
2124 1802
2125 // Check that the function really is a function. Load map into result reg. 1803 // Check that the function really is a function. Load map into result reg.
2126 CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE); 1804 CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE, eq);
2127 b(ne, miss); 1805 bf(miss);
2128 1806
2129 if (miss_on_bound_function) { 1807 if (miss_on_bound_function) {
1808 RECORD_LINE();
2130 ldr(scratch, 1809 ldr(scratch,
2131 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); 1810 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
2132 ldr(scratch, 1811 ldr(scratch,
2133 FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset)); 1812 FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
2134 tst(scratch, 1813 tst(scratch,
2135 Operand(Smi::FromInt(1 << SharedFunctionInfo::kBoundFunction))); 1814 Operand(Smi::FromInt(1 << SharedFunctionInfo::kBoundFunction)));
2136 b(ne, miss); 1815 b(ne, miss);
2137 } 1816 }
2138 1817
1818 RECORD_LINE();
2139 // Make sure that the function has an instance prototype. 1819 // Make sure that the function has an instance prototype.
2140 Label non_instance; 1820 Label non_instance;
2141 ldrb(scratch, FieldMemOperand(result, Map::kBitFieldOffset)); 1821 ldrb(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
2142 tst(scratch, Operand(1 << Map::kHasNonInstancePrototype)); 1822 tst(scratch, Operand(1 << Map::kHasNonInstancePrototype));
2143 b(ne, &non_instance); 1823 bf_near(&non_instance);
2144 1824
1825 RECORD_LINE();
2145 // Get the prototype or initial map from the function. 1826 // Get the prototype or initial map from the function.
2146 ldr(result, 1827 ldr(result,
2147 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 1828 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2148 1829
2149 // If the prototype or initial map is the hole, don't return it and 1830 // If the prototype or initial map is the hole, don't return it and
2150 // simply miss the cache instead. This will allow us to allocate a 1831 // simply miss the cache instead. This will allow us to allocate a
2151 // prototype object on-demand in the runtime system. 1832 // prototype object on-demand in the runtime system.
2152 LoadRoot(ip, Heap::kTheHoleValueRootIndex); 1833 LoadRoot(ip, Heap::kTheHoleValueRootIndex);
2153 cmp(result, ip); 1834 cmp(result, ip);
2154 b(eq, miss); 1835 b(eq, miss);
2155 1836
1837 RECORD_LINE();
2156 // If the function does not have an initial map, we're done. 1838 // If the function does not have an initial map, we're done.
2157 Label done; 1839 Label done;
2158 CompareObjectType(result, scratch, scratch, MAP_TYPE); 1840 CompareObjectType(result, scratch, scratch, MAP_TYPE, eq);
2159 b(ne, &done); 1841 bf_near(&done);
2160 1842
1843 RECORD_LINE();
2161 // Get the prototype from the initial map. 1844 // Get the prototype from the initial map.
2162 ldr(result, FieldMemOperand(result, Map::kPrototypeOffset)); 1845 ldr(result, FieldMemOperand(result, Map::kPrototypeOffset));
2163 jmp(&done); 1846 jmp_near(&done);
2164 1847
1848 RECORD_LINE();
2165 // Non-instance prototype: Fetch prototype from constructor field 1849 // Non-instance prototype: Fetch prototype from constructor field
2166 // in initial map. 1850 // in initial map.
2167 bind(&non_instance); 1851 bind(&non_instance);
2168 ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); 1852 ldr(result, FieldMemOperand(result, Map::kConstructorOffset));
2169 1853
2170 // All done. 1854 // All done.
2171 bind(&done); 1855 bind(&done);
2172 } 1856 }
2173 1857
2174 1858
2175 void MacroAssembler::CallStub(CodeStub* stub, Condition cond) { 1859 void MacroAssembler::CallStub(CodeStub* stub) {
2176 ASSERT(AllowThisStubCall(stub)); // Stub calls are not allowed in some stubs. 1860 ASSERT(AllowThisStubCall(stub)); // Stub calls are not allowed in some stubs.
2177 Call(stub->GetCode(), RelocInfo::CODE_TARGET, TypeFeedbackId::None(), cond); 1861 Call(stub->GetCode(), RelocInfo::CODE_TARGET, TypeFeedbackId::None());
2178 } 1862 }
2179 1863
2180 1864
2181 void MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) { 1865 void MacroAssembler::TailCallStub(CodeStub* stub) {
2182 ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe()); 1866 ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe());
2183 Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond); 1867 Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
2184 } 1868 }
2185 1869
2186 1870
2187 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { 1871 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
2188 return ref0.address() - ref1.address(); 1872 return ref0.address() - ref1.address();
2189 } 1873 }
2190 1874
2191 1875
2192 void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function, 1876 void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
2193 int stack_space) { 1877 int stack_space) {
2194 ExternalReference next_address = 1878 ExternalReference next_address =
2195 ExternalReference::handle_scope_next_address(); 1879 ExternalReference::handle_scope_next_address();
2196 const int kNextOffset = 0; 1880 const int kNextOffset = 0;
2197 const int kLimitOffset = AddressOffset( 1881 const int kLimitOffset = AddressOffset(
2198 ExternalReference::handle_scope_limit_address(), 1882 ExternalReference::handle_scope_limit_address(),
2199 next_address); 1883 next_address);
2200 const int kLevelOffset = AddressOffset( 1884 const int kLevelOffset = AddressOffset(
2201 ExternalReference::handle_scope_level_address(), 1885 ExternalReference::handle_scope_level_address(),
2202 next_address); 1886 next_address);
2203 1887
1888 mov(r4, r0);
1889 mov(r5, r1);
1890
2204 // Allocate HandleScope in callee-save registers. 1891 // Allocate HandleScope in callee-save registers.
2205 mov(r7, Operand(next_address)); 1892 // TODO(stm): use of r10 and r11 is dangerous here (ip and rtmp)
2206 ldr(r4, MemOperand(r7, kNextOffset)); 1893 // We must be sure to not have them clobbered until the actual call.
2207 ldr(r5, MemOperand(r7, kLimitOffset)); 1894 mov(sh4_r11, Operand(next_address));
2208 ldr(r6, MemOperand(r7, kLevelOffset)); 1895 ldr(sh4_r8, MemOperand(sh4_r11, kNextOffset), r0);
2209 add(r6, r6, Operand(1)); 1896 ldr(r9, MemOperand(sh4_r11, kLimitOffset), r0);
2210 str(r6, MemOperand(r7, kLevelOffset)); 1897 ldr(sh4_r10, MemOperand(sh4_r11, kLevelOffset), r0);
1898 add(sh4_r10, sh4_r10, Operand(1), r0);
1899 str(sh4_r10, MemOperand(sh4_r11, kLevelOffset), r0);
2211 1900
2212 // Native call returns to the DirectCEntry stub which redirects to the 1901 // Native call returns to the DirectCEntry stub which redirects to the
2213 // return address pushed on stack (could have moved after GC). 1902 // return address pushed on stack (could have moved after GC).
2214 // DirectCEntry stub itself is generated early and never moves. 1903 // DirectCEntry stub itself is generated early and never moves.
2215 DirectCEntryStub stub; 1904 // This scratch register must not be the return value
2216 stub.GenerateCall(this, function); 1905 DirectCEntryStub stub(r2);
1906 stub.GenerateCall(this, function, r0, r1);
1907
1908 // Move back the registers [r8, r11] => [r4, r7]
1909 mov(r4, sh4_r8);
1910 mov(r5, r9);
1911 mov(r6, sh4_r10);
1912 mov(r7, sh4_r11);
2217 1913
2218 Label promote_scheduled_exception; 1914 Label promote_scheduled_exception;
2219 Label delete_allocated_handles; 1915 Label delete_allocated_handles;
2220 Label leave_exit_frame; 1916 Label leave_exit_frame;
2221 1917
2222 // If result is non-zero, dereference to get the result value 1918 // If result is non-zero, dereference to get the result value
2223 // otherwise set it to undefined. 1919 // otherwise set it to undefined.
1920 Label ltrue, lfalse;
2224 cmp(r0, Operand(0)); 1921 cmp(r0, Operand(0));
2225 LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); 1922 bf_near(&lfalse);
2226 ldr(r0, MemOperand(r0), ne); 1923 LoadRoot(r0, Heap::kUndefinedValueRootIndex);
1924 jmp_near(&ltrue);
1925 bind(&lfalse);
1926 ldr(r0, MemOperand(r0));
1927 bind(&ltrue);
2227 1928
2228 // No more valid handles (the result handle was the last one). Restore 1929 // No more valid handles (the result handle was the last one). Restore
2229 // previous handle scope. 1930 // previous handle scope.
2230 str(r4, MemOperand(r7, kNextOffset)); 1931 str(r4, MemOperand(r7, kNextOffset));
2231 if (emit_debug_code()) { 1932 if (emit_debug_code()) {
2232 ldr(r1, MemOperand(r7, kLevelOffset)); 1933 ldr(r1, MemOperand(r7, kLevelOffset));
2233 cmp(r1, r6); 1934 cmp(r1, r6);
2234 Check(eq, "Unexpected level after return from api call"); 1935 Check(eq, "Unexpected level after return from api call");
2235 } 1936 }
2236 sub(r6, r6, Operand(1)); 1937 sub(r6, r6, Operand(1));
2237 str(r6, MemOperand(r7, kLevelOffset)); 1938 str(r6, MemOperand(r7, kLevelOffset));
2238 ldr(ip, MemOperand(r7, kLimitOffset)); 1939 ldr(sh4_ip, MemOperand(r7, kLimitOffset));
2239 cmp(r5, ip); 1940 cmp(r5, sh4_ip);
2240 b(ne, &delete_allocated_handles); 1941 b(ne, &delete_allocated_handles);
2241 1942
2242 // Check if the function scheduled an exception. 1943 // Check if the function scheduled an exception.
2243 bind(&leave_exit_frame); 1944 bind(&leave_exit_frame);
2244 LoadRoot(r4, Heap::kTheHoleValueRootIndex); 1945 LoadRoot(r4, Heap::kTheHoleValueRootIndex);
2245 mov(ip, Operand(ExternalReference::scheduled_exception_address(isolate()))); 1946 mov(sh4_ip,
2246 ldr(r5, MemOperand(ip)); 1947 Operand(ExternalReference::scheduled_exception_address(isolate())));
1948 ldr(r5, MemOperand(sh4_ip));
2247 cmp(r4, r5); 1949 cmp(r4, r5);
2248 b(ne, &promote_scheduled_exception); 1950 b(ne, &promote_scheduled_exception);
2249 1951
2250 // LeaveExitFrame expects unwind space to be in a register. 1952 // LeaveExitFrame expects unwind space to be in a register.
2251 mov(r4, Operand(stack_space)); 1953 mov(r4, Operand(stack_space));
2252 LeaveExitFrame(false, r4); 1954 LeaveExitFrame(false, r4);
2253 mov(pc, lr); 1955 rts();
2254 1956
2255 bind(&promote_scheduled_exception); 1957 bind(&promote_scheduled_exception);
2256 TailCallExternalReference( 1958 TailCallExternalReference(
2257 ExternalReference(Runtime::kPromoteScheduledException, isolate()), 1959 ExternalReference(Runtime::kPromoteScheduledException, isolate()),
2258 0, 1960 0,
2259 1); 1961 1);
2260 1962
2261 // HandleScope limit has changed. Delete allocated extensions. 1963 // HandleScope limit has changed. Delete allocated extensions.
2262 bind(&delete_allocated_handles); 1964 bind(&delete_allocated_handles);
2263 str(r5, MemOperand(r7, kLimitOffset)); 1965 // use r9 instead of r5 for making PrepareCallCFunction() happy
2264 mov(r4, r0); 1966 str(r9, MemOperand(r7, kLimitOffset));
2265 PrepareCallCFunction(1, r5); 1967 mov(sh4_r8, r0); // preserve in calle-saved the result (r0)
2266 mov(r0, Operand(ExternalReference::isolate_address())); 1968 PrepareCallCFunction(1, r9);
1969 mov(r4, Operand(ExternalReference::isolate_address())); // C-ABI paramater
2267 CallCFunction( 1970 CallCFunction(
2268 ExternalReference::delete_handle_scope_extensions(isolate()), 1); 1971 ExternalReference::delete_handle_scope_extensions(isolate()), 1);
2269 mov(r0, r4); 1972 mov(r0, sh4_r8); // restore result (r0)
2270 jmp(&leave_exit_frame); 1973 jmp(&leave_exit_frame);
2271 } 1974 }
2272 1975
2273 1976
2274 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { 1977 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
2275 if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false; 1978 if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false;
2276 return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe(); 1979 return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe();
2277 } 1980 }
2278 1981
2279 1982
2280 void MacroAssembler::IllegalOperation(int num_arguments) { 1983 void MacroAssembler::IllegalOperation(int num_arguments) {
1984 RECORD_LINE();
2281 if (num_arguments > 0) { 1985 if (num_arguments > 0) {
2282 add(sp, sp, Operand(num_arguments * kPointerSize)); 1986 add(sp, sp, Operand(num_arguments * kPointerSize));
2283 } 1987 }
2284 LoadRoot(r0, Heap::kUndefinedValueRootIndex); 1988 LoadRoot(r0, Heap::kUndefinedValueRootIndex);
2285 } 1989 }
2286 1990
1991 void MacroAssembler::SmiToDoubleFPURegister(Register smi,
1992 DwVfpRegister value,
1993 Register scratch) {
1994 asr(scratch, smi, Operand(kSmiTagSize));
1995 dfloat(value, scratch);
1996 }
1997
2287 1998
2288 void MacroAssembler::IndexFromHash(Register hash, Register index) { 1999 void MacroAssembler::IndexFromHash(Register hash, Register index) {
2289 // If the hash field contains an array index pick it out. The assert checks 2000 // If the hash field contains an array index pick it out. The assert checks
2290 // that the constants for the maximum number of digits for an array index 2001 // that the constants for the maximum number of digits for an array index
2291 // cached in the hash field and the number of bits reserved for it does not 2002 // cached in the hash field and the number of bits reserved for it does not
2292 // conflict. 2003 // conflict.
2293 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < 2004 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
2294 (1 << String::kArrayIndexValueBits)); 2005 (1 << String::kArrayIndexValueBits));
2295 // We want the smi-tagged index in key. kArrayIndexValueMask has zeros in 2006 // We want the smi-tagged index in key. kArrayIndexValueMask has zeros in
2296 // the low kHashShift bits. 2007 // the low kHashShift bits.
2297 STATIC_ASSERT(kSmiTag == 0); 2008 STATIC_ASSERT(kSmiTag == 0);
2009 ASSERT(!hash.is(sh4_ip) && !index.is(sh4_ip));
2010 ASSERT(!hash.is(sh4_rtmp) && !index.is(sh4_rtmp));
2011 RECORD_LINE();
2298 Ubfx(hash, hash, String::kHashShift, String::kArrayIndexValueBits); 2012 Ubfx(hash, hash, String::kHashShift, String::kArrayIndexValueBits);
2299 mov(index, Operand(hash, LSL, kSmiTagSize)); 2013 lsl(index, hash, Operand(kSmiTagSize));
2300 } 2014 }
2301 2015
2302 2016
2303 void MacroAssembler::IntegerToDoubleConversionWithVFP3(Register inReg,
2304 Register outHighReg,
2305 Register outLowReg) {
2306 // ARMv7 VFP3 instructions to implement integer to double conversion.
2307 mov(r7, Operand(inReg, ASR, kSmiTagSize));
2308 vmov(s15, r7);
2309 vcvt_f64_s32(d7, s15);
2310 vmov(outLowReg, outHighReg, d7);
2311 }
2312
2313
2314 void MacroAssembler::ObjectToDoubleVFPRegister(Register object,
2315 DwVfpRegister result,
2316 Register scratch1,
2317 Register scratch2,
2318 Register heap_number_map,
2319 SwVfpRegister scratch3,
2320 Label* not_number,
2321 ObjectToDoubleFlags flags) {
2322 Label done;
2323 if ((flags & OBJECT_NOT_SMI) == 0) {
2324 Label not_smi;
2325 JumpIfNotSmi(object, &not_smi);
2326 // Remove smi tag and convert to double.
2327 mov(scratch1, Operand(object, ASR, kSmiTagSize));
2328 vmov(scratch3, scratch1);
2329 vcvt_f64_s32(result, scratch3);
2330 b(&done);
2331 bind(&not_smi);
2332 }
2333 // Check for heap number and load double value from it.
2334 ldr(scratch1, FieldMemOperand(object, HeapObject::kMapOffset));
2335 sub(scratch2, object, Operand(kHeapObjectTag));
2336 cmp(scratch1, heap_number_map);
2337 b(ne, not_number);
2338 if ((flags & AVOID_NANS_AND_INFINITIES) != 0) {
2339 // If exponent is all ones the number is either a NaN or +/-Infinity.
2340 ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
2341 Sbfx(scratch1,
2342 scratch1,
2343 HeapNumber::kExponentShift,
2344 HeapNumber::kExponentBits);
2345 // All-one value sign extend to -1.
2346 cmp(scratch1, Operand(-1));
2347 b(eq, not_number);
2348 }
2349 vldr(result, scratch2, HeapNumber::kValueOffset);
2350 bind(&done);
2351 }
2352
2353
2354 void MacroAssembler::SmiToDoubleVFPRegister(Register smi,
2355 DwVfpRegister value,
2356 Register scratch1,
2357 SwVfpRegister scratch2) {
2358 mov(scratch1, Operand(smi, ASR, kSmiTagSize));
2359 vmov(scratch2, scratch1);
2360 vcvt_f64_s32(value, scratch2);
2361 }
2362
2363
2364 // Tries to get a signed int32 out of a double precision floating point heap 2017 // Tries to get a signed int32 out of a double precision floating point heap
2365 // number. Rounds towards 0. Branch to 'not_int32' if the double is out of the 2018 // number. Rounds towards 0. Branch to 'not_int32' if the double is out of the
2366 // 32bits signed integer range. 2019 // 32bits signed integer range.
2367 void MacroAssembler::ConvertToInt32(Register source, 2020 void MacroAssembler::ConvertToInt32(Register source,
2368 Register dest, 2021 Register dest,
2369 Register scratch, 2022 Register scratch,
2370 Register scratch2, 2023 Register scratch2,
2371 DwVfpRegister double_scratch, 2024 DwVfpRegister double_scratch,
2372 Label *not_int32) { 2025 Label *not_int32) {
2373 if (CpuFeatures::IsSupported(VFP2)) { 2026 ASSERT(!source.is(sh4_ip) && !dest.is(sh4_ip) && !scratch.is(sh4_ip) &&
2374 CpuFeatures::Scope scope(VFP2); 2027 !scratch2.is(sh4_ip));
2028 ASSERT(!source.is(sh4_rtmp) && !dest.is(sh4_rtmp) && !scratch.is(sh4_rtmp) &&
2029 !scratch2.is(sh4_rtmp));
2030 ASSERT(!source.is(dest) && !source.is(scratch) && !source.is(scratch2) &&
2031 !dest.is(scratch) && !dest.is(scratch2) && !scratch.is(scratch2));
2032
2033 if (CpuFeatures::IsSupported(FPU)) {
2375 sub(scratch, source, Operand(kHeapObjectTag)); 2034 sub(scratch, source, Operand(kHeapObjectTag));
2376 vldr(double_scratch, scratch, HeapNumber::kValueOffset); 2035 dldr(double_scratch, MemOperand(scratch, HeapNumber::kValueOffset));
2377 vcvt_s32_f64(double_scratch.low(), double_scratch); 2036 idouble(dest, double_scratch);
2378 vmov(dest, double_scratch.low());
2379 // Signed vcvt instruction will saturate to the minimum (0x80000000) or 2037 // Signed vcvt instruction will saturate to the minimum (0x80000000) or
2380 // maximun (0x7fffffff) signed 32bits integer when the double is out of 2038 // maximun (0x7fffffff) signed 32bits integer when the double is out of
2381 // range. When substracting one, the minimum signed integer becomes the 2039 // range. When substracting one, the minimum signed integer becomes the
2382 // maximun signed integer. 2040 // maximun signed integer.
2383 sub(scratch, dest, Operand(1)); 2041 sub(scratch, dest, Operand(1));
2384 cmp(scratch, Operand(LONG_MAX - 1)); 2042 cmpge(scratch, Operand(LONG_MAX - 1));
2385 // If equal then dest was LONG_MAX, if greater dest was LONG_MIN. 2043 // If equal then dest was LONG_MAX, if greater dest was LONG_MIN.
2386 b(ge, not_int32); 2044 bt(not_int32);
2387 } else { 2045 } else {
2388 // This code is faster for doubles that are in the ranges -0x7fffffff to 2046 // This code is faster for doubles that are in the ranges -0x7fffffff to
2389 // -0x40000000 or 0x40000000 to 0x7fffffff. This corresponds almost to 2047 // -0x40000000 or 0x40000000 to 0x7fffffff. This corresponds almost to
2390 // the range of signed int32 values that are not Smis. Jumps to the label 2048 // the range of signed int32 values that are not Smis. Jumps to the label
2391 // 'not_int32' if the double isn't in the range -0x80000000.0 to 2049 // 'not_int32' if the double isn't in the range -0x80000000.0 to
2392 // 0x80000000.0 (excluding the endpoints). 2050 // 0x80000000.0 (excluding the endpoints).
2393 Label right_exponent, done; 2051 Label right_exponent, done;
2394 // Get exponent word. 2052 // Get exponent word.
2395 ldr(scratch, FieldMemOperand(source, HeapNumber::kExponentOffset)); 2053 ldr(scratch, FieldMemOperand(source, HeapNumber::kExponentOffset));
2396 // Get exponent alone in scratch2. 2054 // Get exponent alone in scratch2.
(...skipping 14 matching lines...) Expand all
2411 // for cmp because of the overflow flag, but we know the exponent is in the 2069 // for cmp because of the overflow flag, but we know the exponent is in the
2412 // range 0-2047 so there is no overflow. 2070 // range 0-2047 so there is no overflow.
2413 int fudge_factor = 0x400; 2071 int fudge_factor = 0x400;
2414 sub(scratch2, scratch2, Operand(fudge_factor)); 2072 sub(scratch2, scratch2, Operand(fudge_factor));
2415 cmp(scratch2, Operand(non_smi_exponent - fudge_factor)); 2073 cmp(scratch2, Operand(non_smi_exponent - fudge_factor));
2416 // If we have a match of the int32-but-not-Smi exponent then skip some 2074 // If we have a match of the int32-but-not-Smi exponent then skip some
2417 // logic. 2075 // logic.
2418 b(eq, &right_exponent); 2076 b(eq, &right_exponent);
2419 // If the exponent is higher than that then go to slow case. This catches 2077 // If the exponent is higher than that then go to slow case. This catches
2420 // numbers that don't fit in a signed int32, infinities and NaNs. 2078 // numbers that don't fit in a signed int32, infinities and NaNs.
2421 b(gt, not_int32); 2079 cmpgt(scratch2, Operand(non_smi_exponent - fudge_factor));
2080 bt(not_int32);
2422 2081
2423 // We know the exponent is smaller than 30 (biased). If it is less than 2082 // We know the exponent is smaller than 30 (biased). If it is less than
2424 // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, i.e. 2083 // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, i.e.
2425 // it rounds to zero. 2084 // it rounds to zero.
2426 const uint32_t zero_exponent = HeapNumber::kExponentBias + 0; 2085 const uint32_t zero_exponent = HeapNumber::kExponentBias + 0;
2427 sub(scratch2, scratch2, Operand(zero_exponent - fudge_factor), SetCC); 2086 cmpge(scratch2, Operand(zero_exponent - fudge_factor)); // for branch below
2087 sub(scratch2, scratch2, Operand(zero_exponent - fudge_factor));
2428 // Dest already has a Smi zero. 2088 // Dest already has a Smi zero.
2429 b(lt, &done); 2089 bf(&done);
2430 2090
2431 // We have an exponent between 0 and 30 in scratch2. Subtract from 30 to 2091 // We have an exponent between 0 and 30 in scratch2. Subtract from 30 to
2432 // get how much to shift down. 2092 // get how much to shift down.
2433 rsb(dest, scratch2, Operand(30)); 2093 rsb(dest, scratch2, Operand(30));
2434 2094
2435 bind(&right_exponent); 2095 bind(&right_exponent);
2436 // Get the top bits of the mantissa. 2096 // Get the top bits of the mantissa.
2437 and_(scratch2, scratch, Operand(HeapNumber::kMantissaMask)); 2097 land(scratch2, scratch, Operand(HeapNumber::kMantissaMask));
2438 // Put back the implicit 1. 2098 // Put back the implicit 1.
2439 orr(scratch2, scratch2, Operand(1 << HeapNumber::kExponentShift)); 2099 lor(scratch2, scratch2, Operand(1 << HeapNumber::kExponentShift));
2440 // Shift up the mantissa bits to take up the space the exponent used to 2100 // Shift up the mantissa bits to take up the space the exponent used to
2441 // take. We just orred in the implicit bit so that took care of one and 2101 // take. We just orred in the implicit bit so that took care of one and
2442 // we want to leave the sign bit 0 so we subtract 2 bits from the shift 2102 // we want to leave the sign bit 0 so we subtract 2 bits from the shift
2443 // distance. 2103 // distance.
2444 const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; 2104 const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2;
2445 mov(scratch2, Operand(scratch2, LSL, shift_distance)); 2105 lsl(scratch2, scratch2, Operand(shift_distance));
2446 // Put sign in zero flag. 2106 // Put sign in zero flag.
2447 tst(scratch, Operand(HeapNumber::kSignMask)); 2107 tst(scratch, Operand(HeapNumber::kSignMask));
2448 // Get the second half of the double. For some exponents we don't 2108 // Get the second half of the double. For some exponents we don't
2449 // actually need this because the bits get shifted out again, but 2109 // actually need this because the bits get shifted out again, but
2450 // it's probably slower to test than just to do it. 2110 // it's probably slower to test than just to do it.
2451 ldr(scratch, FieldMemOperand(source, HeapNumber::kMantissaOffset)); 2111 ldr(scratch, FieldMemOperand(source, HeapNumber::kMantissaOffset));
2452 // Shift down 22 bits to get the last 10 bits. 2112 // Shift down 22 bits to get the last 10 bits.
2453 orr(scratch, scratch2, Operand(scratch, LSR, 32 - shift_distance)); 2113 lsr(scratch, scratch, Operand(32 - shift_distance));
2114 lor(scratch, scratch2, scratch);
2454 // Move down according to the exponent. 2115 // Move down according to the exponent.
2455 mov(dest, Operand(scratch, LSR, dest)); 2116 lsr(dest, scratch, dest);
2456 // Fix sign if sign bit was set. 2117 // Fix sign if sign bit was set.
2457 rsb(dest, dest, Operand(0, RelocInfo::NONE), LeaveCC, ne); 2118 rsb(dest, dest, Operand(0, RelocInfo::NONE), ne);
2458 bind(&done); 2119 bind(&done);
2459 } 2120 }
2460 } 2121 }
2461 2122
2462 2123
2463 void MacroAssembler::EmitVFPTruncate(VFPRoundingMode rounding_mode, 2124 void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode,
2464 Register result, 2125 Register result,
2465 DwVfpRegister double_input, 2126 DwVfpRegister double_input,
2466 Register scratch, 2127 Register scratch,
2467 DwVfpRegister double_scratch,
2468 CheckForInexactConversion check_inexact) { 2128 CheckForInexactConversion check_inexact) {
2469 ASSERT(!result.is(scratch)); 2129 ASSERT(rounding_mode == kRoundToZero);
2470 ASSERT(!double_input.is(double_scratch)); 2130 int32_t check_inexact_conversion =
2131 (check_inexact == kCheckForInexactConversion) ? kFPUInexactExceptionBit : 0;
2471 2132
2472 ASSERT(CpuFeatures::IsSupported(VFP2)); 2133 idouble(result, double_input, scratch);
2473 CpuFeatures::Scope scope(VFP2);
2474 Register prev_fpscr = result;
2475 Label done;
2476 2134
2477 // Test for values that can be exactly represented as a signed 32-bit integer. 2135 // Check for FPU exceptions
2478 vcvt_s32_f64(double_scratch.low(), double_input); 2136 tst(scratch, Operand(kFPUExceptionMask | check_inexact_conversion));
2479 vmov(result, double_scratch.low());
2480 vcvt_f64_s32(double_scratch, double_scratch.low());
2481 VFPCompareAndSetFlags(double_input, double_scratch);
2482 b(eq, &done);
2483
2484 // Convert to integer, respecting rounding mode.
2485 int32_t check_inexact_conversion =
2486 (check_inexact == kCheckForInexactConversion) ? kVFPInexactExceptionBit : 0;
2487
2488 // Set custom FPCSR:
2489 // - Set rounding mode.
2490 // - Clear vfp cumulative exception flags.
2491 // - Make sure Flush-to-zero mode control bit is unset.
2492 vmrs(prev_fpscr);
2493 bic(scratch,
2494 prev_fpscr,
2495 Operand(kVFPExceptionMask |
2496 check_inexact_conversion |
2497 kVFPRoundingModeMask |
2498 kVFPFlushToZeroMask));
2499 // 'Round To Nearest' is encoded by 0b00 so no bits need to be set.
2500 if (rounding_mode != kRoundToNearest) {
2501 orr(scratch, scratch, Operand(rounding_mode));
2502 }
2503 vmsr(scratch);
2504
2505 // Convert the argument to an integer.
2506 vcvt_s32_f64(double_scratch.low(),
2507 double_input,
2508 (rounding_mode == kRoundToZero) ? kDefaultRoundToZero
2509 : kFPSCRRounding);
2510
2511 // Retrieve FPSCR.
2512 vmrs(scratch);
2513 // Restore FPSCR.
2514 vmsr(prev_fpscr);
2515 // Move the converted value into the result register.
2516 vmov(result, double_scratch.low());
2517 // Check for vfp exceptions.
2518 tst(scratch, Operand(kVFPExceptionMask | check_inexact_conversion));
2519
2520 bind(&done);
2521 } 2137 }
2522 2138
2523 2139
2524 void MacroAssembler::EmitOutOfInt32RangeTruncate(Register result, 2140 void MacroAssembler::EmitOutOfInt32RangeTruncate(Register result,
2525 Register input_high, 2141 Register input_high,
2526 Register input_low, 2142 Register input_low,
2527 Register scratch) { 2143 Register scratch) {
2528 Label done, normal_exponent, restore_sign; 2144 Label done, normal_exponent, restore_sign;
2529 2145
2530 // Extract the biased exponent in result. 2146 // Extract the biased exponent in result.
2531 Ubfx(result, 2147 Ubfx(result,
2532 input_high, 2148 input_high,
2533 HeapNumber::kExponentShift, 2149 HeapNumber::kExponentShift,
2534 HeapNumber::kExponentBits); 2150 HeapNumber::kExponentBits);
2535 2151
2536 // Check for Infinity and NaNs, which should return 0. 2152 // Check for Infinity and NaNs, which should return 0.
2537 cmp(result, Operand(HeapNumber::kExponentMask)); 2153 cmp(result, Operand(HeapNumber::kExponentMask));
2538 mov(result, Operand(0), LeaveCC, eq); 2154 mov(result, Operand(0), eq);
2539 b(eq, &done); 2155 b(eq, &done);
2540 2156
2541 // Express exponent as delta to (number of mantissa bits + 31). 2157 // Express exponent as delta to (number of mantissa bits + 31).
2542 sub(result, 2158 sub(result,
2543 result, 2159 result,
2544 Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits + 31), 2160 Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits + 31));
2545 SetCC); 2161 cmpgt(result, Operand(0));
2546 2162
2547 // If the delta is strictly positive, all bits would be shifted away, 2163 // If the delta is strictly positive, all bits would be shifted away,
2548 // which means that we can return 0. 2164 // which means that we can return 0.
2549 b(le, &normal_exponent); 2165 b(f, &normal_exponent);
2550 mov(result, Operand(0)); 2166 mov(result, Operand(0));
2551 b(&done); 2167 b(&done);
2552 2168
2553 bind(&normal_exponent); 2169 bind(&normal_exponent);
2554 const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1; 2170 const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1;
2555 // Calculate shift. 2171 // Calculate shift.
2556 add(scratch, result, Operand(kShiftBase + HeapNumber::kMantissaBits), SetCC); 2172 add(scratch, result, Operand(kShiftBase + HeapNumber::kMantissaBits));
2557 2173
2558 // Save the sign. 2174 // Save the sign.
2559 Register sign = result; 2175 Register sign = result;
2560 result = no_reg; 2176 result = no_reg;
2561 and_(sign, input_high, Operand(HeapNumber::kSignMask)); 2177 land(sign, input_high, Operand(HeapNumber::kSignMask));
2562 2178
2563 // Set the implicit 1 before the mantissa part in input_high. 2179 // Set the implicit 1 before the mantissa part in input_high.
2564 orr(input_high, 2180 orr(input_high,
2565 input_high, 2181 input_high,
2566 Operand(1 << HeapNumber::kMantissaBitsInTopWord)); 2182 Operand(1 << HeapNumber::kMantissaBitsInTopWord));
2567 // Shift the mantissa bits to the correct position. 2183 // Shift the mantissa bits to the correct position.
2568 // We don't need to clear non-mantissa bits as they will be shifted away. 2184 // We don't need to clear non-mantissa bits as they will be shifted away.
2569 // If they weren't, it would mean that the answer is in the 32bit range. 2185 // If they weren't, it would mean that the answer is in the 32bit range.
2570 mov(input_high, Operand(input_high, LSL, scratch)); 2186 lsl(input_high, input_high, scratch);
2571 2187
2572 // Replace the shifted bits with bits from the lower mantissa word. 2188 // Replace the shifted bits with bits from the lower mantissa word.
2573 Label pos_shift, shift_done; 2189 Label pos_shift, shift_done;
2574 rsb(scratch, scratch, Operand(32), SetCC); 2190 rsb(scratch, scratch, Operand(32));
2575 b(&pos_shift, ge); 2191 cmpge(scratch, Operand(0));
2192 bt(&pos_shift);
2576 2193
2577 // Negate scratch. 2194 // Negate scratch.
2578 rsb(scratch, scratch, Operand(0)); 2195 rsb(scratch, scratch, Operand(0));
2579 mov(input_low, Operand(input_low, LSL, scratch)); 2196 lsl(input_low, input_low, scratch);
2580 b(&shift_done); 2197 b(&shift_done);
2581 2198
2582 bind(&pos_shift); 2199 bind(&pos_shift);
2583 mov(input_low, Operand(input_low, LSR, scratch)); 2200 lsr(input_low, input_low, scratch);
2584 2201
2585 bind(&shift_done); 2202 bind(&shift_done);
2586 orr(input_high, input_high, Operand(input_low)); 2203 orr(input_high, input_high, input_low);
2587 // Restore sign if necessary. 2204 // Restore sign if necessary.
2588 cmp(sign, Operand(0)); 2205 cmp(sign, Operand(0));
2589 result = sign; 2206 result = sign;
2590 sign = no_reg; 2207 sign = no_reg;
2591 rsb(result, input_high, Operand(0), LeaveCC, ne); 2208 rsb(result, input_high, Operand(0));
2592 mov(result, input_high, LeaveCC, eq); 2209 mov(result, input_high, eq);
2593 bind(&done); 2210 bind(&done);
2594 } 2211 }
2595 2212
2596 2213
2597 void MacroAssembler::EmitECMATruncate(Register result, 2214 void MacroAssembler::EmitECMATruncate(Register result,
2598 DwVfpRegister double_input, 2215 DwVfpRegister double_input,
2599 SwVfpRegister single_scratch, 2216 SwVfpRegister single_scratch,
2600 Register scratch, 2217 Register scratch,
2601 Register input_high, 2218 Register input_high,
2602 Register input_low) { 2219 Register input_low) {
2603 CpuFeatures::Scope scope(VFP2); 2220 ASSERT(CpuFeatures::IsSupported(FPU));
2604 ASSERT(!input_high.is(result)); 2221 ASSERT(!input_high.is(result));
2605 ASSERT(!input_low.is(result)); 2222 ASSERT(!input_low.is(result));
2606 ASSERT(!input_low.is(input_high)); 2223 ASSERT(!input_low.is(input_high));
2607 ASSERT(!scratch.is(result) && 2224 ASSERT(!scratch.is(result) &&
2608 !scratch.is(input_high) && 2225 !scratch.is(input_high) &&
2609 !scratch.is(input_low)); 2226 !scratch.is(input_low));
2610 ASSERT(!single_scratch.is(double_input.low()) && 2227 ASSERT(!single_scratch.is(double_input.low()) &&
2611 !single_scratch.is(double_input.high())); 2228 !single_scratch.is(double_input.high()));
2612 2229
2613 Label done; 2230 Label done;
2614 2231
2615 // Clear cumulative exception flags. 2232 // Do the conversion
2616 ClearFPSCRBits(kVFPExceptionMask, scratch); 2233 idouble(result, double_input);
2617 // Try a conversion to a signed integer. 2234 // Retrieve the FPSCR.
2618 vcvt_s32_f64(single_scratch, double_input); 2235 str_fpscr(scratch);
2619 vmov(result, single_scratch);
2620 // Retrieve he FPSCR.
2621 vmrs(scratch);
2622 // Check for overflow and NaNs. 2236 // Check for overflow and NaNs.
2623 tst(scratch, Operand(kVFPOverflowExceptionBit | 2237 tst(scratch, Operand(kFPUOverflowExceptionBit |
2624 kVFPUnderflowExceptionBit | 2238 kFPUUnderflowExceptionBit |
2625 kVFPInvalidOpExceptionBit)); 2239 kFPUInvalidExceptionBit |
2240 kFPUInexactExceptionBit));
2626 // If we had no exceptions we are done. 2241 // If we had no exceptions we are done.
2627 b(eq, &done); 2242 b(eq, &done);
2628 2243
2629 // Load the double value and perform a manual truncation. 2244 // Load the double value and perform a manual truncation.
2630 vmov(input_low, input_high, double_input); 2245 movd(input_low, input_high, double_input);
2631 EmitOutOfInt32RangeTruncate(result, 2246 EmitOutOfInt32RangeTruncate(result,
2632 input_high, 2247 input_high,
2633 input_low, 2248 input_low,
2634 scratch); 2249 scratch);
2635 bind(&done); 2250 bind(&done);
2636 } 2251 }
2637 2252
2638 2253
2639 void MacroAssembler::GetLeastBitsFromSmi(Register dst, 2254 void MacroAssembler::GetLeastBitsFromSmi(Register dst,
2640 Register src, 2255 Register src,
2641 int num_least_bits) { 2256 int num_least_bits) {
2642 if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size()) { 2257 Ubfx(dst, src, kSmiTagSize, num_least_bits);
2643 ubfx(dst, src, kSmiTagSize, num_least_bits);
2644 } else {
2645 mov(dst, Operand(src, ASR, kSmiTagSize));
2646 and_(dst, dst, Operand((1 << num_least_bits) - 1));
2647 }
2648 } 2258 }
2649 2259
2650 2260
2651 void MacroAssembler::GetLeastBitsFromInt32(Register dst, 2261 void MacroAssembler::GetLeastBitsFromInt32(Register dst,
2652 Register src, 2262 Register src,
2653 int num_least_bits) { 2263 int num_least_bits) {
2654 and_(dst, src, Operand((1 << num_least_bits) - 1)); 2264 ASSERT(!dst.is(sh4_rtmp) && !src.is(sh4_rtmp));
2265 land(dst, src, Operand((1 << num_least_bits) - 1));
2655 } 2266 }
2656 2267
2657 2268
2658 void MacroAssembler::CallRuntime(const Runtime::Function* f, 2269 void MacroAssembler::CallRuntime(const Runtime::Function* f,
2659 int num_arguments) { 2270 int num_arguments) {
2271 // No register conventions on entry.
2660 // All parameters are on the stack. r0 has the return value after call. 2272 // All parameters are on the stack. r0 has the return value after call.
2273 #ifdef DEBUG
2274 // Clobber parameter registers on entry.
2275 Dead(r0, r1, r2, r3);
2276 Dead(r4, r5, r6, r7);
2277 #endif
2661 2278
2662 // If the expected number of arguments of the runtime function is 2279 // If the expected number of arguments of the runtime function is
2663 // constant, we check that the actual number of arguments match the 2280 // constant, we check that the actual number of arguments match the
2664 // expectation. 2281 // expectation.
2282 RECORD_LINE();
2665 if (f->nargs >= 0 && f->nargs != num_arguments) { 2283 if (f->nargs >= 0 && f->nargs != num_arguments) {
2666 IllegalOperation(num_arguments); 2284 IllegalOperation(num_arguments);
2667 return; 2285 return;
2668 } 2286 }
2669 2287
2670 // TODO(1236192): Most runtime routines don't need the number of 2288 // TODO(1236192): Most runtime routines don't need the number of
2671 // arguments passed in because it is constant. At some point we 2289 // arguments passed in because it is constant. At some point we
2672 // should remove this need and make the runtime routine entry code 2290 // should remove this need and make the runtime routine entry code
2673 // smarter. 2291 // smarter.
2674 mov(r0, Operand(num_arguments)); 2292 mov(r0, Operand(num_arguments));
2675 mov(r1, Operand(ExternalReference(f, isolate()))); 2293 mov(r1, Operand(ExternalReference(f, isolate())));
2676 CEntryStub stub(1); 2294 CEntryStub stub(1);
2677 CallStub(&stub); 2295 CallStub(&stub);
2678 } 2296 }
2679 2297
2680 2298
2681 void MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) { 2299 void MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) {
2300 RECORD_LINE();
2682 CallRuntime(Runtime::FunctionForId(fid), num_arguments); 2301 CallRuntime(Runtime::FunctionForId(fid), num_arguments);
2683 } 2302 }
2684 2303
2685 2304
2686 void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) {
2687 const Runtime::Function* function = Runtime::FunctionForId(id);
2688 mov(r0, Operand(function->nargs));
2689 mov(r1, Operand(ExternalReference(function, isolate())));
2690 CEntryStub stub(1, kSaveFPRegs);
2691 CallStub(&stub);
2692 }
2693
2694
2695 void MacroAssembler::CallExternalReference(const ExternalReference& ext, 2305 void MacroAssembler::CallExternalReference(const ExternalReference& ext,
2696 int num_arguments) { 2306 int num_arguments) {
2697 mov(r0, Operand(num_arguments)); 2307 mov(r0, Operand(num_arguments));
2698 mov(r1, Operand(ext)); 2308 mov(r1, Operand(ext));
2699 2309
2700 CEntryStub stub(1); 2310 CEntryStub stub(1);
2701 CallStub(&stub); 2311 CallStub(&stub);
2702 } 2312 }
2703 2313
2704 2314
2705 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext, 2315 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
2706 int num_arguments, 2316 int num_arguments,
2707 int result_size) { 2317 int result_size) {
2708 // TODO(1236192): Most runtime routines don't need the number of 2318 // TODO(1236192): Most runtime routines don't need the number of
2709 // arguments passed in because it is constant. At some point we 2319 // arguments passed in because it is constant. At some point we
2710 // should remove this need and make the runtime routine entry code 2320 // should remove this need and make the runtime routine entry code
2711 // smarter. 2321 // smarter.
2322 RECORD_LINE();
2712 mov(r0, Operand(num_arguments)); 2323 mov(r0, Operand(num_arguments));
2713 JumpToExternalReference(ext); 2324 JumpToExternalReference(ext);
2714 } 2325 }
2715 2326
2716 2327
2717 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, 2328 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
2718 int num_arguments, 2329 int num_arguments,
2719 int result_size) { 2330 int result_size) {
2331 RECORD_LINE();
2720 TailCallExternalReference(ExternalReference(fid, isolate()), 2332 TailCallExternalReference(ExternalReference(fid, isolate()),
2721 num_arguments, 2333 num_arguments,
2722 result_size); 2334 result_size);
2723 } 2335 }
2724 2336
2725 2337
2726 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin) { 2338 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin) {
2727 #if defined(__thumb__) 2339 RECORD_LINE();
2728 // Thumb mode builtin.
2729 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1);
2730 #endif
2731 mov(r1, Operand(builtin)); 2340 mov(r1, Operand(builtin));
2732 CEntryStub stub(1); 2341 CEntryStub stub(1);
2733 Jump(stub.GetCode(), RelocInfo::CODE_TARGET); 2342 RECORD_LINE();
2343 jmp(stub.GetCode(), RelocInfo::CODE_TARGET);
2734 } 2344 }
2735 2345
2736 2346
2737 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, 2347 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
2738 InvokeFlag flag, 2348 InvokeFlag flag,
2739 const CallWrapper& call_wrapper) { 2349 const CallWrapper& call_wrapper) {
2740 // You can't call a builtin without a valid frame. 2350 // You can't call a builtin without a valid frame.
2741 ASSERT(flag == JUMP_FUNCTION || has_frame()); 2351 ASSERT(flag == JUMP_FUNCTION || has_frame());
2742 2352
2353 // No register conventions on entry.
2354 // All parameters are on stack.
2355 // Return value in r0 after call.
2356 #ifdef DEBUG
2357 // Clobber parameter registers on entry.
2358 Dead(r0, r1, r2, r3);
2359 Dead(r4, r5, r6, r7);
2360 #endif
2361
2362 RECORD_LINE();
2743 GetBuiltinEntry(r2, id); 2363 GetBuiltinEntry(r2, id);
2744 if (flag == CALL_FUNCTION) { 2364 if (flag == CALL_FUNCTION) {
2745 call_wrapper.BeforeCall(CallSize(r2)); 2365 RECORD_LINE();
2366 call_wrapper.BeforeCall(2 * kInstrSize);
2746 SetCallKind(r5, CALL_AS_METHOD); 2367 SetCallKind(r5, CALL_AS_METHOD);
2747 Call(r2); 2368 jsr(r2);
2748 call_wrapper.AfterCall(); 2369 call_wrapper.AfterCall();
2749 } else { 2370 } else {
2750 ASSERT(flag == JUMP_FUNCTION); 2371 ASSERT(flag == JUMP_FUNCTION);
2372 RECORD_LINE();
2751 SetCallKind(r5, CALL_AS_METHOD); 2373 SetCallKind(r5, CALL_AS_METHOD);
2752 Jump(r2); 2374 jmp(r2);
2753 } 2375 }
2754 } 2376 }
2755 2377
2756 2378
2757 void MacroAssembler::GetBuiltinFunction(Register target, 2379 void MacroAssembler::GetBuiltinFunction(Register target,
2758 Builtins::JavaScript id) { 2380 Builtins::JavaScript id) {
2381 ASSERT(!target.is(sh4_ip));
2382 ASSERT(!target.is(sh4_rtmp));
2383 RECORD_LINE();
2759 // Load the builtins object into target register. 2384 // Load the builtins object into target register.
2760 ldr(target, 2385 ldr(target,
2761 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 2386 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
2762 ldr(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset)); 2387 ldr(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset));
2763 // Load the JavaScript builtin function from the builtins object. 2388 // Load the JavaScript builtin function from the builtins object.
2764 ldr(target, FieldMemOperand(target, 2389 ldr(target, FieldMemOperand(target,
2765 JSBuiltinsObject::OffsetOfFunctionWithId(id))); 2390 JSBuiltinsObject::OffsetOfFunctionWithId(id)));
2766 } 2391 }
2767 2392
2768 2393
2769 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { 2394 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
2395 // FIXME(stm): why r1 ??
2770 ASSERT(!target.is(r1)); 2396 ASSERT(!target.is(r1));
2397 ASSERT(!target.is(sh4_rtmp));
2398 ASSERT(!target.is(sh4_ip));
2399 RECORD_LINE();
2771 GetBuiltinFunction(r1, id); 2400 GetBuiltinFunction(r1, id);
2401 RECORD_LINE();
2772 // Load the code entry point from the builtins object. 2402 // Load the code entry point from the builtins object.
2773 ldr(target, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); 2403 ldr(target, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
2774 } 2404 }
2775 2405
2776 2406
2777 void MacroAssembler::SetCounter(StatsCounter* counter, int value, 2407 void MacroAssembler::SetCounter(StatsCounter* counter, int value,
2778 Register scratch1, Register scratch2) { 2408 Register scratch1, Register scratch2) {
2409 RECORD_LINE();
2410 ASSERT(!scratch1.is(scratch2));
2411 ASSERT(!scratch1.is(sh4_rtmp) && !scratch2.is(sh4_rtmp));
2412 ASSERT(!scratch1.is(sh4_ip) && !scratch2.is(sh4_ip));
2779 if (FLAG_native_code_counters && counter->Enabled()) { 2413 if (FLAG_native_code_counters && counter->Enabled()) {
2414 RECORD_LINE();
2780 mov(scratch1, Operand(value)); 2415 mov(scratch1, Operand(value));
2781 mov(scratch2, Operand(ExternalReference(counter))); 2416 mov(scratch2, Operand(ExternalReference(counter)));
2782 str(scratch1, MemOperand(scratch2)); 2417 str(scratch1, MemOperand(scratch2));
2783 } 2418 }
2784 } 2419 }
2785 2420
2786 2421
2787 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value, 2422 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
2788 Register scratch1, Register scratch2) { 2423 Register scratch1, Register scratch2) {
2789 ASSERT(value > 0); 2424 ASSERT(value > 0);
2425 ASSERT(!scratch1.is(scratch2));
2426 ASSERT(!scratch1.is(sh4_rtmp) && !scratch2.is(sh4_rtmp));
2427 ASSERT(!scratch1.is(sh4_ip) && !scratch2.is(sh4_ip));
2428 RECORD_LINE();
2790 if (FLAG_native_code_counters && counter->Enabled()) { 2429 if (FLAG_native_code_counters && counter->Enabled()) {
2430 RECORD_LINE();
2791 mov(scratch2, Operand(ExternalReference(counter))); 2431 mov(scratch2, Operand(ExternalReference(counter)));
2792 ldr(scratch1, MemOperand(scratch2)); 2432 ldr(scratch1, MemOperand(scratch2));
2793 add(scratch1, scratch1, Operand(value)); 2433 add(scratch1, scratch1, Operand(value));
2794 str(scratch1, MemOperand(scratch2)); 2434 str(scratch1, MemOperand(scratch2));
2795 } 2435 }
2796 } 2436 }
2797 2437
2798 2438
2799 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value, 2439 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
2800 Register scratch1, Register scratch2) { 2440 Register scratch1, Register scratch2) {
2801 ASSERT(value > 0); 2441 ASSERT(value > 0);
2442 ASSERT(!scratch1.is(scratch2));
2443 ASSERT(!scratch1.is(sh4_rtmp) && !scratch2.is(sh4_rtmp));
2444 ASSERT(!scratch1.is(sh4_ip) && !scratch2.is(sh4_ip));
2445
2446 RECORD_LINE();
2802 if (FLAG_native_code_counters && counter->Enabled()) { 2447 if (FLAG_native_code_counters && counter->Enabled()) {
2448 RECORD_LINE();
2803 mov(scratch2, Operand(ExternalReference(counter))); 2449 mov(scratch2, Operand(ExternalReference(counter)));
2804 ldr(scratch1, MemOperand(scratch2)); 2450 ldr(scratch1, MemOperand(scratch2));
2805 sub(scratch1, scratch1, Operand(value)); 2451 sub(scratch1, scratch1, Operand(value));
2806 str(scratch1, MemOperand(scratch2)); 2452 str(scratch1, MemOperand(scratch2));
2807 } 2453 }
2808 } 2454 }
2809 2455
2810 2456
2811 void MacroAssembler::Assert(Condition cond, const char* msg) { 2457 void MacroAssembler::Assert(Condition cond, const char* msg) {
2812 if (emit_debug_code()) 2458 if (emit_debug_code())
2813 Check(cond, msg); 2459 Check(cond, msg);
2814 } 2460 }
2815 2461
2816 2462
2817 void MacroAssembler::AssertRegisterIsRoot(Register reg, 2463 void MacroAssembler::AssertRegisterIsRoot(Register reg, Register scratch,
2818 Heap::RootListIndex index) { 2464 Heap::RootListIndex index) {
2465 // TODO(STM): scratch need or ip ok ?
2466 ASSERT(!reg.is(scratch));
2819 if (emit_debug_code()) { 2467 if (emit_debug_code()) {
2820 LoadRoot(ip, index); 2468 LoadRoot(scratch, index);
2821 cmp(reg, ip); 2469 cmp(reg, scratch);
2822 Check(eq, "Register did not match expected root"); 2470 Check(eq, "Register did not match expected root");
2823 } 2471 }
2824 } 2472 }
2825 2473
2826 2474
2827 void MacroAssembler::AssertFastElements(Register elements) { 2475 void MacroAssembler::AssertFastElements(Register elements) {
2476 RECORD_LINE();
2828 if (emit_debug_code()) { 2477 if (emit_debug_code()) {
2829 ASSERT(!elements.is(ip)); 2478 ASSERT(!elements.is(sh4_rtmp));
2479 ASSERT(!elements.is(sh4_ip));
2830 Label ok; 2480 Label ok;
2481 RECORD_LINE();
2831 push(elements); 2482 push(elements);
2832 ldr(elements, FieldMemOperand(elements, HeapObject::kMapOffset)); 2483 ldr(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
2833 LoadRoot(ip, Heap::kFixedArrayMapRootIndex); 2484 LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
2834 cmp(elements, ip); 2485 cmp(elements, ip);
2835 b(eq, &ok); 2486 b(eq, &ok);
2487 RECORD_LINE();
2836 LoadRoot(ip, Heap::kFixedDoubleArrayMapRootIndex); 2488 LoadRoot(ip, Heap::kFixedDoubleArrayMapRootIndex);
2837 cmp(elements, ip); 2489 cmp(elements, ip);
2838 b(eq, &ok); 2490 b(eq, &ok);
2491 RECORD_LINE();
2839 LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); 2492 LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
2840 cmp(elements, ip); 2493 cmp(elements, ip);
2841 b(eq, &ok); 2494 b(eq, &ok);
2495 RECORD_LINE();
2842 Abort("JSObject with fast elements map has slow elements"); 2496 Abort("JSObject with fast elements map has slow elements");
2843 bind(&ok); 2497 bind(&ok);
2498 RECORD_LINE();
2844 pop(elements); 2499 pop(elements);
2845 } 2500 }
2846 } 2501 }
2847 2502
2848 2503
2849 void MacroAssembler::Check(Condition cond, const char* msg) { 2504 void MacroAssembler::Check(Condition cond, const char* msg) {
2850 Label L; 2505 Label L;
2506 RECORD_LINE();
2851 b(cond, &L); 2507 b(cond, &L);
2852 Abort(msg); 2508 Abort(msg);
2853 // will not return here 2509 // will not return here
2854 bind(&L); 2510 bind(&L);
2855 } 2511 }
2856 2512
2513 void MacroAssembler::DebugPrint(Register obj) {
2514 RECORD_LINE();
2515 push(obj);
2516 CallRuntime(Runtime::kDebugPrint, 1);
2517 }
2857 2518
2858 void MacroAssembler::Abort(const char* msg) { 2519 void MacroAssembler::Abort(const char* msg) {
2859 Label abort_start; 2520 Label abort_start;
2860 bind(&abort_start); 2521 bind(&abort_start);
2522 RECORD_LINE();
2861 // We want to pass the msg string like a smi to avoid GC 2523 // We want to pass the msg string like a smi to avoid GC
2862 // problems, however msg is not guaranteed to be aligned 2524 // problems, however msg is not guaranteed to be aligned
2863 // properly. Instead, we pass an aligned pointer that is 2525 // properly. Instead, we pass an aligned pointer that is
2864 // a proper v8 smi, but also pass the alignment difference 2526 // a proper v8 smi, but also pass the alignment difference
2865 // from the real pointer as a smi. 2527 // from the real pointer as a smi.
2866 intptr_t p1 = reinterpret_cast<intptr_t>(msg); 2528 intptr_t p1 = reinterpret_cast<intptr_t>(msg);
2867 intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag; 2529 intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
2868 ASSERT(reinterpret_cast<Object*>(p0)->IsSmi()); 2530 ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());
2869 #ifdef DEBUG 2531 #ifdef DEBUG
2870 if (msg != NULL) { 2532 if (msg != NULL) {
2871 RecordComment("Abort message: "); 2533 RecordComment("Abort message: ");
2872 RecordComment(msg); 2534 RecordComment(msg);
2873 } 2535 }
2874 #endif 2536 #endif
2875
2876 mov(r0, Operand(p0)); 2537 mov(r0, Operand(p0));
2877 push(r0); 2538 push(r0);
2878 mov(r0, Operand(Smi::FromInt(p1 - p0))); 2539 mov(r0, Operand(Smi::FromInt(p1 - p0)));
2879 push(r0); 2540 push(r0);
2880 // Disable stub call restrictions to always allow calls to abort. 2541 // Disable stub call restrictions to always allow calls to abort.
2881 if (!has_frame_) { 2542 if (!has_frame_) {
2882 // We don't actually want to generate a pile of code for this, so just 2543 // We don't actually want to generate a pile of code for this, so just
2883 // claim there is a stack frame, without generating one. 2544 // claim there is a stack frame, without generating one.
2884 FrameScope scope(this, StackFrame::NONE); 2545 FrameScope scope(this, StackFrame::NONE);
2885 CallRuntime(Runtime::kAbort, 2); 2546 CallRuntime(Runtime::kAbort, 2);
2886 } else { 2547 } else {
2887 CallRuntime(Runtime::kAbort, 2); 2548 CallRuntime(Runtime::kAbort, 2);
2888 } 2549 }
2889 // will not return here 2550 // will not return here
2890 if (is_const_pool_blocked()) { 2551 // TODO(STM): implement this when const pool manager is active
2891 // If the calling code cares about the exact number of 2552 // if (is_const_pool_blocked()) {
2892 // instructions generated, we insert padding here to keep the size 2553 // }
2893 // of the Abort macro constant.
2894 static const int kExpectedAbortInstructions = 10;
2895 int abort_instructions = InstructionsGeneratedSince(&abort_start);
2896 ASSERT(abort_instructions <= kExpectedAbortInstructions);
2897 while (abort_instructions++ < kExpectedAbortInstructions) {
2898 nop();
2899 }
2900 }
2901 } 2554 }
2902 2555
2903 2556
2557 // Clobbers: sh4_rtmp, dst
2558 // live-in: cp
2559 // live-out: cp, dst
2904 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { 2560 void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
2561 ASSERT(!dst.is(sh4_rtmp));
2562 RECORD_LINE();
2905 if (context_chain_length > 0) { 2563 if (context_chain_length > 0) {
2564 RECORD_LINE();
2906 // Move up the chain of contexts to the context containing the slot. 2565 // Move up the chain of contexts to the context containing the slot.
2907 ldr(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX))); 2566 ldr(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2908 for (int i = 1; i < context_chain_length; i++) { 2567 for (int i = 1; i < context_chain_length; i++) {
2568 RECORD_LINE();
2909 ldr(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX))); 2569 ldr(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2910 } 2570 }
2911 } else { 2571 } else {
2572 RECORD_LINE();
2912 // Slot is in the current function context. Move it into the 2573 // Slot is in the current function context. Move it into the
2913 // destination register in case we store into it (the write barrier 2574 // destination register in case we store into it (the write barrier
2914 // cannot be allowed to destroy the context in esi). 2575 // cannot be allowed to destroy the context in esi).
2915 mov(dst, cp); 2576 mov(dst, cp);
2916 } 2577 }
2917 } 2578 }
2918 2579
2919 2580
2920 void MacroAssembler::LoadTransitionedArrayMapConditional( 2581 void MacroAssembler::LoadTransitionedArrayMapConditional(
2921 ElementsKind expected_kind, 2582 ElementsKind expected_kind,
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2978 ldr(function, FieldMemOperand(function, 2639 ldr(function, FieldMemOperand(function,
2979 GlobalObject::kNativeContextOffset)); 2640 GlobalObject::kNativeContextOffset));
2980 // Load the function from the native context. 2641 // Load the function from the native context.
2981 ldr(function, MemOperand(function, Context::SlotOffset(index))); 2642 ldr(function, MemOperand(function, Context::SlotOffset(index)));
2982 } 2643 }
2983 2644
2984 2645
2985 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, 2646 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
2986 Register map, 2647 Register map,
2987 Register scratch) { 2648 Register scratch) {
2649 ASSERT(!scratch.is(sh4_ip));
2650 ASSERT(!scratch.is(sh4_rtmp));
2988 // Load the initial map. The global functions all have initial maps. 2651 // Load the initial map. The global functions all have initial maps.
2989 ldr(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 2652 ldr(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2990 if (emit_debug_code()) { 2653 if (emit_debug_code()) {
2991 Label ok, fail; 2654 Label ok;
2655 Label fail;
2992 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK); 2656 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
2993 b(&ok); 2657 b_near(&ok);
2994 bind(&fail); 2658 bind(&fail);
2995 Abort("Global functions must have initial map"); 2659 Abort("Global functions must have initial map");
2996 bind(&ok); 2660 bind(&ok);
2997 } 2661 }
2998 } 2662 }
2999 2663
3000 2664
3001 void MacroAssembler::JumpIfNotPowerOfTwoOrZero( 2665 void MacroAssembler::JumpIfNotPowerOfTwoOrZero(
3002 Register reg, 2666 Register reg,
3003 Register scratch, 2667 Register scratch,
3004 Label* not_power_of_two_or_zero) { 2668 Label* not_power_of_two_or_zero) {
3005 sub(scratch, reg, Operand(1), SetCC); 2669 ASSERT(!reg.is(sh4_rtmp) && !scratch.is(sh4_rtmp));
3006 b(mi, not_power_of_two_or_zero); 2670 RECORD_LINE();
2671 // Note: actually the case 0x80000000 is considered a power of two
2672 // (not a neg value)
2673 sub(scratch, reg, Operand(1));
2674 cmpge(scratch, Operand(0));
2675 bf(not_power_of_two_or_zero);
3007 tst(scratch, reg); 2676 tst(scratch, reg);
3008 b(ne, not_power_of_two_or_zero); 2677 b(ne, not_power_of_two_or_zero);
3009 } 2678 }
3010 2679
3011 2680
3012 void MacroAssembler::JumpIfNotPowerOfTwoOrZeroAndNeg( 2681 void MacroAssembler::JumpIfNotPowerOfTwoOrZeroAndNeg(
3013 Register reg, 2682 Register reg,
3014 Register scratch, 2683 Register scratch,
3015 Label* zero_and_neg, 2684 Label* zero_and_neg,
3016 Label* not_power_of_two) { 2685 Label* not_power_of_two) {
3017 sub(scratch, reg, Operand(1), SetCC); 2686 ASSERT(!reg.is(sh4_rtmp) && !scratch.is(sh4_rtmp));
3018 b(mi, zero_and_neg); 2687 RECORD_LINE();
2688 // Note: actually the case 0x80000000 is considered a pozer of two
2689 // (not a neg value)
2690 sub(scratch, reg, Operand(1));
2691 cmpge(scratch, Operand(0));
2692 bf(zero_and_neg);
3019 tst(scratch, reg); 2693 tst(scratch, reg);
3020 b(ne, not_power_of_two); 2694 b(ne, not_power_of_two);
3021 } 2695 }
3022 2696
3023 2697
3024 void MacroAssembler::JumpIfNotBothSmi(Register reg1, 2698 void MacroAssembler::JumpIfNotBothSmi(Register reg1,
3025 Register reg2, 2699 Register reg2,
3026 Label* on_not_both_smi) { 2700 Label* on_not_both_smi,
2701 Label::Distance distance) {
2702 ASSERT(!reg1.is(sh4_rtmp) && !reg2.is(sh4_rtmp));
3027 STATIC_ASSERT(kSmiTag == 0); 2703 STATIC_ASSERT(kSmiTag == 0);
2704 RECORD_LINE();
3028 tst(reg1, Operand(kSmiTagMask)); 2705 tst(reg1, Operand(kSmiTagMask));
3029 tst(reg2, Operand(kSmiTagMask), eq); 2706 b(ne, on_not_both_smi, distance);
3030 b(ne, on_not_both_smi); 2707 tst(reg2, Operand(kSmiTagMask));
2708 b(ne, on_not_both_smi, distance);
3031 } 2709 }
3032 2710
3033 2711
3034 void MacroAssembler::UntagAndJumpIfSmi( 2712 void MacroAssembler::UntagAndJumpIfSmi(
3035 Register dst, Register src, Label* smi_case) { 2713 Register dst, Register src, Label* smi_case) {
3036 STATIC_ASSERT(kSmiTag == 0); 2714 STATIC_ASSERT(kSmiTag == 0);
3037 mov(dst, Operand(src, ASR, kSmiTagSize), SetCC); 2715 tst(src, Operand(kSmiTagMask));
3038 b(cc, smi_case); // Shifter carry is not set for a smi. 2716 asr(dst, src, Operand(kSmiTagSize));
3039 } 2717 bt(smi_case);
3040
3041
3042 void MacroAssembler::UntagAndJumpIfNotSmi(
3043 Register dst, Register src, Label* non_smi_case) {
3044 STATIC_ASSERT(kSmiTag == 0);
3045 mov(dst, Operand(src, ASR, kSmiTagSize), SetCC);
3046 b(cs, non_smi_case); // Shifter carry is set for a non-smi.
3047 } 2718 }
3048 2719
3049 2720
3050 void MacroAssembler::JumpIfEitherSmi(Register reg1, 2721 void MacroAssembler::JumpIfEitherSmi(Register reg1,
3051 Register reg2, 2722 Register reg2,
3052 Label* on_either_smi) { 2723 Label* on_either_smi,
2724 Label::Distance distance) {
2725 ASSERT(!reg1.is(sh4_rtmp) && !reg2.is(sh4_rtmp));
3053 STATIC_ASSERT(kSmiTag == 0); 2726 STATIC_ASSERT(kSmiTag == 0);
2727 RECORD_LINE();
3054 tst(reg1, Operand(kSmiTagMask)); 2728 tst(reg1, Operand(kSmiTagMask));
3055 tst(reg2, Operand(kSmiTagMask), ne); 2729 b(eq, on_either_smi, distance);
3056 b(eq, on_either_smi); 2730 tst(reg2, Operand(kSmiTagMask));
2731 b(eq, on_either_smi, distance);
3057 } 2732 }
3058 2733
3059 2734
3060 void MacroAssembler::AssertNotSmi(Register object) { 2735 void MacroAssembler::AbortIfSmi(Register object) {
3061 if (emit_debug_code()) { 2736 STATIC_ASSERT(kSmiTag == 0);
3062 STATIC_ASSERT(kSmiTag == 0); 2737 ASSERT(!object.is(sh4_rtmp));
3063 tst(object, Operand(kSmiTagMask)); 2738
3064 Check(ne, "Operand is a smi"); 2739 tst(object, Operand(kSmiTagMask));
3065 } 2740 Assert(ne, "Operand is a smi");
3066 } 2741 }
3067 2742
3068 2743
3069 void MacroAssembler::AssertSmi(Register object) { 2744 void MacroAssembler::AbortIfNotSmi(Register object) {
3070 if (emit_debug_code()) { 2745 STATIC_ASSERT(kSmiTag == 0);
3071 STATIC_ASSERT(kSmiTag == 0); 2746 ASSERT(!object.is(sh4_rtmp));
3072 tst(object, Operand(kSmiTagMask)); 2747
3073 Check(eq, "Operand is not smi"); 2748 tst(object, Operand(kSmiTagMask));
3074 } 2749 Assert(eq, "Operand is not smi");
3075 } 2750 }
3076 2751
3077 2752
3078 void MacroAssembler::AssertString(Register object) { 2753 void MacroAssembler::AbortIfNotString(Register object) {
3079 if (emit_debug_code()) { 2754 STATIC_ASSERT(kSmiTag == 0);
3080 STATIC_ASSERT(kSmiTag == 0); 2755 ASSERT(!object.is(sh4_ip));
3081 tst(object, Operand(kSmiTagMask)); 2756 ASSERT(!object.is(sh4_rtmp));
3082 Check(ne, "Operand is a smi and not a string"); 2757
3083 push(object); 2758 tst(object, Operand(kSmiTagMask));
3084 ldr(object, FieldMemOperand(object, HeapObject::kMapOffset)); 2759 Assert(ne, "Operand is not a string");
3085 CompareInstanceType(object, object, FIRST_NONSTRING_TYPE); 2760 RECORD_LINE();
3086 pop(object); 2761 push(object);
3087 Check(lo, "Operand is not a string"); 2762 ldr(object, FieldMemOperand(object, HeapObject::kMapOffset));
3088 } 2763 CompareInstanceType(object, object, FIRST_NONSTRING_TYPE, hs);
2764 pop(object);
2765 Assert(ne, "Operand is not a string");
3089 } 2766 }
3090 2767
3091 2768
3092 2769 void MacroAssembler::AbortIfNotRootValue(Register src,
3093 void MacroAssembler::AssertRootValue(Register src, 2770 Heap::RootListIndex root_value_index,
3094 Heap::RootListIndex root_value_index, 2771 const char* message) {
3095 const char* message) { 2772 ASSERT(!src.is(sh4_ip));
3096 if (emit_debug_code()) { 2773 ASSERT(!src.is(sh4_rtmp));
3097 CompareRoot(src, root_value_index); 2774 CompareRoot(src, root_value_index);
3098 Check(eq, message); 2775 Assert(eq, message);
3099 }
3100 } 2776 }
3101 2777
3102 2778
2779 void MacroAssembler::PrintRegisterValue(Register reg) {
2780 ASSERT(!reg.is(r4) && !reg.is(r5) && !reg.is(r6) && !reg.is(r7));
2781 ASSERT(!reg.is(sh4_rtmp));
2782 Label gc_required, skip, not_smi;
2783 RECORD_LINE();
2784 EnterInternalFrame();
2785 // Save reg as it is scratched by WriteInt32ToHeapNumberStub()
2786 push(reg);
2787 pushm(kJSCallerSaved);
2788 TrySmiTag(reg, &not_smi, r5/*scratch*/);
2789 mov(r4, reg);
2790 jmp(&skip);
2791 bind(&not_smi);
2792 RECORD_LINE();
2793 LoadRoot(r7, Heap::kHeapNumberMapRootIndex);
2794 AllocateHeapNumber(r4/*result heap number*/, r5/*scratch*/, r6/*scratch*/,
2795 r7/*heap_number_map*/, &gc_required);
2796 WriteInt32ToHeapNumberStub stub(reg, r4, r5/*scratch*/);
2797 CallStub(&stub);
2798 jmp(&skip);
2799 bind(&gc_required);
2800 RECORD_LINE();
2801 Abort("GC required while dumping number");
2802 bind(&skip);
2803 RECORD_LINE();
2804 push(r4);
2805 CallRuntime(Runtime::kNumberToString, 1);
2806 push(r0);
2807 CallRuntime(Runtime::kGlobalPrint, 1);
2808 popm(kJSCallerSaved);
2809 pop(reg);
2810 LeaveInternalFrame();
2811 }
2812
2813
3103 void MacroAssembler::JumpIfNotHeapNumber(Register object, 2814 void MacroAssembler::JumpIfNotHeapNumber(Register object,
3104 Register heap_number_map, 2815 Register heap_number_map,
3105 Register scratch, 2816 Register scratch,
3106 Label* on_not_heap_number) { 2817 Label* on_not_heap_number) {
2818 RECORD_LINE();
2819 ASSERT(!scratch.is(sh4_ip));
2820 ASSERT(!scratch.is(sh4_rtmp));
2821 AssertRegisterIsRoot(heap_number_map, scratch, Heap::kHeapNumberMapRootIndex);
3107 ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); 2822 ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
3108 AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
3109 cmp(scratch, heap_number_map); 2823 cmp(scratch, heap_number_map);
3110 b(ne, on_not_heap_number); 2824 b(ne, on_not_heap_number);
3111 } 2825 }
3112 2826
3113 2827
3114 void MacroAssembler::JumpIfNonSmisNotBothSequentialAsciiStrings( 2828 void MacroAssembler::JumpIfNonSmisNotBothSequentialAsciiStrings(
3115 Register first, 2829 Register first,
3116 Register second, 2830 Register second,
3117 Register scratch1, 2831 Register scratch1,
3118 Register scratch2, 2832 Register scratch2,
3119 Label* failure) { 2833 Label* failure) {
2834
2835 ASSERT(!first.is(sh4_ip) && !second.is(sh4_ip) && !scratch1.is(sh4_ip) &&
2836 !scratch2.is(sh4_ip));
2837 ASSERT(!first.is(sh4_rtmp) && !second.is(sh4_rtmp) &&
2838 !scratch1.is(sh4_rtmp) && !scratch2.is(sh4_rtmp));
2839 RECORD_LINE();
3120 // Test that both first and second are sequential ASCII strings. 2840 // Test that both first and second are sequential ASCII strings.
3121 // Assume that they are non-smis. 2841 // Assume that they are non-smis.
3122 ldr(scratch1, FieldMemOperand(first, HeapObject::kMapOffset)); 2842 ldr(scratch1, FieldMemOperand(first, HeapObject::kMapOffset));
3123 ldr(scratch2, FieldMemOperand(second, HeapObject::kMapOffset)); 2843 ldr(scratch2, FieldMemOperand(second, HeapObject::kMapOffset));
3124 ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); 2844 ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
3125 ldrb(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset)); 2845 ldrb(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset));
3126 2846
3127 JumpIfBothInstanceTypesAreNotSequentialAscii(scratch1, 2847 JumpIfBothInstanceTypesAreNotSequentialAscii(scratch1,
3128 scratch2, 2848 scratch2,
3129 scratch1, 2849 scratch1,
3130 scratch2, 2850 scratch2,
3131 failure); 2851 failure);
3132 } 2852 }
3133 2853
2854
3134 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first, 2855 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first,
3135 Register second, 2856 Register second,
3136 Register scratch1, 2857 Register scratch1,
3137 Register scratch2, 2858 Register scratch2,
3138 Label* failure) { 2859 Label* failure) {
2860 ASSERT(!first.is(sh4_ip) && !second.is(sh4_ip) && !scratch1.is(sh4_ip) &&
2861 !scratch2.is(sh4_ip));
2862 ASSERT(!first.is(sh4_rtmp) && !second.is(sh4_rtmp) &&
2863 !scratch1.is(sh4_rtmp) && !scratch2.is(sh4_rtmp));
2864 RECORD_LINE();
3139 // Check that neither is a smi. 2865 // Check that neither is a smi.
3140 STATIC_ASSERT(kSmiTag == 0); 2866 STATIC_ASSERT(kSmiTag == 0);
3141 and_(scratch1, first, Operand(second)); 2867 land(scratch1, first, second);
3142 JumpIfSmi(scratch1, failure); 2868 JumpIfSmi(scratch1, failure);
3143 JumpIfNonSmisNotBothSequentialAsciiStrings(first, 2869 JumpIfNonSmisNotBothSequentialAsciiStrings(first,
3144 second, 2870 second,
3145 scratch1, 2871 scratch1,
3146 scratch2, 2872 scratch2,
3147 failure); 2873 failure);
3148 } 2874 }
3149 2875
3150 2876
3151 // Allocates a heap number or jumps to the need_gc label if the young space 2877 // Allocates a heap number or jumps to the need_gc label if the young space
3152 // is full and a scavenge is needed. 2878 // is full and a scavenge is needed.
3153 void MacroAssembler::AllocateHeapNumber(Register result, 2879 void MacroAssembler::AllocateHeapNumber(Register result,
3154 Register scratch1, 2880 Register scratch1,
3155 Register scratch2, 2881 Register scratch2,
3156 Register heap_number_map, 2882 Register heap_number_map,
3157 Label* gc_required, 2883 Label* gc_required) {
3158 TaggingMode tagging_mode) {
3159 // Allocate an object in the heap for the heap number and tag it as a heap 2884 // Allocate an object in the heap for the heap number and tag it as a heap
3160 // object. 2885 // object.
2886 RECORD_LINE();
3161 AllocateInNewSpace(HeapNumber::kSize, 2887 AllocateInNewSpace(HeapNumber::kSize,
3162 result, 2888 result,
3163 scratch1, 2889 scratch1,
3164 scratch2, 2890 scratch2,
3165 gc_required, 2891 gc_required,
3166 tagging_mode == TAG_RESULT ? TAG_OBJECT : 2892 TAG_OBJECT);
3167 NO_ALLOCATION_FLAGS);
3168 2893
3169 // Store heap number map in the allocated object. 2894 // Store heap number map in the allocated object.
3170 AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 2895 RECORD_LINE();
3171 if (tagging_mode == TAG_RESULT) { 2896 AssertRegisterIsRoot(heap_number_map, scratch1,
3172 str(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset)); 2897 Heap::kHeapNumberMapRootIndex);
3173 } else { 2898 RECORD_LINE();
3174 str(heap_number_map, MemOperand(result, HeapObject::kMapOffset)); 2899 str(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
3175 }
3176 } 2900 }
3177 2901
3178 2902
3179 void MacroAssembler::AllocateHeapNumberWithValue(Register result,
3180 DwVfpRegister value,
3181 Register scratch1,
3182 Register scratch2,
3183 Register heap_number_map,
3184 Label* gc_required) {
3185 AllocateHeapNumber(result, scratch1, scratch2, heap_number_map, gc_required);
3186 sub(scratch1, result, Operand(kHeapObjectTag));
3187 vstr(value, scratch1, HeapNumber::kValueOffset);
3188 }
3189
3190
3191 // Copies a fixed number of fields of heap objects from src to dst. 2903 // Copies a fixed number of fields of heap objects from src to dst.
3192 void MacroAssembler::CopyFields(Register dst, 2904 void MacroAssembler::CopyFields(Register dst,
3193 Register src, 2905 Register src,
3194 RegList temps, 2906 RegList temps,
3195 int field_count) { 2907 int field_count) {
3196 // At least one bit set in the first 15 registers. 2908 // At least one bit set in the first 15 registers.
3197 ASSERT((temps & ((1 << 15) - 1)) != 0); 2909 ASSERT((temps & ((1 << 15) - 1)) != 0);
3198 ASSERT((temps & dst.bit()) == 0); 2910 ASSERT((temps & dst.bit()) == 0);
3199 ASSERT((temps & src.bit()) == 0); 2911 ASSERT((temps & src.bit()) == 0);
3200 // Primitive implementation using only one temporary register. 2912 // Primitive implementation using only one temporary register.
3201 2913
3202 Register tmp = no_reg; 2914 Register tmp = no_reg;
3203 // Find a temp register in temps list. 2915 // Find a temp register in temps list.
3204 for (int i = 0; i < 15; i++) { 2916 for (int i = 0; i < 15; i++) {
3205 if ((temps & (1 << i)) != 0) { 2917 if ((temps & (1 << i)) != 0) {
3206 tmp.set_code(i); 2918 tmp.set_code(i);
3207 break; 2919 break;
3208 } 2920 }
3209 } 2921 }
3210 ASSERT(!tmp.is(no_reg)); 2922 ASSERT(!tmp.is(no_reg));
3211 2923 RECORD_LINE();
3212 for (int i = 0; i < field_count; i++) { 2924 for (int i = 0; i < field_count; i++) {
2925 RECORD_LINE();
3213 ldr(tmp, FieldMemOperand(src, i * kPointerSize)); 2926 ldr(tmp, FieldMemOperand(src, i * kPointerSize));
3214 str(tmp, FieldMemOperand(dst, i * kPointerSize)); 2927 str(tmp, FieldMemOperand(dst, i * kPointerSize));
3215 } 2928 }
3216 } 2929 }
3217 2930
3218 2931
3219 void MacroAssembler::CopyBytes(Register src, 2932 void MacroAssembler::CopyBytes(Register src,
3220 Register dst, 2933 Register dst,
3221 Register length, 2934 Register length,
3222 Register scratch) { 2935 Register scratch) {
3223 Label align_loop, align_loop_1, word_loop, byte_loop, byte_loop_1, done; 2936 Label align_loop, align_loop_1, word_loop, byte_loop, byte_loop_1, done;
3224 2937
3225 // Align src before copying in word size chunks. 2938 // Align src before copying in word size chunks.
3226 bind(&align_loop); 2939 bind(&align_loop);
3227 cmp(length, Operand(0)); 2940 cmp(length, Operand(0));
3228 b(eq, &done); 2941 b(eq, &done, Label::kNear);
3229 bind(&align_loop_1); 2942 bind(&align_loop_1);
3230 tst(src, Operand(kPointerSize - 1)); 2943 tst(src, Operand(kPointerSize - 1));
3231 b(eq, &word_loop); 2944 b(eq, &word_loop, Label::kNear);
3232 ldrb(scratch, MemOperand(src, 1, PostIndex)); 2945 ldrb(scratch, MemOperand(src));
3233 strb(scratch, MemOperand(dst, 1, PostIndex)); 2946 add(src, src, Operand(1));
3234 sub(length, length, Operand(1), SetCC); 2947 strb(scratch, MemOperand(dst));
3235 b(ne, &byte_loop_1); 2948 add(dst, dst, Operand(1));
2949 dt(length);
2950 b(ne, &byte_loop_1, Label::kNear);
3236 2951
3237 // Copy bytes in word size chunks. 2952 // Copy bytes in word size chunks.
3238 bind(&word_loop); 2953 bind(&word_loop);
3239 if (emit_debug_code()) { 2954 if (emit_debug_code()) {
3240 tst(src, Operand(kPointerSize - 1)); 2955 tst(src, Operand(kPointerSize - 1));
3241 Assert(eq, "Expecting alignment for CopyBytes"); 2956 Assert(eq, "Expecting alignment for CopyBytes");
3242 } 2957 }
3243 cmp(length, Operand(kPointerSize)); 2958 cmpge(length, Operand(kPointerSize));
3244 b(lt, &byte_loop); 2959 bf_near(&byte_loop);
3245 ldr(scratch, MemOperand(src, kPointerSize, PostIndex)); 2960 ldr(scratch, MemOperand(src));
3246 if (CpuFeatures::IsSupported(UNALIGNED_ACCESSES)) { 2961 add(src, src, Operand(kPointerSize));
3247 str(scratch, MemOperand(dst, kPointerSize, PostIndex)); 2962 #if CAN_USE_UNALIGNED_ACCESSES
3248 } else { 2963 str(scratch, MemOperand(dst));
3249 strb(scratch, MemOperand(dst, 1, PostIndex)); 2964 add(dst, dst, Operand(kPointerSize));
3250 mov(scratch, Operand(scratch, LSR, 8)); 2965 #else
3251 strb(scratch, MemOperand(dst, 1, PostIndex)); 2966 strb(scratch, MemOperand(dst));
3252 mov(scratch, Operand(scratch, LSR, 8)); 2967 add(dst, dst, Operand(1));
3253 strb(scratch, MemOperand(dst, 1, PostIndex)); 2968 lsr(scratch, scratch, Operand(8));
3254 mov(scratch, Operand(scratch, LSR, 8)); 2969 strb(scratch, MemOperand(dst));
3255 strb(scratch, MemOperand(dst, 1, PostIndex)); 2970 add(dst, dst, Operand(1));
3256 } 2971 lsr(scratch, scratch, Operand(8));
2972 strb(scratch, MemOperand(dst));
2973 add(dst, dst, Operand(1));
2974 lsr(scratch, scratch, Operand(8));
2975 strb(scratch, MemOperand(dst));
2976 add(dst, dst, Operand(1));
2977 #endif
3257 sub(length, length, Operand(kPointerSize)); 2978 sub(length, length, Operand(kPointerSize));
3258 b(&word_loop); 2979 b_near(&word_loop);
3259 2980
3260 // Copy the last bytes if any left. 2981 // Copy the last bytes if any left.
3261 bind(&byte_loop); 2982 bind(&byte_loop);
3262 cmp(length, Operand(0)); 2983 cmp(length, Operand(0));
3263 b(eq, &done); 2984 b(eq, &done, Label::kNear);
3264 bind(&byte_loop_1); 2985 bind(&byte_loop_1);
3265 ldrb(scratch, MemOperand(src, 1, PostIndex)); 2986 ldrb(scratch, MemOperand(src));
3266 strb(scratch, MemOperand(dst, 1, PostIndex)); 2987 add(src, src, Operand(1));
3267 sub(length, length, Operand(1), SetCC); 2988 strb(scratch, MemOperand(dst));
3268 b(ne, &byte_loop_1); 2989 add(dst, dst, Operand(1));
2990 dt(length);
2991 b(ne, &byte_loop_1, Label::kNear);
3269 bind(&done); 2992 bind(&done);
3270 } 2993 }
3271 2994
3272 2995
3273 void MacroAssembler::InitializeFieldsWithFiller(Register start_offset, 2996 void MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
3274 Register end_offset, 2997 Register end_offset,
3275 Register filler) { 2998 Register filler) {
3276 Label loop, entry; 2999 Label loop, entry;
3277 b(&entry); 3000 jmp(&entry);
3278 bind(&loop); 3001 bind(&loop);
3279 str(filler, MemOperand(start_offset, kPointerSize, PostIndex)); 3002 str(filler, MemOperand(start_offset, kPointerSize, PostIndex));
3280 bind(&entry); 3003 bind(&entry);
3281 cmp(start_offset, end_offset); 3004 cmpge(start_offset, end_offset);
3282 b(lt, &loop); 3005 bf(&loop);
3283 } 3006 }
3284 3007
3285 3008
3286 void MacroAssembler::CountLeadingZeros(Register zeros, // Answer. 3009 void MacroAssembler::CountLeadingZeros(Register zeros, // Answer.
3287 Register source, // Input. 3010 Register source, // Input.
3288 Register scratch) { 3011 Register scratch) {
3289 ASSERT(!zeros.is(source) || !source.is(scratch)); 3012 ASSERT(!zeros.is(source) || !source.is(scratch));
3290 ASSERT(!zeros.is(scratch)); 3013 ASSERT(!zeros.is(scratch));
3291 ASSERT(!scratch.is(ip)); 3014 ASSERT(!scratch.is(sh4_rtmp));
3292 ASSERT(!source.is(ip)); 3015 ASSERT(!source.is(sh4_rtmp));
3293 ASSERT(!zeros.is(ip)); 3016 ASSERT(!zeros.is(sh4_rtmp));
3294 #ifdef CAN_USE_ARMV5_INSTRUCTIONS 3017 ASSERT(!scratch.is(sh4_ip));
3295 clz(zeros, source); // This instruction is only supported after ARM5. 3018 ASSERT(!source.is(sh4_ip));
3296 #else 3019 ASSERT(!zeros.is(sh4_ip));
3297 // Order of the next two lines is important: zeros register 3020 RECORD_LINE();
3298 // can be the same as source register. 3021
3299 Move(scratch, source); 3022 Label l0, l1, l2, l3, l4, l5;
3300 mov(zeros, Operand(0, RelocInfo::NONE)); 3023 cmpeq(source, Operand(0));
3024 bf_near(&l0);
3025 mov(zeros, Operand(32));
3026 jmp_near(&l5);
3027
3028 bind(&l0);
3029 // Be carefull to save source in scratch, source and zeros may be the same
3030 // register
3031 mov(scratch, source);
3032 mov(zeros, Operand(0));
3301 // Top 16. 3033 // Top 16.
3302 tst(scratch, Operand(0xffff0000)); 3034 tst(scratch, Operand(0xffff0000));
3303 add(zeros, zeros, Operand(16), LeaveCC, eq); 3035 bf_near(&l1);
3304 mov(scratch, Operand(scratch, LSL, 16), LeaveCC, eq); 3036 add(zeros, zeros, Operand(16));
3037 lsl(scratch, scratch, Operand(16));
3305 // Top 8. 3038 // Top 8.
3039 bind(&l1);
3306 tst(scratch, Operand(0xff000000)); 3040 tst(scratch, Operand(0xff000000));
3307 add(zeros, zeros, Operand(8), LeaveCC, eq); 3041 bf_near(&l2);
3308 mov(scratch, Operand(scratch, LSL, 8), LeaveCC, eq); 3042 add(zeros, zeros, Operand(8));
3043 lsl(scratch, scratch, Operand(8));
3309 // Top 4. 3044 // Top 4.
3045 bind(&l2);
3310 tst(scratch, Operand(0xf0000000)); 3046 tst(scratch, Operand(0xf0000000));
3311 add(zeros, zeros, Operand(4), LeaveCC, eq); 3047 bf_near(&l3);
3312 mov(scratch, Operand(scratch, LSL, 4), LeaveCC, eq); 3048 add(zeros, zeros, Operand(4));
3049 lsl(scratch, scratch, Operand(4));
3313 // Top 2. 3050 // Top 2.
3051 bind(&l3);
3314 tst(scratch, Operand(0xc0000000)); 3052 tst(scratch, Operand(0xc0000000));
3315 add(zeros, zeros, Operand(2), LeaveCC, eq); 3053 bf_near(&l4);
3316 mov(scratch, Operand(scratch, LSL, 2), LeaveCC, eq); 3054 add(zeros, zeros, Operand(2));
3055 lsl(scratch, scratch, Operand(2));
3317 // Top bit. 3056 // Top bit.
3057 bind(&l4);
3318 tst(scratch, Operand(0x80000000u)); 3058 tst(scratch, Operand(0x80000000u));
3319 add(zeros, zeros, Operand(1), LeaveCC, eq); 3059 bf_near(&l5);
3320 #endif 3060 add(zeros, zeros, Operand(1));
3061 bind(&l5);
3321 } 3062 }
3322 3063
3323 3064
3324 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii( 3065 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii(
3325 Register first, 3066 Register first,
3326 Register second, 3067 Register second,
3327 Register scratch1, 3068 Register scratch1,
3328 Register scratch2, 3069 Register scratch2,
3329 Label* failure) { 3070 Label* failure) {
3071 ASSERT(!first.is(sh4_ip) && !second.is(sh4_ip) && !scratch1.is(sh4_ip) &&
3072 !scratch2.is(sh4_ip));
3073 ASSERT(!first.is(sh4_rtmp) && !second.is(sh4_rtmp) &&
3074 !scratch1.is(sh4_rtmp) && !scratch2.is(sh4_rtmp));
3075
3330 int kFlatAsciiStringMask = 3076 int kFlatAsciiStringMask =
3331 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; 3077 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
3332 int kFlatAsciiStringTag = ASCII_STRING_TYPE; 3078 int kFlatAsciiStringTag = ASCII_STRING_TYPE;
3333 and_(scratch1, first, Operand(kFlatAsciiStringMask)); 3079 RECORD_LINE();
3334 and_(scratch2, second, Operand(kFlatAsciiStringMask)); 3080 land(scratch1, first, Operand(kFlatAsciiStringMask));
3081 land(scratch2, second, Operand(kFlatAsciiStringMask));
3335 cmp(scratch1, Operand(kFlatAsciiStringTag)); 3082 cmp(scratch1, Operand(kFlatAsciiStringTag));
3336 // Ignore second test if first test failed. 3083 // Ignore second test if first test failed.
3337 cmp(scratch2, Operand(kFlatAsciiStringTag), eq); 3084 b(ne, failure);
3085 RECORD_LINE();
3086 cmp(scratch2, Operand(kFlatAsciiStringTag));
3338 b(ne, failure); 3087 b(ne, failure);
3339 } 3088 }
3340 3089
3341 3090
3342 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(Register type, 3091 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(Register type,
3343 Register scratch, 3092 Register scratch,
3344 Label* failure) { 3093 Label* failure) {
3094 ASSERT(!type.is(sh4_rtmp) && !scratch.is(sh4_rtmp));
3095
3345 int kFlatAsciiStringMask = 3096 int kFlatAsciiStringMask =
3346 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; 3097 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
3347 int kFlatAsciiStringTag = ASCII_STRING_TYPE; 3098 int kFlatAsciiStringTag = ASCII_STRING_TYPE;
3348 and_(scratch, type, Operand(kFlatAsciiStringMask)); 3099 RECORD_LINE();
3100 land(scratch, type, Operand(kFlatAsciiStringMask));
3349 cmp(scratch, Operand(kFlatAsciiStringTag)); 3101 cmp(scratch, Operand(kFlatAsciiStringTag));
3350 b(ne, failure); 3102 b(ne, failure);
3351 } 3103 }
3352 3104
3353 static const int kRegisterPassedArguments = 4; 3105 static const int kRegisterPassedArguments = 4;
3354 3106
3355 3107
3356 int MacroAssembler::CalculateStackPassedWords(int num_reg_arguments, 3108 int MacroAssembler::CalculateStackPassedWords(int num_reg_arguments,
3357 int num_double_arguments) { 3109 int num_double_arguments) {
3358 int stack_passed_words = 0; 3110 int stack_passed_words = 0;
3359 if (use_eabi_hardfloat()) { 3111 // Up to 4 simple arguments are passed in [r4, r7]
3360 // In the hard floating point calling convention, we can use
3361 // all double registers to pass doubles.
3362 if (num_double_arguments > DoubleRegister::kNumRegisters) {
3363 stack_passed_words +=
3364 2 * (num_double_arguments - DoubleRegister::kNumRegisters);
3365 }
3366 } else {
3367 // In the soft floating point calling convention, every double
3368 // argument is passed using two registers.
3369 num_reg_arguments += 2 * num_double_arguments;
3370 }
3371 // Up to four simple arguments are passed in registers r0..r3.
3372 if (num_reg_arguments > kRegisterPassedArguments) { 3112 if (num_reg_arguments > kRegisterPassedArguments) {
3373 stack_passed_words += num_reg_arguments - kRegisterPassedArguments; 3113 stack_passed_words += num_reg_arguments - kRegisterPassedArguments;
3374 } 3114 }
3115
3116 // Up to 4 double arguments are passed in [dr4, dr10]
3117 if (num_double_arguments > kRegisterPassedArguments) {
3118 stack_passed_words += 2 * (num_double_arguments - kRegisterPassedArguments);
3119 }
3120
3375 return stack_passed_words; 3121 return stack_passed_words;
3376 } 3122 }
3377 3123
3378 3124
3379 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, 3125 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
3380 int num_double_arguments, 3126 int num_double_arguments,
3381 Register scratch) { 3127 Register scratch) {
3382 int frame_alignment = ActivationFrameAlignment(); 3128 ASSERT(!scratch.is(sh4_ip));
3383 int stack_passed_arguments = CalculateStackPassedWords( 3129 ASSERT(!scratch.is(sh4_rtmp));
3384 num_reg_arguments, num_double_arguments); 3130 // Depending on the number of registers used, assert on the right scratch
3131 // registers.
3132 ASSERT((num_reg_arguments < 1 || !scratch.is(r4)) &&
3133 (num_reg_arguments < 2 || !scratch.is(r5)) &&
3134 (num_reg_arguments < 3 || !scratch.is(r6)) &&
3135 (num_reg_arguments < 4 || !scratch.is(r7)));
3136 int frame_alignment = OS::ActivationFrameAlignment();
3137 int stack_passed_arguments = CalculateStackPassedWords(num_reg_arguments,
3138 num_double_arguments);
3385 if (frame_alignment > kPointerSize) { 3139 if (frame_alignment > kPointerSize) {
3140 RECORD_LINE();
3386 // Make stack end at alignment and make room for num_arguments - 4 words 3141 // Make stack end at alignment and make room for num_arguments - 4 words
3387 // and the original value of sp. 3142 // and the original value of sp.
3388 mov(scratch, sp); 3143 mov(scratch, sp);
3389 sub(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize)); 3144 sub(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize));
3390 ASSERT(IsPowerOf2(frame_alignment)); 3145 ASSERT(IsPowerOf2(frame_alignment));
3391 and_(sp, sp, Operand(-frame_alignment)); 3146 land(sp, sp, Operand(-frame_alignment));
3392 str(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize)); 3147 str(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
3393 } else { 3148 } else {
3149 RECORD_LINE();
3394 sub(sp, sp, Operand(stack_passed_arguments * kPointerSize)); 3150 sub(sp, sp, Operand(stack_passed_arguments * kPointerSize));
3395 } 3151 }
3396 } 3152 }
3397 3153
3398 3154
3399 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, 3155 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
3400 Register scratch) { 3156 Register scratch) {
3401 PrepareCallCFunction(num_reg_arguments, 0, scratch); 3157 PrepareCallCFunction(num_reg_arguments, 0, scratch);
3402 } 3158 }
3403 3159
3404 3160
3405 void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg) {
3406 ASSERT(CpuFeatures::IsSupported(VFP2));
3407 if (use_eabi_hardfloat()) {
3408 Move(d0, dreg);
3409 } else {
3410 vmov(r0, r1, dreg);
3411 }
3412 }
3413
3414
3415 void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg1,
3416 DoubleRegister dreg2) {
3417 ASSERT(CpuFeatures::IsSupported(VFP2));
3418 if (use_eabi_hardfloat()) {
3419 if (dreg2.is(d0)) {
3420 ASSERT(!dreg1.is(d1));
3421 Move(d1, dreg2);
3422 Move(d0, dreg1);
3423 } else {
3424 Move(d0, dreg1);
3425 Move(d1, dreg2);
3426 }
3427 } else {
3428 vmov(r0, r1, dreg1);
3429 vmov(r2, r3, dreg2);
3430 }
3431 }
3432
3433
3434 void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg,
3435 Register reg) {
3436 ASSERT(CpuFeatures::IsSupported(VFP2));
3437 if (use_eabi_hardfloat()) {
3438 Move(d0, dreg);
3439 Move(r0, reg);
3440 } else {
3441 Move(r2, reg);
3442 vmov(r0, r1, dreg);
3443 }
3444 }
3445
3446
3447 void MacroAssembler::CallCFunction(ExternalReference function, 3161 void MacroAssembler::CallCFunction(ExternalReference function,
3448 int num_reg_arguments, 3162 int num_reg_arguments,
3449 int num_double_arguments) { 3163 int num_double_arguments) {
3450 mov(ip, Operand(function)); 3164 RECORD_LINE();
3451 CallCFunctionHelper(ip, num_reg_arguments, num_double_arguments); 3165 mov(r3, Operand(function));
3166 CallCFunctionHelper(r3, num_reg_arguments, num_double_arguments);
3452 } 3167 }
3453 3168
3454 3169
3455 void MacroAssembler::CallCFunction(Register function,
3456 int num_reg_arguments,
3457 int num_double_arguments) {
3458 CallCFunctionHelper(function, num_reg_arguments, num_double_arguments);
3459 }
3460
3461
3462 void MacroAssembler::CallCFunction(ExternalReference function,
3463 int num_arguments) {
3464 CallCFunction(function, num_arguments, 0);
3465 }
3466
3467
3468 void MacroAssembler::CallCFunction(Register function,
3469 int num_arguments) {
3470 CallCFunction(function, num_arguments, 0);
3471 }
3472
3473
3474 void MacroAssembler::CallCFunctionHelper(Register function, 3170 void MacroAssembler::CallCFunctionHelper(Register function,
3475 int num_reg_arguments, 3171 int num_reg_arguments,
3476 int num_double_arguments) { 3172 int num_double_arguments) {
3477 ASSERT(has_frame()); 3173 ASSERT(has_frame());
3478 // Make sure that the stack is aligned before calling a C function unless 3174 ASSERT(!function.is(sh4_ip));
3479 // running in the simulator. The simulator has its own alignment check which 3175 ASSERT(!function.is(sh4_rtmp));
3480 // provides more information. 3176 #if defined(V8_HOST_ARCH_SH4)
3481 #if defined(V8_HOST_ARCH_ARM)
3482 if (emit_debug_code()) { 3177 if (emit_debug_code()) {
3483 int frame_alignment = OS::ActivationFrameAlignment(); 3178 int frame_alignment = OS::ActivationFrameAlignment();
3484 int frame_alignment_mask = frame_alignment - 1; 3179 int frame_alignment_mask = frame_alignment - 1;
3485 if (frame_alignment > kPointerSize) { 3180 if (frame_alignment > kPointerSize) {
3486 ASSERT(IsPowerOf2(frame_alignment)); 3181 ASSERT(IsPowerOf2(frame_alignment));
3487 Label alignment_as_expected; 3182 Label alignment_as_expected;
3488 tst(sp, Operand(frame_alignment_mask)); 3183 tst(sp, Operand(frame_alignment_mask));
3489 b(eq, &alignment_as_expected); 3184 b(eq, &alignment_as_expected);
3490 // Don't use Check here, as it will call Runtime_Abort possibly 3185 // Don't use Check here, as it will call Runtime_Abort possibly
3491 // re-entering here. 3186 // re-entering here.
3492 stop("Unexpected alignment"); 3187 stop("Unexpected alignment");
3493 bind(&alignment_as_expected); 3188 bind(&alignment_as_expected);
3494 } 3189 }
3495 } 3190 }
3496 #endif 3191 #endif
3497 3192
3498 // Just call directly. The function called cannot cause a GC, or 3193 // Just call directly. The function called cannot cause a GC, or
3499 // allow preemption, so the return address in the link register 3194 // allow preemption, so the return address in the link register
3500 // stays correct. 3195 // stays correct.
3501 Call(function); 3196 jsr(function);
3502 int stack_passed_arguments = CalculateStackPassedWords( 3197 int stack_passed_arguments = CalculateStackPassedWords(
3503 num_reg_arguments, num_double_arguments); 3198 num_reg_arguments, num_double_arguments);
3504 if (ActivationFrameAlignment() > kPointerSize) { 3199 if (OS::ActivationFrameAlignment() > kPointerSize) {
3505 ldr(sp, MemOperand(sp, stack_passed_arguments * kPointerSize)); 3200 ldr(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
3506 } else { 3201 } else {
3507 add(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize))); 3202 add(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize)));
3508 } 3203 }
3509 } 3204 }
3510 3205
3511 3206
3512 void MacroAssembler::GetRelocatedValueLocation(Register ldr_location, 3207 void MacroAssembler::GetRelocatedValueLocation(Register ldr_location,
3513 Register result) { 3208 Register result) {
3514 const uint32_t kLdrOffsetMask = (1 << 12) - 1; 3209 UNIMPLEMENTED_BREAK();
3515 const int32_t kPCRegOffset = 2 * kPointerSize;
3516 ldr(result, MemOperand(ldr_location));
3517 if (emit_debug_code()) {
3518 // Check that the instruction is a ldr reg, [pc + offset] .
3519 and_(result, result, Operand(kLdrPCPattern));
3520 cmp(result, Operand(kLdrPCPattern));
3521 Check(eq, "The instruction to patch should be a load from pc.");
3522 // Result was clobbered. Restore it.
3523 ldr(result, MemOperand(ldr_location));
3524 }
3525 // Get the address of the constant.
3526 and_(result, result, Operand(kLdrOffsetMask));
3527 add(result, ldr_location, Operand(result));
3528 add(result, result, Operand(kPCRegOffset));
3529 } 3210 }
3530 3211
3531 3212
3532 void MacroAssembler::CheckPageFlag( 3213 void MacroAssembler::CheckPageFlag(
3533 Register object, 3214 Register object,
3534 Register scratch, 3215 Register scratch,
3535 int mask, 3216 int mask,
3536 Condition cc, 3217 Condition cc,
3537 Label* condition_met) { 3218 Label* condition_met) {
3538 Bfc(scratch, object, 0, kPageSizeBits); 3219 land(scratch, object, Operand(~Page::kPageAlignmentMask));
3539 ldr(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset)); 3220 ldr(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset));
3540 tst(scratch, Operand(mask)); 3221 cmphs(scratch, Operand(mask));
3541 b(cc, condition_met); 3222 bf(condition_met);
3542 } 3223 }
3543 3224
3544 3225
3545 void MacroAssembler::JumpIfBlack(Register object, 3226 void MacroAssembler::JumpIfBlack(Register object,
3546 Register scratch0, 3227 Register scratch0,
3547 Register scratch1, 3228 Register scratch1,
3548 Label* on_black) { 3229 Label* on_black) {
3549 HasColor(object, scratch0, scratch1, on_black, 1, 0); // kBlackBitPattern. 3230 HasColor(object, scratch0, scratch1, on_black, 1, 0); // kBlackBitPattern.
3550 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); 3231 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
3551 } 3232 }
3552 3233
3553 3234
3554 void MacroAssembler::HasColor(Register object, 3235 void MacroAssembler::HasColor(Register object,
3555 Register bitmap_scratch, 3236 Register bitmap_scratch,
3556 Register mask_scratch, 3237 Register mask_scratch,
3557 Label* has_color, 3238 Label* has_color,
3558 int first_bit, 3239 int first_bit,
3559 int second_bit) { 3240 int second_bit) {
3560 ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, no_reg)); 3241 ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, no_reg));
3561 3242
3562 GetMarkBits(object, bitmap_scratch, mask_scratch); 3243 GetMarkBits(object, bitmap_scratch, mask_scratch);
3563 3244
3564 Label other_color, word_boundary; 3245 Label other_color, word_boundary;
3565 ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); 3246 ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
3566 tst(ip, Operand(mask_scratch)); 3247 tst(ip, mask_scratch);
3567 b(first_bit == 1 ? eq : ne, &other_color); 3248 b(first_bit == 1 ? eq : ne, &other_color);
3568 // Shift left 1 by adding. 3249 // Shift left 1 by adding.
3569 add(mask_scratch, mask_scratch, Operand(mask_scratch), SetCC); 3250 add(mask_scratch, mask_scratch, mask_scratch);
3251 tst(mask_scratch, mask_scratch);
3570 b(eq, &word_boundary); 3252 b(eq, &word_boundary);
3571 tst(ip, Operand(mask_scratch)); 3253 tst(ip, mask_scratch);
3572 b(second_bit == 1 ? ne : eq, has_color); 3254 b(second_bit == 1 ? ne : eq, has_color);
3573 jmp(&other_color); 3255 jmp(&other_color);
3574 3256
3575 bind(&word_boundary); 3257 bind(&word_boundary);
3576 ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize)); 3258 ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize));
3577 tst(ip, Operand(1)); 3259 tst(ip, Operand(1));
3578 b(second_bit == 1 ? ne : eq, has_color); 3260 b(second_bit == 1 ? ne : eq, has_color);
3579 bind(&other_color); 3261 bind(&other_color);
3580 } 3262 }
3581 3263
3582 3264
3583 // Detect some, but not all, common pointer-free objects. This is used by the
3584 // incremental write barrier which doesn't care about oddballs (they are always
3585 // marked black immediately so this code is not hit).
3586 void MacroAssembler::JumpIfDataObject(Register value,
3587 Register scratch,
3588 Label* not_data_object) {
3589 Label is_data_object;
3590 ldr(scratch, FieldMemOperand(value, HeapObject::kMapOffset));
3591 CompareRoot(scratch, Heap::kHeapNumberMapRootIndex);
3592 b(eq, &is_data_object);
3593 ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
3594 ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
3595 // If it's a string and it's not a cons string then it's an object containing
3596 // no GC pointers.
3597 ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
3598 tst(scratch, Operand(kIsIndirectStringMask | kIsNotStringMask));
3599 b(ne, not_data_object);
3600 bind(&is_data_object);
3601 }
3602
3603
3604 void MacroAssembler::GetMarkBits(Register addr_reg, 3265 void MacroAssembler::GetMarkBits(Register addr_reg,
3605 Register bitmap_reg, 3266 Register bitmap_reg,
3606 Register mask_reg) { 3267 Register mask_reg) {
3607 ASSERT(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg)); 3268 ASSERT(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg));
3608 and_(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask)); 3269 land(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask));
3609 Ubfx(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2); 3270 Ubfx(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2);
3610 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; 3271 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2;
3611 Ubfx(ip, addr_reg, kLowBits, kPageSizeBits - kLowBits); 3272 Ubfx(ip, addr_reg, kLowBits, kPageSizeBits - kLowBits);
3612 add(bitmap_reg, bitmap_reg, Operand(ip, LSL, kPointerSizeLog2)); 3273 lsl(ip, ip, Operand(kPointerSizeLog2));
3274 add(bitmap_reg, bitmap_reg, ip);
3613 mov(ip, Operand(1)); 3275 mov(ip, Operand(1));
3614 mov(mask_reg, Operand(ip, LSL, mask_reg)); 3276 lsl(mask_reg, ip, mask_reg);
3615 } 3277 }
3616 3278
3617 3279
3618 void MacroAssembler::EnsureNotWhite( 3280 void MacroAssembler::EnsureNotWhite(
3619 Register value, 3281 Register value,
3620 Register bitmap_scratch, 3282 Register bitmap_scratch,
3621 Register mask_scratch, 3283 Register mask_scratch,
3622 Register load_scratch, 3284 Register load_scratch,
3623 Label* value_is_white_and_not_data) { 3285 Label* value_is_white_and_not_data) {
3624 ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, ip)); 3286 ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, ip));
(...skipping 10 matching lines...) Expand all
3635 // Since both black and grey have a 1 in the first position and white does 3297 // Since both black and grey have a 1 in the first position and white does
3636 // not have a 1 there we only need to check one bit. 3298 // not have a 1 there we only need to check one bit.
3637 ldr(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); 3299 ldr(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
3638 tst(mask_scratch, load_scratch); 3300 tst(mask_scratch, load_scratch);
3639 b(ne, &done); 3301 b(ne, &done);
3640 3302
3641 if (emit_debug_code()) { 3303 if (emit_debug_code()) {
3642 // Check for impossible bit pattern. 3304 // Check for impossible bit pattern.
3643 Label ok; 3305 Label ok;
3644 // LSL may overflow, making the check conservative. 3306 // LSL may overflow, making the check conservative.
3645 tst(load_scratch, Operand(mask_scratch, LSL, 1)); 3307 lsl(ip, mask_scratch, Operand(1));
3308 tst(load_scratch, ip);
3646 b(eq, &ok); 3309 b(eq, &ok);
3647 stop("Impossible marking bit pattern"); 3310 stop("Impossible marking bit pattern");
3648 bind(&ok); 3311 bind(&ok);
3649 } 3312 }
3650 3313
3651 // Value is white. We check whether it is data that doesn't need scanning. 3314 // Value is white. We check whether it is data that doesn't need scanning.
3652 // Currently only checks for HeapNumber and non-cons strings. 3315 // Currently only checks for HeapNumber and non-cons strings.
3653 Register map = load_scratch; // Holds map while checking type. 3316 Register map = load_scratch; // Holds map while checking type.
3654 Register length = load_scratch; // Holds length of object after testing type. 3317 Register length = load_scratch; // Holds length of object after testing type.
3655 Label is_data_object; 3318 Label is_data_object;
3656 3319
3657 // Check for heap-number 3320 // Check for heap-number
3658 ldr(map, FieldMemOperand(value, HeapObject::kMapOffset)); 3321 ldr(map, FieldMemOperand(value, HeapObject::kMapOffset));
3659 CompareRoot(map, Heap::kHeapNumberMapRootIndex); 3322 CompareRoot(map, Heap::kHeapNumberMapRootIndex);
3660 mov(length, Operand(HeapNumber::kSize), LeaveCC, eq); 3323 mov(length, Operand(HeapNumber::kSize), eq);
3661 b(eq, &is_data_object); 3324 b(eq, &is_data_object);
3662 3325
3663 // Check for strings. 3326 // Check for strings.
3664 ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); 3327 ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
3665 ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); 3328 ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
3666 // If it's a string and it's not a cons string then it's an object containing 3329 // If it's a string and it's not a cons string then it's an object containing
3667 // no GC pointers. 3330 // no GC pointers.
3668 Register instance_type = load_scratch; 3331 Register instance_type = load_scratch;
3669 ldrb(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset)); 3332 ldrb(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset));
3670 tst(instance_type, Operand(kIsIndirectStringMask | kIsNotStringMask)); 3333 tst(instance_type, Operand(kIsIndirectStringMask | kIsNotStringMask));
3671 b(ne, value_is_white_and_not_data); 3334 b(ne, value_is_white_and_not_data);
3672 // It's a non-indirect (non-cons and non-slice) string. 3335 // It's a non-indirect (non-cons and non-slice) string.
3673 // If it's external, the length is just ExternalString::kSize. 3336 // If it's external, the length is just ExternalString::kSize.
3674 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). 3337 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2).
3675 // External strings are the only ones with the kExternalStringTag bit 3338 // External strings are the only ones with the kExternalStringTag bit
3676 // set. 3339 // set.
3677 ASSERT_EQ(0, kSeqStringTag & kExternalStringTag); 3340 ASSERT_EQ(0, kSeqStringTag & kExternalStringTag);
3678 ASSERT_EQ(0, kConsStringTag & kExternalStringTag); 3341 ASSERT_EQ(0, kConsStringTag & kExternalStringTag);
3679 tst(instance_type, Operand(kExternalStringTag)); 3342 tst(instance_type, Operand(kExternalStringTag));
3680 mov(length, Operand(ExternalString::kSize), LeaveCC, ne); 3343 mov(length, Operand(ExternalString::kSize), ne);
3681 b(ne, &is_data_object); 3344 b(ne, &is_data_object);
3682 3345
3683 // Sequential string, either ASCII or UC16. 3346 // Sequential string, either ASCII or UC16.
3684 // For ASCII (char-size of 1) we shift the smi tag away to get the length. 3347 // For ASCII (char-size of 1) we shift the smi tag away to get the length.
3685 // For UC16 (char-size of 2) we just leave the smi tag in place, thereby 3348 // For UC16 (char-size of 2) we just leave the smi tag in place, thereby
3686 // getting the length multiplied by 2. 3349 // getting the length multiplied by 2.
3687 ASSERT(kAsciiStringTag == 4 && kStringEncodingMask == 4); 3350 ASSERT(kAsciiStringTag == 4 && kStringEncodingMask == 4);
3688 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 3351 ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3689 ldr(ip, FieldMemOperand(value, String::kLengthOffset)); 3352 ldr(ip, FieldMemOperand(value, String::kLengthOffset));
3690 tst(instance_type, Operand(kStringEncodingMask)); 3353 tst(instance_type, Operand(kStringEncodingMask));
3691 mov(ip, Operand(ip, LSR, 1), LeaveCC, ne); 3354 Label skip;
3355 bt(&skip);
3356 lsr(ip, ip, Operand(1));
3357 bind(&skip);
3692 add(length, ip, Operand(SeqString::kHeaderSize + kObjectAlignmentMask)); 3358 add(length, ip, Operand(SeqString::kHeaderSize + kObjectAlignmentMask));
3693 and_(length, length, Operand(~kObjectAlignmentMask)); 3359 land(length, length, Operand(~kObjectAlignmentMask));
3694 3360
3695 bind(&is_data_object); 3361 bind(&is_data_object);
3696 // Value is a data object, and it is white. Mark it black. Since we know 3362 // Value is a data object, and it is white. Mark it black. Since we know
3697 // that the object is white we can make it black by flipping one bit. 3363 // that the object is white we can make it black by flipping one bit.
3698 ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); 3364 ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
3699 orr(ip, ip, Operand(mask_scratch)); 3365 orr(ip, ip, mask_scratch);
3700 str(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); 3366 str(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
3701 3367
3702 and_(bitmap_scratch, bitmap_scratch, Operand(~Page::kPageAlignmentMask)); 3368 land(bitmap_scratch, bitmap_scratch, Operand(~Page::kPageAlignmentMask));
3703 ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); 3369 ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
3704 add(ip, ip, Operand(length)); 3370 add(ip, ip, length);
3705 str(ip, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); 3371 str(ip, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
3706 3372
3707 bind(&done); 3373 bind(&done);
3708 } 3374 }
3709 3375
3710 3376
3711 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) {
3712 Usat(output_reg, 8, Operand(input_reg));
3713 }
3714
3715
3716 void MacroAssembler::ClampDoubleToUint8(Register result_reg,
3717 DoubleRegister input_reg,
3718 DoubleRegister temp_double_reg) {
3719 Label above_zero;
3720 Label done;
3721 Label in_bounds;
3722
3723 Vmov(temp_double_reg, 0.0);
3724 VFPCompareAndSetFlags(input_reg, temp_double_reg);
3725 b(gt, &above_zero);
3726
3727 // Double value is less than zero, NaN or Inf, return 0.
3728 mov(result_reg, Operand(0));
3729 b(al, &done);
3730
3731 // Double value is >= 255, return 255.
3732 bind(&above_zero);
3733 Vmov(temp_double_reg, 255.0, result_reg);
3734 VFPCompareAndSetFlags(input_reg, temp_double_reg);
3735 b(le, &in_bounds);
3736 mov(result_reg, Operand(255));
3737 b(al, &done);
3738
3739 // In 0-255 range, round and truncate.
3740 bind(&in_bounds);
3741 // Save FPSCR.
3742 vmrs(ip);
3743 // Set rounding mode to round to the nearest integer by clearing bits[23:22].
3744 bic(result_reg, ip, Operand(kVFPRoundingModeMask));
3745 vmsr(result_reg);
3746 vcvt_s32_f64(input_reg.low(), input_reg, kFPSCRRounding);
3747 vmov(result_reg, input_reg.low());
3748 // Restore FPSCR.
3749 vmsr(ip);
3750 bind(&done);
3751 }
3752
3753
3754 void MacroAssembler::LoadInstanceDescriptors(Register map, 3377 void MacroAssembler::LoadInstanceDescriptors(Register map,
3755 Register descriptors) { 3378 Register descriptors,
3379 Register scratch) {
3756 ldr(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset)); 3380 ldr(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset));
3757 } 3381 }
3758 3382
3759 3383
3760 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { 3384 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
3761 ldr(dst, FieldMemOperand(map, Map::kBitField3Offset)); 3385 ldr(dst, FieldMemOperand(map, Map::kBitField3Offset));
3762 DecodeField<Map::NumberOfOwnDescriptorsBits>(dst); 3386 DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
3763 } 3387 }
3764 3388
3765 3389
3766 void MacroAssembler::EnumLength(Register dst, Register map) { 3390 void MacroAssembler::EnumLength(Register dst, Register map) {
3767 STATIC_ASSERT(Map::EnumLengthBits::kShift == 0); 3391 STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
3768 ldr(dst, FieldMemOperand(map, Map::kBitField3Offset)); 3392 ldr(dst, FieldMemOperand(map, Map::kBitField3Offset));
3769 and_(dst, dst, Operand(Smi::FromInt(Map::EnumLengthBits::kMask))); 3393 land(dst, dst, Operand(Smi::FromInt(Map::EnumLengthBits::kMask)));
3770 } 3394 }
3771 3395
3772 3396
3773 void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) { 3397 void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) {
3774 Register empty_fixed_array_value = r6; 3398 Register empty_fixed_array_value = r6;
3775 LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); 3399 LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
3776 Label next, start; 3400 Label next, start;
3777 mov(r2, r0); 3401 mov(r2, r0);
3778 3402
3779 // Check if the enum length field is properly initialized, indicating that 3403 // Check if the enum length field is properly initialized, indicating that
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
3825 if (reg4.is_valid()) regs |= reg4.bit(); 3449 if (reg4.is_valid()) regs |= reg4.bit();
3826 if (reg5.is_valid()) regs |= reg5.bit(); 3450 if (reg5.is_valid()) regs |= reg5.bit();
3827 if (reg6.is_valid()) regs |= reg6.bit(); 3451 if (reg6.is_valid()) regs |= reg6.bit();
3828 int n_of_non_aliasing_regs = NumRegs(regs); 3452 int n_of_non_aliasing_regs = NumRegs(regs);
3829 3453
3830 return n_of_valid_regs != n_of_non_aliasing_regs; 3454 return n_of_valid_regs != n_of_non_aliasing_regs;
3831 } 3455 }
3832 #endif 3456 #endif
3833 3457
3834 3458
3459 void MacroAssembler::Drop(int stack_elements) {
3460 RECORD_LINE();
3461 if (stack_elements > 0) {
3462 RECORD_LINE();
3463 add(sp, sp, Operand(stack_elements * kPointerSize));
3464 }
3465 }
3466
3467
3468 void MacroAssembler::UnimplementedBreak(const char *file, int line) {
3469 uint32_t file_id = 0;
3470 const char *base = strrchr(file, '/');
3471 if (base == NULL)
3472 base = file;
3473 while (*base) {
3474 file_id += *base;
3475 base++;
3476 }
3477 RECORD_LINE();
3478 mov(r0, Operand(file_id));
3479 mov(r1, Operand(line));
3480 bkpt();
3481 }
3482
3483
3484 void MacroAssembler::Ret(Condition cond) {
3485 ASSERT(cond == al || cond == eq || cond == ne);
3486 if (cond == al) {
3487 RECORD_LINE();
3488 rts();
3489 } else {
3490 RECORD_LINE();
3491 Label skip;
3492 if (cond == eq) {
3493 bf_near(&skip);
3494 } else {
3495 bt_near(&skip);
3496 }
3497 rts();
3498 bind(&skip);
3499 }
3500 }
3501
3502
3503 MacroAssembler* MacroAssembler::RecordFunctionLine(const char* function,
3504 int line) {
3505 if (FLAG_code_comments) {
3506 /* 10(strlen of MAXINT) + 1(separator) +1(nul). */
3507 int size = strlen("/line/")+strlen(function) + 10 + 1 + 1;
3508 char *buffer = new char[size];
3509 snprintf(buffer, size, "/line/%s/%d", function, line);
3510 buffer[size-1] = '\0';
3511 RecordComment(buffer);
3512 }
3513 return this;
3514 }
3515
3516
3835 CodePatcher::CodePatcher(byte* address, int instructions) 3517 CodePatcher::CodePatcher(byte* address, int instructions)
3836 : address_(address), 3518 : address_(address),
3837 instructions_(instructions), 3519 instructions_(instructions),
3838 size_(instructions * Assembler::kInstrSize), 3520 size_(instructions * Assembler::kInstrSize),
3839 masm_(NULL, address, size_ + Assembler::kGap) { 3521 masm_(NULL, address, size_ + Assembler::kGap) {
3840 // Create a new macro assembler pointing to the address of the code to patch. 3522 // Create a new macro assembler pointing to the address of the code to patch.
3841 // The size is adjusted with kGap on order for the assembler to generate size 3523 // The size is adjusted with kGap on order for the assembler to generate size
3842 // bytes of instructions without failing with buffer size constraints. 3524 // bytes of instructions without failing with buffer size constraints.
3843 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 3525 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
3844 } 3526 }
3845 3527
3846 3528
3847 CodePatcher::~CodePatcher() { 3529 CodePatcher::~CodePatcher() {
3848 // Indicate that code has changed. 3530 // Indicate that code has changed.
3849 CPU::FlushICache(address_, size_); 3531 CPU::FlushICache(address_, size_);
3850 3532
3851 // Check that the code was patched as expected. 3533 // Check that the code was patched as expected.
3852 ASSERT(masm_.pc_ == address_ + size_); 3534 ASSERT(masm_.pc_ == address_ + size_);
3853 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 3535 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
3854 } 3536 }
3855 3537
3856 3538
3857 void CodePatcher::Emit(Instr instr) {
3858 masm()->emit(instr);
3859 }
3860
3861
3862 void CodePatcher::Emit(Address addr) {
3863 masm()->emit(reinterpret_cast<Instr>(addr));
3864 }
3865
3866
3867 void CodePatcher::EmitCondition(Condition cond) { 3539 void CodePatcher::EmitCondition(Condition cond) {
3868 Instr instr = Assembler::instr_at(masm_.pc_); 3540 Instr instr = Assembler::instr_at(masm_.pc_);
3869 instr = (instr & ~kCondMask) | cond; 3541 ASSERT(cond == eq || cond == ne);
3542 ASSERT(Assembler::IsBranch(instr));
3543 instr = (instr & ~0x200); // Changed to bt
3544 if (cond == ne)
3545 instr |= 0x200; // Changed to bf
3870 masm_.emit(instr); 3546 masm_.emit(instr);
3871 } 3547 }
3872 3548
3873 3549
3874 } } // namespace v8::internal 3550 } } // namespace v8::internal
3875 3551
3876 #endif // V8_TARGET_ARCH_ARM 3552 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/sh4/macro-assembler-sh4.h ('k') | src/sh4/map-sh4.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698