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

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

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/lithium-sh4.cc ('k') | src/sh4/macro-assembler-sh4.cc » ('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 #ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_ 28 #ifndef V8_SH4_MACRO_ASSEMBLER_SH4_H_
29 #define V8_ARM_MACRO_ASSEMBLER_ARM_H_ 29 #define V8_SH4_MACRO_ASSEMBLER_SH4_H_
30 30
31 #include "assembler.h" 31 #include "assembler.h"
32 #include "frames.h" 32 #include "frames.h"
33 #include "v8globals.h" 33 #include "v8globals.h"
34 34
35 namespace v8 { 35 namespace v8 {
36 namespace internal { 36 namespace internal {
37 37
38 // ---------------------------------------------------------------------------- 38 // ----------------------------------------------------------------------------
39 // Static helper functions 39 // Static helper functions
40 40
41 // Generate a MemOperand for loading a field from an object. 41 // Generate a MemOperand for loading a field from an object.
42 inline MemOperand FieldMemOperand(Register object, int offset) { 42 inline MemOperand FieldMemOperand(Register object, int offset) {
43 return MemOperand(object, offset - kHeapObjectTag); 43 return MemOperand(object, offset - kHeapObjectTag);
44 } 44 }
45 45
46
47 inline Operand SmiUntagOperand(Register object) {
48 return Operand(object, ASR, kSmiTagSize);
49 }
50
51
52
53 // Give alias names to registers
54 const Register cp = { 8 }; // JavaScript context pointer
55 const Register kRootRegister = { 10 }; // Roots array pointer.
56
57 // Flags used for the AllocateInNewSpace functions. 46 // Flags used for the AllocateInNewSpace functions.
58 enum AllocationFlags { 47 enum AllocationFlags {
59 // No special flags. 48 // No special flags.
60 NO_ALLOCATION_FLAGS = 0, 49 NO_ALLOCATION_FLAGS = 0,
61 // Return the pointer to the allocated already tagged as a heap object. 50 // Return the pointer to the allocated already tagged as a heap object.
62 TAG_OBJECT = 1 << 0, 51 TAG_OBJECT = 1 << 0,
63 // The content of the result register already contains the allocation top in 52 // The content of the result register already contains the allocation top in
64 // new space. 53 // new space.
65 RESULT_CONTAINS_TOP = 1 << 1, 54 RESULT_CONTAINS_TOP = 1 << 1,
66 // Specify that the requested size of the space to allocate is specified in 55 // Specify that the requested size of the space to allocate is specified in
67 // words instead of bytes. 56 // words instead of bytes.
68 SIZE_IN_WORDS = 1 << 2 57 SIZE_IN_WORDS = 1 << 2
69 }; 58 };
70 59
71 // Flags used for AllocateHeapNumber
72 enum TaggingMode {
73 // Tag the result.
74 TAG_RESULT,
75 // Don't tag
76 DONT_TAG_RESULT
77 };
78 60
79 // Flags used for the ObjectToDoubleVFPRegister function. 61 // Flags used for the ObjectToDoubleVFPRegister function.
80 enum ObjectToDoubleFlags { 62 enum ObjectToDoubleFlags {
81 // No special flags. 63 // No special flags.
82 NO_OBJECT_TO_DOUBLE_FLAGS = 0, 64 NO_OBJECT_TO_DOUBLE_FLAGS = 0,
83 // Object is known to be a non smi. 65 // Object is known to be a non smi.
84 OBJECT_NOT_SMI = 1 << 0, 66 OBJECT_NOT_SMI = 1 << 0,
85 // Don't load NaNs or infinities, branch to the non number case instead. 67 // Don't load NaNs or infinities, branch to the non number case instead.
86 AVOID_NANS_AND_INFINITIES = 1 << 1 68 AVOID_NANS_AND_INFINITIES = 1 << 1
87 }; 69 };
88 70
89 71
90 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET }; 72 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
91 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK }; 73 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
92 enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved }; 74 enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved };
93 75
94 76
95 #ifdef DEBUG 77 #ifdef DEBUG
96 bool AreAliased(Register reg1, 78 bool AreAliased(Register reg1,
97 Register reg2, 79 Register reg2,
98 Register reg3 = no_reg, 80 Register reg3 = no_reg,
99 Register reg4 = no_reg, 81 Register reg4 = no_reg,
100 Register reg5 = no_reg, 82 Register reg5 = no_reg,
101 Register reg6 = no_reg); 83 Register reg6 = no_reg);
102 #endif 84 #endif
103 85
104 86
105 enum TargetAddressStorageMode {
106 CAN_INLINE_TARGET_ADDRESS,
107 NEVER_INLINE_TARGET_ADDRESS
108 };
109
110 // MacroAssembler implements a collection of frequently used macros. 87 // MacroAssembler implements a collection of frequently used macros.
111 class MacroAssembler: public Assembler { 88 class MacroAssembler: public Assembler {
112 public: 89 public:
113 // The isolate parameter can be NULL if the macro assembler should 90 // The isolate parameter can be NULL if the macro assembler should
114 // not use isolate-dependent functionality. In this case, it's the 91 // not use isolate-dependent functionality. In this case, it's the
115 // responsibility of the caller to never invoke such function on the 92 // responsibility of the caller to never invoke such function on the
116 // macro assembler. 93 // macro assembler.
117 MacroAssembler(Isolate* isolate, void* buffer, int size); 94 MacroAssembler(Isolate* isolate, void* buffer, int size);
118 95
119 // Jump, Call, and Ret pseudo instructions implementing inter-working.
120 void Jump(Register target, Condition cond = al);
121 void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al);
122 void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
123 static int CallSize(Register target, Condition cond = al);
124 void Call(Register target, Condition cond = al);
125 int CallSize(Address target, RelocInfo::Mode rmode, Condition cond = al);
126 static int CallSizeNotPredictableCodeSize(Address target,
127 RelocInfo::Mode rmode,
128 Condition cond = al);
129 void Call(Address target, RelocInfo::Mode rmode,
130 Condition cond = al,
131 TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS);
132 int CallSize(Handle<Code> code,
133 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
134 TypeFeedbackId ast_id = TypeFeedbackId::None(),
135 Condition cond = al);
136 void Call(Handle<Code> code,
137 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
138 TypeFeedbackId ast_id = TypeFeedbackId::None(),
139 Condition cond = al,
140 TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS);
141 void Ret(Condition cond = al);
142
143 // Emit code to discard a non-negative number of pointer-sized elements
144 // from the stack, clobbering only the sp register.
145 void Drop(int count, Condition cond = al);
146
147 void Ret(int drop, Condition cond = al);
148
149 // Swap two registers. If the scratch register is omitted then a slightly
150 // less efficient form using xor instead of mov is emitted.
151 void Swap(Register reg1,
152 Register reg2,
153 Register scratch = no_reg,
154 Condition cond = al);
155
156
157 void And(Register dst, Register src1, const Operand& src2,
158 Condition cond = al);
159 void Ubfx(Register dst, Register src, int lsb, int width,
160 Condition cond = al);
161 void Sbfx(Register dst, Register src, int lsb, int width,
162 Condition cond = al);
163 // The scratch register is not used for ARMv7.
164 // scratch can be the same register as src (in which case it is trashed), but
165 // not the same as dst.
166 void Bfi(Register dst,
167 Register src,
168 Register scratch,
169 int lsb,
170 int width,
171 Condition cond = al);
172 void Bfc(Register dst, Register src, int lsb, int width, Condition cond = al);
173 void Usat(Register dst, int satpos, const Operand& src,
174 Condition cond = al);
175
176 void Call(Label* target);
177
178 // Register move. May do nothing if the registers are identical.
179 void Move(Register dst, Handle<Object> value);
180 void Move(Register dst, Register src, Condition cond = al);
181 void Move(DoubleRegister dst, DoubleRegister src);
182
183 // Load an object from the root table. 96 // Load an object from the root table.
184 void LoadRoot(Register destination, 97 void LoadRoot(Register destination,
185 Heap::RootListIndex index, 98 Heap::RootListIndex index);
186 Condition cond = al);
187 // Store an object to the root table. 99 // Store an object to the root table.
188 void StoreRoot(Register source, 100 void StoreRoot(Register source,
189 Heap::RootListIndex index, 101 Heap::RootListIndex index);
190 Condition cond = al);
191 102
192 void LoadHeapObject(Register dst, Handle<HeapObject> object); 103 void LoadHeapObject(Register dst, Handle<HeapObject> object);
193 104
194 void LoadObject(Register result, Handle<Object> object) { 105 void LoadObject(Register result, Handle<Object> object) {
195 if (object->IsHeapObject()) { 106 if (object->IsHeapObject()) {
196 LoadHeapObject(result, Handle<HeapObject>::cast(object)); 107 LoadHeapObject(result, Handle<HeapObject>::cast(object));
197 } else { 108 } else {
198 Move(result, object); 109 Move(result, object);
199 } 110 }
200 } 111 }
201 112
202 // --------------------------------------------------------------------------- 113 // ---------------------------------------------------------------------------
203 // GC Support 114 // GC Support
204 115
205 void IncrementalMarkingRecordWriteHelper(Register object,
206 Register value,
207 Register address);
208
209 enum RememberedSetFinalAction { 116 enum RememberedSetFinalAction {
210 kReturnAtEnd, 117 kReturnAtEnd,
211 kFallThroughAtEnd 118 kFallThroughAtEnd
212 }; 119 };
213 120
214 // Record in the remembered set the fact that we have a pointer to new space 121 // Record in the remembered set the fact that we have a pointer to new space
215 // at the address pointed to by the addr register. Only works if addr is not 122 // at the address pointed to by the addr register. Only works if addr is not
216 // in new space. 123 // in new space.
217 void RememberedSetHelper(Register object, // Used for debug code. 124 void RememberedSetHelper(Register object, // Used for debug code.
218 Register addr, 125 Register addr,
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 // then we just fall through, since it is already live. If it is white and 166 // then we just fall through, since it is already live. If it is white and
260 // we can determine that it doesn't need to be scanned, then we just mark it 167 // we can determine that it doesn't need to be scanned, then we just mark it
261 // black and fall through. For the rest we jump to the label so the 168 // black and fall through. For the rest we jump to the label so the
262 // incremental marker can fix its assumptions. 169 // incremental marker can fix its assumptions.
263 void EnsureNotWhite(Register object, 170 void EnsureNotWhite(Register object,
264 Register scratch1, 171 Register scratch1,
265 Register scratch2, 172 Register scratch2,
266 Register scratch3, 173 Register scratch3,
267 Label* object_is_white_and_not_data); 174 Label* object_is_white_and_not_data);
268 175
269 // Detects conservatively whether an object is data-only, i.e. it does need to 176 // Check if object is in new space.
270 // be scanned by the garbage collector. 177 // scratch can be object itself, but it will be clobbered.
271 void JumpIfDataObject(Register value, 178 void InNewSpace(Register object,
272 Register scratch, 179 Register scratch,
273 Label* not_data_object); 180 // eq for "in new space?", ne for "not in new space?"
181 Condition cond,
182 Label* branch);
274 183
275 // Notify the garbage collector that we wrote a pointer into an object. 184 // Notify the garbage collector that we wrote a pointer into an object.
276 // |object| is the object being stored into, |value| is the object being 185 // |object| is the object being stored into, |value| is the object being
277 // stored. value and scratch registers are clobbered by the operation. 186 // stored. value and scratch registers are clobbered by the operation.
278 // The offset is the offset from the start of the object, not the offset from 187 // The offset is the offset from the start of the object, not the offset from
279 // the tagged HeapObject pointer. For use with FieldOperand(reg, off). 188 // the tagged HeapObject pointer. For use with FieldOperand(reg, off).
280 void RecordWriteField( 189 void RecordWriteField(
281 Register object, 190 Register object,
282 int offset, 191 int offset,
283 Register value, 192 Register value,
(...skipping 29 matching lines...) Expand all
313 // address registers are clobbered by the operation. 222 // address registers are clobbered by the operation.
314 void RecordWrite( 223 void RecordWrite(
315 Register object, 224 Register object,
316 Register address, 225 Register address,
317 Register value, 226 Register value,
318 LinkRegisterStatus lr_status, 227 LinkRegisterStatus lr_status,
319 SaveFPRegsMode save_fp, 228 SaveFPRegsMode save_fp,
320 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 229 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
321 SmiCheck smi_check = INLINE_SMI_CHECK); 230 SmiCheck smi_check = INLINE_SMI_CHECK);
322 231
323 // Push a handle. 232
324 void Push(Handle<Object> handle); 233 // Mark the register as dead. Put the pattern 0xFFFFFFDE into the register.
234 void Dead(Register dead) {
235 // Fit in a single SH4 mov_imm_ instruction
236 mov(dead, Operand(static_cast<int>(0xFFFFFFDE)));
237 }
238
239 // Mark up to four registers dead at a time.
240 void Dead(Register d1, Register d2, Register d3 = no_reg,
241 Register d4 = no_reg) {
242 Dead(d1);
243 Dead(d2);
244 if (d3.is_valid()) Dead(d3);
245 if (d4.is_valid()) Dead(d4);
246 }
247
248 void Push(Handle<Object> handle) { push(Operand(handle), sh4_ip); }
325 249
326 // Push two registers. Pushes leftmost register first (to highest address). 250 // Push two registers. Pushes leftmost register first (to highest address).
327 void Push(Register src1, Register src2, Condition cond = al) { 251 void Push(Register src1, Register src2) {
328 ASSERT(!src1.is(src2)); 252 ASSERT(!src1.is(src2));
329 if (src1.code() > src2.code()) { 253 push(src1);
330 stm(db_w, sp, src1.bit() | src2.bit(), cond); 254 push(src2);
331 } else {
332 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
333 str(src2, MemOperand(sp, 4, NegPreIndex), cond);
334 }
335 } 255 }
336 256
337 // Push three registers. Pushes leftmost register first (to highest address). 257 // Push three registers. Pushes leftmost register first (to highest address).
338 void Push(Register src1, Register src2, Register src3, Condition cond = al) { 258 void Push(Register src1, Register src2, Register src3) {
339 ASSERT(!src1.is(src2)); 259 ASSERT(!src1.is(src2));
340 ASSERT(!src2.is(src3)); 260 ASSERT(!src2.is(src3));
341 ASSERT(!src1.is(src3)); 261 ASSERT(!src1.is(src3));
342 if (src1.code() > src2.code()) { 262 push(src1);
343 if (src2.code() > src3.code()) { 263 push(src2);
344 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); 264 push(src3);
345 } else {
346 stm(db_w, sp, src1.bit() | src2.bit(), cond);
347 str(src3, MemOperand(sp, 4, NegPreIndex), cond);
348 }
349 } else {
350 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
351 Push(src2, src3, cond);
352 }
353 } 265 }
354 266
355 // Push four registers. Pushes leftmost register first (to highest address). 267 // Push four registers. Pushes leftmost register first (to highest address).
356 void Push(Register src1, 268 void Push(Register src1, Register src2,
357 Register src2, 269 Register src3, Register src4) {
358 Register src3,
359 Register src4,
360 Condition cond = al) {
361 ASSERT(!src1.is(src2)); 270 ASSERT(!src1.is(src2));
362 ASSERT(!src2.is(src3)); 271 ASSERT(!src2.is(src3));
363 ASSERT(!src1.is(src3)); 272 ASSERT(!src1.is(src3));
364 ASSERT(!src1.is(src4)); 273 ASSERT(!src1.is(src4));
365 ASSERT(!src2.is(src4)); 274 ASSERT(!src2.is(src4));
366 ASSERT(!src3.is(src4)); 275 ASSERT(!src3.is(src4));
367 if (src1.code() > src2.code()) { 276 push(src1);
368 if (src2.code() > src3.code()) { 277 push(src2);
369 if (src3.code() > src4.code()) { 278 push(src3);
370 stm(db_w, 279 push(src4);
371 sp,
372 src1.bit() | src2.bit() | src3.bit() | src4.bit(),
373 cond);
374 } else {
375 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
376 str(src4, MemOperand(sp, 4, NegPreIndex), cond);
377 }
378 } else {
379 stm(db_w, sp, src1.bit() | src2.bit(), cond);
380 Push(src3, src4, cond);
381 }
382 } else {
383 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
384 Push(src2, src3, src4, cond);
385 }
386 } 280 }
387 281
388 // Pop two registers. Pops rightmost register first (from lower address). 282 // Pop two registers. Pops rightmost register first (from lower address).
389 void Pop(Register src1, Register src2, Condition cond = al) { 283 void Pop(Register src1, Register src2) {
390 ASSERT(!src1.is(src2)); 284 ASSERT(!src1.is(src2));
391 if (src1.code() > src2.code()) { 285 pop(src2);
392 ldm(ia_w, sp, src1.bit() | src2.bit(), cond); 286 pop(src1);
393 } else {
394 ldr(src2, MemOperand(sp, 4, PostIndex), cond);
395 ldr(src1, MemOperand(sp, 4, PostIndex), cond);
396 }
397 } 287 }
398 288
399 // Pop three registers. Pops rightmost register first (from lower address). 289 // Pop three registers. Pops rightmost register first (from lower address).
400 void Pop(Register src1, Register src2, Register src3, Condition cond = al) { 290 void Pop(Register src1, Register src2, Register src3) {
401 ASSERT(!src1.is(src2)); 291 ASSERT(!src1.is(src2));
402 ASSERT(!src2.is(src3)); 292 ASSERT(!src2.is(src3));
403 ASSERT(!src1.is(src3)); 293 ASSERT(!src1.is(src3));
404 if (src1.code() > src2.code()) { 294 pop(src3);
405 if (src2.code() > src3.code()) { 295 pop(src2);
406 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); 296 pop(src1);
407 } else {
408 ldr(src3, MemOperand(sp, 4, PostIndex), cond);
409 ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
410 }
411 } else {
412 Pop(src2, src3, cond);
413 str(src1, MemOperand(sp, 4, PostIndex), cond);
414 }
415 } 297 }
416 298
417 // Pop four registers. Pops rightmost register first (from lower address). 299 // Pop four registers. Pops rightmost register first (from lower address).
418 void Pop(Register src1, 300 void Pop(Register src1, Register src2, Register src3, Register src4) {
419 Register src2,
420 Register src3,
421 Register src4,
422 Condition cond = al) {
423 ASSERT(!src1.is(src2)); 301 ASSERT(!src1.is(src2));
424 ASSERT(!src2.is(src3)); 302 ASSERT(!src2.is(src3));
425 ASSERT(!src1.is(src3)); 303 ASSERT(!src1.is(src3));
426 ASSERT(!src1.is(src4)); 304 ASSERT(!src1.is(src4));
427 ASSERT(!src2.is(src4)); 305 ASSERT(!src2.is(src4));
428 ASSERT(!src3.is(src4)); 306 ASSERT(!src3.is(src4));
429 if (src1.code() > src2.code()) { 307 pop(src4);
430 if (src2.code() > src3.code()) { 308 pop(src3);
431 if (src3.code() > src4.code()) { 309 pop(src2);
432 ldm(ia_w, 310 pop(src1);
433 sp,
434 src1.bit() | src2.bit() | src3.bit() | src4.bit(),
435 cond);
436 } else {
437 ldr(src4, MemOperand(sp, 4, PostIndex), cond);
438 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
439 }
440 } else {
441 Pop(src3, src4, cond);
442 ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
443 }
444 } else {
445 Pop(src2, src3, src4, cond);
446 ldr(src1, MemOperand(sp, 4, PostIndex), cond);
447 }
448 } 311 }
449 312
450 // Push and pop the registers that can hold pointers, as defined by the 313 // Push and pop the registers that can hold pointers, as defined by the
451 // RegList constant kSafepointSavedRegisters. 314 // RegList constant kSafepointSavedRegisters.
452 void PushSafepointRegisters(); 315 void PushSafepointRegisters();
453 void PopSafepointRegisters(); 316 void PopSafepointRegisters();
454 void PushSafepointRegistersAndDoubles(); 317 void PushSafepointRegistersAndDoubles();
455 void PopSafepointRegistersAndDoubles(); 318 void PopSafepointRegistersAndDoubles();
456 // Store value in register src in the safepoint stack slot for 319 // Store value in register src in the safepoint stack slot for
457 // register dst. 320 // register dst.
458 void StoreToSafepointRegisterSlot(Register src, Register dst); 321 void StoreToSafepointRegisterSlot(Register src, Register dst);
459 void StoreToSafepointRegistersAndDoublesSlot(Register src, Register dst); 322 void StoreToSafepointRegistersAndDoublesSlot(Register src, Register dst);
460 // Load the value of the src register from its safepoint stack slot 323 // Load the value of the src register from its safepoint stack slot
461 // into register dst. 324 // into register dst.
462 void LoadFromSafepointRegisterSlot(Register dst, Register src); 325 void LoadFromSafepointRegisterSlot(Register dst, Register src);
463 326
464 // Load two consecutive registers with two consecutive memory locations. 327 // Load two consecutive registers with two consecutive memory locations.
465 void Ldrd(Register dst1, 328 void Ldrd(Register dst1,
466 Register dst2, 329 Register dst2,
467 const MemOperand& src, 330 const MemOperand& src);
468 Condition cond = al);
469 331
470 // Store two consecutive registers to two consecutive memory locations. 332 // Store two consecutive registers to two consecutive memory locations.
471 void Strd(Register src1, 333 void Strd(Register src1,
472 Register src2, 334 Register src2,
473 const MemOperand& dst, 335 const MemOperand& dst);
474 Condition cond = al);
475 336
476 // Clear specified FPSCR bits. 337 void IsObjectJSStringType(Register object,
477 void ClearFPSCRBits(const uint32_t bits_to_clear, 338 Register scratch,
478 const Register scratch, 339 Label* fail);
479 const Condition cond = al);
480 340
481 // Compare double values and move the result to the normal condition flags. 341 #ifdef ENABLE_DEBUGGER_SUPPORT
482 void VFPCompareAndSetFlags(const DwVfpRegister src1, 342 // ---------------------------------------------------------------------------
483 const DwVfpRegister src2, 343 // Debugger Support
484 const Condition cond = al);
485 void VFPCompareAndSetFlags(const DwVfpRegister src1,
486 const double src2,
487 const Condition cond = al);
488 344
489 // Compare double values and then load the fpscr flags to a register. 345 void DebugBreak();
490 void VFPCompareAndLoadFlags(const DwVfpRegister src1, 346 #endif
491 const DwVfpRegister src2,
492 const Register fpscr_flags,
493 const Condition cond = al);
494 void VFPCompareAndLoadFlags(const DwVfpRegister src1,
495 const double src2,
496 const Register fpscr_flags,
497 const Condition cond = al);
498 347
499 void Vmov(const DwVfpRegister dst, 348 // ---------------------------------------------------------------------------
500 const double imm, 349 // Support for marking unimplemented code generator function
501 const Register scratch = no_reg, 350 // Should be called with UNIMPLEMENTED_BREAK define below.
502 const Condition cond = al); 351 void UnimplementedBreak(const char *file, int line);
352 #ifdef DEBUG
353 #define UNIMPLEMENTED_BREAK() UnimplementedBreak(__FILE__, __LINE__)
354 #else
355 #define UNIMPLEMENTED_BREAK() UnimplementedBreak("", 0)
356 #endif
357
358 // ---------------------------------------------------------------------------
359 // Activation frames
360
361 void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
362 void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
363
364 void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
365 void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
366
367 // Expects object in r0 and returns map with validated enum cache
368 // in r0. Assumes that any other register can be used as a scratch.
369 void CheckEnumCache(Register null_value, Label* call_runtime);
503 370
504 // Enter exit frame. 371 // Enter exit frame.
505 // stack_space - extra stack space, used for alignment before call to C. 372 // stack_space - extra stack space, used for alignment before call to C.
506 void EnterExitFrame(bool save_doubles, int stack_space = 0); 373 void EnterExitFrame(bool save_doubles, int stack_space = 0,
374 Register scratch = sh4_ip);
507 375
508 // Leave the current exit frame. Expects the return value in r0. 376 // Leave the current exit frame. Expects the return value in r0.
509 // Expect the number of values, pushed prior to the exit frame, to 377 // Expect the number of values, pushed prior to the exit frame, to
510 // remove in a register (or no_reg, if there is nothing to remove). 378 // remove in a register (or no_reg, if there is nothing to remove).
511 void LeaveExitFrame(bool save_doubles, Register argument_count); 379 void LeaveExitFrame(bool save_doubles, Register argument_count);
512 380
513 // Get the actual activation frame alignment for target environment. 381 void LoadContext(Register dst, int context_chain_length);
514 static int ActivationFrameAlignment();
515 382
516 void LoadContext(Register dst, int context_chain_length);
517 383
518 // Conditionally load the cached Array transitioned map of type 384 // Conditionally load the cached Array transitioned map of type
519 // transitioned_kind from the native context if the map in register 385 // transitioned_kind from the native context if the map in register
520 // map_in_out is the cached Array map in the native context of 386 // map_in_out is the cached Array map in the native context of
521 // expected_kind. 387 // expected_kind.
522 void LoadTransitionedArrayMapConditional( 388 void LoadTransitionedArrayMapConditional(
523 ElementsKind expected_kind, 389 ElementsKind expected_kind,
524 ElementsKind transitioned_kind, 390 ElementsKind transitioned_kind,
525 Register map_in_out, 391 Register map_in_out,
526 Register scratch, 392 Register scratch,
527 Label* no_map_match); 393 Label* no_map_match);
528 394
529 // Load the initial map for new Arrays from a JSFunction. 395 // Load the initial map for new Arrays from a JSFunction.
530 void LoadInitialArrayMap(Register function_in, 396 void LoadInitialArrayMap(Register function_in,
531 Register scratch, 397 Register scratch,
532 Register map_out, 398 Register map_out,
533 bool can_have_holes); 399 bool can_have_holes);
534 400
535 void LoadGlobalFunction(int index, Register function); 401 void LoadGlobalFunction(int index, Register function);
536 402
537 // Load the initial map from the global function. The registers 403 // Load the initial map from the global function. The registers
538 // function and map can be the same, function is then overwritten. 404 // function and map can be the same, function is then overwritten.
539 void LoadGlobalFunctionInitialMap(Register function, 405 void LoadGlobalFunctionInitialMap(Register function,
540 Register map, 406 Register map,
541 Register scratch); 407 Register scratch);
542 408
543 void InitializeRootRegister() { 409 void InitializeRootRegister() {
544 ExternalReference roots_array_start = 410 ExternalReference roots_array_start =
545 ExternalReference::roots_array_start(isolate()); 411 ExternalReference::roots_array_start(isolate());
546 mov(kRootRegister, Operand(roots_array_start)); 412 mov(roots, Operand(roots_array_start));
547 } 413 }
548 414
549 // --------------------------------------------------------------------------- 415 // ---------------------------------------------------------------------------
550 // JavaScript invokes 416 // JavaScript invokes
551 417
552 // Set up call kind marking in ecx. The method takes ecx as an 418 // Set up call kind marking in ecx. The method takes ecx as an
553 // explicit first parameter to make the code more readable at the 419 // explicit first parameter to make the code more readable at the
554 // call sites. 420 // call sites.
555 void SetCallKind(Register dst, CallKind kind); 421 void SetCallKind(Register dst, CallKind kind);
556 422
(...skipping 19 matching lines...) Expand all
576 InvokeFlag flag, 442 InvokeFlag flag,
577 const CallWrapper& call_wrapper, 443 const CallWrapper& call_wrapper,
578 CallKind call_kind); 444 CallKind call_kind);
579 445
580 void InvokeFunction(Handle<JSFunction> function, 446 void InvokeFunction(Handle<JSFunction> function,
581 const ParameterCount& actual, 447 const ParameterCount& actual,
582 InvokeFlag flag, 448 InvokeFlag flag,
583 const CallWrapper& call_wrapper, 449 const CallWrapper& call_wrapper,
584 CallKind call_kind); 450 CallKind call_kind);
585 451
452 // Expression support
453 void Set(Register dst, const Operand& x);
454 void Set(const Operand& dst, const Operand& x);
455
456 // Compare object type for heap object.
457 // Incoming register is heap_object and outgoing register is map.
458 void CmpObjectType(Register heap_object, InstanceType type, Register map);
459
460 // Compare instance type for map.
461 void CmpInstanceType(Register map, InstanceType type);
462
463 // Check if the map of an object is equal to a specified map and branch to a
464 // specified target if equal. Skip the smi check if not required (object is
465 // known to be a heap object)
466 void DispatchMap(Register obj,
467 Register scratch,
468 Handle<Map> map,
469 Handle<Code> success,
470 SmiCheckType smi_check_type);
471
472 // Compare the object in a register to a value from the root list.
473 // Uses the ip register as scratch.
474 void CompareRoot(Register obj, Heap::RootListIndex index);
475
476 // Check if a heap object's type is in the JSObject range, not including
477 // JSFunction. The object's map will be loaded in the map register.
478 // Any or all of the three registers may be the same.
479 // The contents of the scratch register will always be overwritten.
586 void IsObjectJSObjectType(Register heap_object, 480 void IsObjectJSObjectType(Register heap_object,
587 Register map, 481 Register map,
588 Register scratch, 482 Register scratch,
589 Label* fail); 483 Label* fail);
590 484
591 void IsInstanceJSObjectType(Register map, 485 // The contents of the scratch register will be overwritten.
592 Register scratch, 486 void IsInstanceJSObjectType(Register map, Register scratch, Label* fail);
593 Label* fail);
594 487
595 void IsObjectJSStringType(Register object, 488 // ---------------------------------------------------------------------------
596 Register scratch, 489 // String utilities
597 Label* fail);
598 490
599 #ifdef ENABLE_DEBUGGER_SUPPORT 491 // Checks if both objects are sequential ASCII strings and jumps to label
492 // if either is not. Assumes that neither object is a smi.
493 void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1,
494 Register object2,
495 Register scratch1,
496 Register scratch2,
497 Label* failure);
498
499 // Checks if both objects are sequential ASCII strings and jumps to label
500 // if either is not.
501 void JumpIfNotBothSequentialAsciiStrings(Register first,
502 Register second,
503 Register scratch1,
504 Register scratch2,
505 Label* not_flat_ascii_strings);
506
507 // Checks if both instance types are sequential ASCII strings and jumps to
508 // label if either is not.
509 void JumpIfBothInstanceTypesAreNotSequentialAscii(
510 Register first_object_instance_type,
511 Register second_object_instance_type,
512 Register scratch1,
513 Register scratch2,
514 Label* failure);
515
516 // Check if instance type is sequential ASCII string and jump to label if
517 // it is not.
518 void JumpIfInstanceTypeIsNotSequentialAscii(Register type,
519 Register scratch,
520 Label* failure);
521
522 // Abort execution if argument is not a number. Used in debug code.
523 void AbortIfNotNumber(Register object);
524
525 // Abort execution if argument is not a smi. Used in debug code.
526 void AbortIfNotSmi(Register object);
527
528 // Abort execution if argument is a smi. Used in debug code.
529 void AbortIfSmi(Register object);
530
531 // Abort execution if argument is a string. Used in debug code.
532 void AbortIfNotString(Register object);
533
534 // Abort execution if argument is not the root value with the given index.
535 void AbortIfNotRootValue(Register src,
536 Heap::RootListIndex root_value_index,
537 const char* message);
538
539 // Prints the value of the register to stdout. Use for debug only.
540 void PrintRegisterValue(Register reg);
541
600 // --------------------------------------------------------------------------- 542 // ---------------------------------------------------------------------------
601 // Debugger Support 543 // Patching helpers.
602 544
603 void DebugBreak(); 545 // Get the location of a relocated constant (its address in the constant pool)
604 #endif 546 // from its load site.
547 void GetRelocatedValueLocation(Register ldr_location,
548 Register result);
549
550 void LoadInstanceDescriptors(Register map,
551 Register descriptors,
552 Register scratch);
553 void EnumLength(Register dst, Register map);
554 void NumberOfOwnDescriptors(Register dst, Register map);
555
556 template<typename Field>
557 void DecodeField(Register reg) {
558 static const int shift = Field::kShift;
559 static const int mask = (Field::kMask >> shift) << kSmiTagSize;
560 lsr(reg, reg, Operand(shift));
561 land(reg, reg, Operand(mask));
562 }
563
564
565
566 // ---------------------------------------------------------------------------
567 // HeapNumber utilities
568
569 void JumpIfNotHeapNumber(Register object,
570 Register heap_number_map,
571 Register scratch,
572 Label* on_not_heap_number);
573
605 574
606 // --------------------------------------------------------------------------- 575 // ---------------------------------------------------------------------------
607 // Exception handling 576 // Exception handling
608 577
609 // Push a new try handler and link into try handler chain. 578 // Push a new try handler and link into try handler chain.
610 void PushTryHandler(StackHandler::Kind kind, int handler_index); 579 void PushTryHandler(StackHandler::Kind kind, int handler_index);
611 580
612 // Unlink the stack handler on top of the stack from the try handler chain. 581 // Unlink the stack handler on top of the stack from the try handler chain.
613 // Must preserve the result register. 582 // Must preserve the result register.
614 void PopTryHandler(); 583 void PopTryHandler();
615 584
616 // Passes thrown value to the handler of top of the try handler chain. 585 // Activate the top handler in the try hander chain.
617 void Throw(Register value); 586 void Throw(Register value);
618 587
619 // Propagates an uncatchable exception to the top of the current JS stack's 588 // Propagates an uncatchable exception to the top of the current JS stack's
620 // handler chain. 589 // handler chain.
621 void ThrowUncatchable(Register value); 590 void ThrowUncatchable(Register value);
622 591
623 // --------------------------------------------------------------------------- 592 // ---------------------------------------------------------------------------
624 // Inline caching support 593 // Inline caching support
625 594
626 // Generate code for checking access rights - used for security checks 595 // Generate code for checking access rights - used for security checks
627 // on access to global objects across environments. The holder register 596 // on access to global objects across environments. The holder register
628 // is left untouched, whereas both scratch registers are clobbered. 597 // is left untouched, whereas both scratch registers are clobbered.
629 void CheckAccessGlobalProxy(Register holder_reg, 598 void CheckAccessGlobalProxy(Register holder_reg,
630 Register scratch, 599 Register scratch,
631 Label* miss); 600 Label* miss);
632 601
633 void GetNumberHash(Register t0, Register scratch); 602 void GetNumberHash(Register t0, Register scratch);
634 603
635 void LoadFromNumberDictionary(Label* miss, 604 void LoadFromNumberDictionary(Label* miss,
636 Register elements, 605 Register elements,
637 Register key, 606 Register key,
638 Register result, 607 Register result,
639 Register t0, 608 Register t0,
640 Register t1, 609 Register t1,
641 Register t2); 610 Register t2);
642 611
643
644 inline void MarkCode(NopMarkerTypes type) {
645 nop(type);
646 }
647
648 // Check if the given instruction is a 'type' marker.
649 // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type))
650 // These instructions are generated to mark special location in the code,
651 // like some special IC code.
652 static inline bool IsMarkedCode(Instr instr, int type) {
653 ASSERT((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
654 return IsNop(instr, type);
655 }
656
657
658 static inline int GetCodeMarker(Instr instr) {
659 int dst_reg_offset = 12;
660 int dst_mask = 0xf << dst_reg_offset;
661 int src_mask = 0xf;
662 int dst_reg = (instr & dst_mask) >> dst_reg_offset;
663 int src_reg = instr & src_mask;
664 uint32_t non_register_mask = ~(dst_mask | src_mask);
665 uint32_t mov_mask = al | 13 << 21;
666
667 // Return <n> if we have a mov rn rn, else return -1.
668 int type = ((instr & non_register_mask) == mov_mask) &&
669 (dst_reg == src_reg) &&
670 (FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER)
671 ? src_reg
672 : -1;
673 ASSERT((type == -1) ||
674 ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
675 return type;
676 }
677
678
679 // --------------------------------------------------------------------------- 612 // ---------------------------------------------------------------------------
680 // Allocation support 613 // Allocation support
681 614
682 // Allocate an object in new space. The object_size is specified 615 // Allocate an object in new space. If the new space is exhausted control
683 // either in bytes or in words if the allocation flag SIZE_IN_WORDS 616 // continues at the gc_required label. The allocated object is returned in
684 // is passed. If the new space is exhausted control continues at the 617 // result and end of the new object is returned in result_end. The register
685 // gc_required label. The allocated object is returned in result. If 618 // scratch can be passed as no_reg in which case an additional object
686 // the flag tag_allocated_object is true the result is tagged as as 619 // reference will be added to the reloc info. The returned pointers in result
687 // a heap object. All registers are clobbered also when control 620 // and result_end have not yet been tagged as heap objects. If
688 // continues at the gc_required label. 621 // result_contains_top_on_entry is true the content of result is known to be
622 // the allocation top on entry (could be result_end from a previous call to
623 // AllocateInNewSpace). If result_contains_top_on_entry is true scratch
624 // should be no_reg as it is never used.
689 void AllocateInNewSpace(int object_size, 625 void AllocateInNewSpace(int object_size,
690 Register result, 626 Register result,
691 Register scratch1, 627 Register result_end,
692 Register scratch2, 628 Register scratch,
693 Label* gc_required,
694 AllocationFlags flags);
695 void AllocateInNewSpace(Register object_size,
696 Register result,
697 Register scratch1,
698 Register scratch2,
699 Label* gc_required, 629 Label* gc_required,
700 AllocationFlags flags); 630 AllocationFlags flags);
701 631
632 void AllocateInNewSpace(int header_size,
633 ScaleFactor element_size,
634 Register element_count,
635 Register result,
636 Register result_end,
637 Register scratch,
638 Label* gc_required,
639 AllocationFlags flags);
640
641 void AllocateInNewSpace(Register object_size,
642 Register result,
643 Register result_end,
644 Register scratch,
645 Label* gc_required,
646 AllocationFlags flags);
647
702 // Undo allocation in new space. The object passed and objects allocated after 648 // Undo allocation in new space. The object passed and objects allocated after
703 // it will no longer be allocated. The caller must make sure that no pointers 649 // it will no longer be allocated. The caller must make sure that no pointers
704 // are left to the object(s) no longer allocated as they would be invalid when 650 // are left to the object(s) no longer allocated as they would be invalid when
705 // allocation is undone. 651 // allocation is undone.
706 void UndoAllocationInNewSpace(Register object, Register scratch); 652 void UndoAllocationInNewSpace(Register object, Register scratch);
707 653
708 654
655 // Allocate a heap number in new space with undefined value. The
656 // register scratch2 can be passed as no_reg; the others must be
657 // valid registers. Returns tagged pointer in result register, or
658 // jumps to gc_required if new space is full.
659 void AllocateHeapNumber(Register result,
660 Register scratch1,
661 Register scratch2,
662 Register heap_number_map,
663 Label* gc_required);
664
665 // Allocate a sequential string. All the header fields of the string object
666 // are initialized.
709 void AllocateTwoByteString(Register result, 667 void AllocateTwoByteString(Register result,
710 Register length, 668 Register length,
711 Register scratch1, 669 Register scratch1,
712 Register scratch2, 670 Register scratch2,
713 Register scratch3, 671 Register scratch3,
714 Label* gc_required); 672 Label* gc_required);
715 void AllocateAsciiString(Register result, 673 void AllocateAsciiString(Register result,
716 Register length, 674 Register length,
717 Register scratch1, 675 Register scratch1,
718 Register scratch2, 676 Register scratch2,
719 Register scratch3, 677 Register scratch3,
720 Label* gc_required); 678 Label* gc_required);
679 void AllocateAsciiString(Register result,
680 int length,
681 Register scratch1,
682 Register scratch2,
683 Label* gc_required);
684
685 // Allocate a raw cons string object. Only the map field of the result is
686 // initialized.
721 void AllocateTwoByteConsString(Register result, 687 void AllocateTwoByteConsString(Register result,
722 Register length, 688 Register length,
723 Register scratch1, 689 Register scratch1,
724 Register scratch2, 690 Register scratch2,
725 Label* gc_required); 691 Label* gc_required);
692
726 void AllocateAsciiConsString(Register result, 693 void AllocateAsciiConsString(Register result,
727 Register length, 694 Register length,
728 Register scratch1, 695 Register scratch1,
729 Register scratch2, 696 Register scratch2,
730 Label* gc_required); 697 Label* gc_required);
731 void AllocateTwoByteSlicedString(Register result, 698 void AllocateTwoByteSlicedString(Register result,
732 Register length, 699 Register length,
733 Register scratch1, 700 Register scratch1,
734 Register scratch2, 701 Register scratch2,
735 Label* gc_required); 702 Label* gc_required);
736 void AllocateAsciiSlicedString(Register result, 703 void AllocateAsciiSlicedString(Register result,
737 Register length, 704 Register length,
738 Register scratch1, 705 Register scratch1,
739 Register scratch2, 706 Register scratch2,
740 Label* gc_required); 707 Label* gc_required);
741 708
742 // Allocates a heap number or jumps to the gc_required label if the young
743 // space is full and a scavenge is needed. All registers are clobbered also
744 // when control continues at the gc_required label.
745 void AllocateHeapNumber(Register result,
746 Register scratch1,
747 Register scratch2,
748 Register heap_number_map,
749 Label* gc_required,
750 TaggingMode tagging_mode = TAG_RESULT);
751 void AllocateHeapNumberWithValue(Register result,
752 DwVfpRegister value,
753 Register scratch1,
754 Register scratch2,
755 Register heap_number_map,
756 Label* gc_required);
757
758 // Copies a fixed number of fields of heap objects from src to dst. 709 // Copies a fixed number of fields of heap objects from src to dst.
759 void CopyFields(Register dst, Register src, RegList temps, int field_count); 710 void CopyFields(Register dst, Register src, RegList temps, int field_count);
760 711
761 // Copies a number of bytes from src to dst. All registers are clobbered. On 712 // Copy memory, byte-by-byte, from source to destination. Not optimized for
762 // exit src and dst will point to the place just after where the last byte was 713 // long or aligned copies.
763 // read or written and length will be zero. 714 // The contents of index and scratch are destroyed.
764 void CopyBytes(Register src, 715 void CopyBytes(Register source,
765 Register dst, 716 Register destination,
766 Register length, 717 Register length,
767 Register scratch); 718 Register scratch);
768 719
769 // Initialize fields with filler values. Fields starting at |start_offset| 720 // Initialize fields with filler values. Fields starting at |start_offset|
770 // not including end_offset are overwritten with the value in |filler|. At 721 // not including end_offset are overwritten with the value in |filler|. At
771 // the end the loop, |start_offset| takes the value of |end_offset|. 722 // the end the loop, |start_offset| takes the value of |end_offset|.
772 void InitializeFieldsWithFiller(Register start_offset, 723 void InitializeFieldsWithFiller(Register start_offset,
773 Register end_offset, 724 Register end_offset,
774 Register filler); 725 Register filler);
775 726
(...skipping 14 matching lines...) Expand all
790 // Compare object type for heap object. heap_object contains a non-Smi 741 // Compare object type for heap object. heap_object contains a non-Smi
791 // whose object type should be compared with the given type. This both 742 // whose object type should be compared with the given type. This both
792 // sets the flags and leaves the object type in the type_reg register. 743 // sets the flags and leaves the object type in the type_reg register.
793 // It leaves the map in the map register (unless the type_reg and map register 744 // It leaves the map in the map register (unless the type_reg and map register
794 // are the same register). It leaves the heap object in the heap_object 745 // are the same register). It leaves the heap object in the heap_object
795 // register unless the heap_object register is the same register as one of the 746 // register unless the heap_object register is the same register as one of the
796 // other registers. 747 // other registers.
797 void CompareObjectType(Register heap_object, 748 void CompareObjectType(Register heap_object,
798 Register map, 749 Register map,
799 Register type_reg, 750 Register type_reg,
800 InstanceType type); 751 InstanceType type,
752 Condition cond);
801 753
802 // Compare instance type in a map. map contains a valid map object whose 754 // Compare instance type in a map. map contains a valid map object whose
803 // object type should be compared with the given type. This both 755 // object type should be compared with the given type. This both
804 // sets the flags and leaves the object type in the type_reg register. 756 // sets the flags and leaves the object type in the type_reg register. It
757 // leaves the heap object in the heap_object register unless the heap_object
758 // register is the same register as type_reg.
805 void CompareInstanceType(Register map, 759 void CompareInstanceType(Register map,
806 Register type_reg, 760 Register type_reg,
807 InstanceType type); 761 InstanceType type,
808 762 Condition cond);
809 763
810 // Check if a map for a JSObject indicates that the object has fast elements. 764 // Check if a map for a JSObject indicates that the object has fast elements.
811 // Jump to the specified label if it does not. 765 // Jump to the specified label if it does not.
812 void CheckFastElements(Register map, 766 void CheckFastElements(Register map,
813 Register scratch, 767 Register scratch,
814 Label* fail); 768 Label* fail);
815 769
816 // Check if a map for a JSObject indicates that the object can have both smi 770 // Check if a map for a JSObject indicates that the object can have both smi
817 // and HeapObject elements. Jump to the specified label if it does not. 771 // and HeapObject elements. Jump to the specified label if it does not.
818 void CheckFastObjectElements(Register map, 772 void CheckFastObjectElements(Register map,
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
869 CompareMapMode mode = REQUIRE_EXACT_MAP); 823 CompareMapMode mode = REQUIRE_EXACT_MAP);
870 824
871 825
872 void CheckMap(Register obj, 826 void CheckMap(Register obj,
873 Register scratch, 827 Register scratch,
874 Heap::RootListIndex index, 828 Heap::RootListIndex index,
875 Label* fail, 829 Label* fail,
876 SmiCheckType smi_check_type); 830 SmiCheckType smi_check_type);
877 831
878 832
879 // Check if the map of an object is equal to a specified map and branch to a
880 // specified target if equal. Skip the smi check if not required (object is
881 // known to be a heap object)
882 void DispatchMap(Register obj,
883 Register scratch,
884 Handle<Map> map,
885 Handle<Code> success,
886 SmiCheckType smi_check_type);
887
888
889 // Compare the object in a register to a value from the root list.
890 // Uses the ip register as scratch.
891 void CompareRoot(Register obj, Heap::RootListIndex index);
892
893 833
894 // Load and check the instance type of an object for being a string. 834 // Load and check the instance type of an object for being a string.
895 // Loads the type into the second argument register. 835 // Loads the type into the second argument register.
896 // Returns a condition that will be enabled if the object was a string. 836 // Returns a condition that will be enabled if the object was a string.
897 Condition IsObjectStringType(Register obj, 837 Condition IsObjectStringType(Register obj,
898 Register type) { 838 Register type) {
899 ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset)); 839 ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset));
900 ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset)); 840 ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset));
901 tst(type, Operand(kIsNotStringMask)); 841 tst(type, Operand(kIsNotStringMask));
902 ASSERT_EQ(0, kStringTag); 842 ASSERT_EQ(0, kStringTag);
903 return eq; 843 return eq;
904 } 844 }
905 845
906 846
907 // Generates code for reporting that an illegal operation has 847 // Generates code for reporting that an illegal operation has
908 // occurred. 848 // occurred.
909 void IllegalOperation(int num_arguments); 849 void IllegalOperation(int num_arguments);
910 850
911 // Picks out an array index from the hash field. 851 // Picks out an array index from the hash field.
912 // Register use: 852 // Register use:
913 // hash - holds the index's hash. Clobbered. 853 // hash - holds the index's hash. Clobbered.
914 // index - holds the overwritten index on exit. 854 // index - holds the overwritten index on exit.
915 void IndexFromHash(Register hash, Register index); 855 void IndexFromHash(Register hash, Register index);
916 856
917 // Get the number of least significant bits from a register 857 // Get the number of least significant bits from a register
918 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits); 858 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
919 void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits); 859 void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits);
920 860
921 // Uses VFP instructions to Convert a Smi to a double.
922 void IntegerToDoubleConversionWithVFP3(Register inReg,
923 Register outHighReg,
924 Register outLowReg);
925
926 // Load the value of a number object into a VFP double register. If the object
927 // is not a number a jump to the label not_number is performed and the VFP
928 // double register is unchanged.
929 void ObjectToDoubleVFPRegister(
930 Register object,
931 DwVfpRegister value,
932 Register scratch1,
933 Register scratch2,
934 Register heap_number_map,
935 SwVfpRegister scratch3,
936 Label* not_number,
937 ObjectToDoubleFlags flags = NO_OBJECT_TO_DOUBLE_FLAGS);
938
939 // Load the value of a smi object into a VFP double register. The register
940 // scratch1 can be the same register as smi in which case smi will hold the
941 // untagged value afterwards.
942 void SmiToDoubleVFPRegister(Register smi,
943 DwVfpRegister value,
944 Register scratch1,
945 SwVfpRegister scratch2);
946
947 // Convert the HeapNumber pointed to by source to a 32bits signed integer 861 // Convert the HeapNumber pointed to by source to a 32bits signed integer
948 // dest. If the HeapNumber does not fit into a 32bits signed integer branch 862 // dest. If the HeapNumber does not fit into a 32bits signed integer branch
949 // to not_int32 label. If VFP3 is available double_scratch is used but not 863 // to not_int32 label. If VFP3 is available double_scratch is used but not
950 // scratch2. 864 // scratch2. TODO: SH4, use fp reg.
951 void ConvertToInt32(Register source, 865 void ConvertToInt32(Register source,
952 Register dest, 866 Register dest,
953 Register scratch, 867 Register scratch,
954 Register scratch2, 868 Register scratch2,
955 DwVfpRegister double_scratch, 869 DwVfpRegister double_scratch,
956 Label *not_int32); 870 Label *not_int32);
957 871
958 // Truncates a double using a specific rounding mode, and writes the value 872 // Load the value of a smi object into a FPU double register. The register
959 // to the result register. 873 // scratch1 can be the same register as smi in which case smi will hold the
874 // untagged value afterwards.
875 void SmiToDoubleFPURegister(Register smi,
876 DwVfpRegister value,
877 Register scratch1);
878
879
880
881 // Truncates a double using a specific rounding mode.
960 // Clears the z flag (ne condition) if an overflow occurs. 882 // Clears the z flag (ne condition) if an overflow occurs.
961 // If kCheckForInexactConversion is passed, the z flag is also cleared if the 883 // If exact_conversion is true, the z flag is also cleared if the conversion
962 // conversion was inexact, i.e. if the double value could not be converted 884 // was inexact, ie. if the double value could not be converted exactly
963 // exactly to a 32-bit integer. 885 // to a 32bit integer.
964 void EmitVFPTruncate(VFPRoundingMode rounding_mode, 886 void EmitFPUTruncate(FPURoundingMode rounding_mode,
965 Register result, 887 Register result,
966 DwVfpRegister double_input, 888 DwVfpRegister double_input,
967 Register scratch, 889 Register scratch,
968 DwVfpRegister double_scratch,
969 CheckForInexactConversion check 890 CheckForInexactConversion check
970 = kDontCheckForInexactConversion); 891 = kDontCheckForInexactConversion);
971 892
972 // Helper for EmitECMATruncate. 893 // Helper for EmitECMATruncate.
973 // This will truncate a floating-point value outside of the signed 32bit 894 // This will truncate a floating-point value outside of the singed 32bit
974 // integer range to a 32bit signed integer. 895 // integer range to a 32bit signed integer.
975 // Expects the double value loaded in input_high and input_low. 896 // Expects the double value loaded in input_high and input_low.
976 // Exits with the answer in 'result'. 897 // Exits with the answer in 'result'.
977 // Note that this code does not work for values in the 32bit range! 898 // Note that this code does not work for values in the 32bit range!
978 void EmitOutOfInt32RangeTruncate(Register result, 899 void EmitOutOfInt32RangeTruncate(Register result,
979 Register input_high, 900 Register input_high,
980 Register input_low, 901 Register input_low,
981 Register scratch); 902 Register scratch);
982 903
983 // Performs a truncating conversion of a floating point number as used by 904 // Performs a truncating conversion of a floating point number as used by
(...skipping 12 matching lines...) Expand all
996 // the source is clobbered. Source and zeros can also be the same in which 917 // the source is clobbered. Source and zeros can also be the same in which
997 // case scratch should be a different register. 918 // case scratch should be a different register.
998 void CountLeadingZeros(Register zeros, 919 void CountLeadingZeros(Register zeros,
999 Register source, 920 Register source,
1000 Register scratch); 921 Register scratch);
1001 922
1002 // --------------------------------------------------------------------------- 923 // ---------------------------------------------------------------------------
1003 // Runtime calls 924 // Runtime calls
1004 925
1005 // Call a code stub. 926 // Call a code stub.
1006 void CallStub(CodeStub* stub, Condition cond = al); 927 void CallStub(CodeStub* stub);
1007 928
1008 // Call a code stub. 929 // Call a code stub.
1009 void TailCallStub(CodeStub* stub, Condition cond = al); 930 void TailCallStub(CodeStub* stub);
1010 931
1011 // Call a runtime routine. 932 // Call a runtime routine.
1012 void CallRuntime(const Runtime::Function* f, int num_arguments); 933 void CallRuntime(const Runtime::Function* f, int num_arguments);
1013 void CallRuntimeSaveDoubles(Runtime::FunctionId id); 934 void CallRuntimeSaveDoubles(Runtime::FunctionId id);
1014 935
1015 // Convenience function: Same as above, but takes the fid instead. 936 // Convenience function: Same as above, but takes the fid instead.
1016 void CallRuntime(Runtime::FunctionId fid, int num_arguments); 937 void CallRuntime(Runtime::FunctionId fid, int num_arguments);
1017 938
1018 // Convenience function: call an external reference. 939 // Convenience function: call an external reference.
1019 void CallExternalReference(const ExternalReference& ext, 940 void CallExternalReference(const ExternalReference& ext,
(...skipping 23 matching lines...) Expand all
1043 // Some compilers/platforms require the stack to be aligned when calling 964 // Some compilers/platforms require the stack to be aligned when calling
1044 // C++ code. 965 // C++ code.
1045 // Needs a scratch register to do some arithmetic. This register will be 966 // Needs a scratch register to do some arithmetic. This register will be
1046 // trashed. 967 // trashed.
1047 void PrepareCallCFunction(int num_reg_arguments, 968 void PrepareCallCFunction(int num_reg_arguments,
1048 int num_double_registers, 969 int num_double_registers,
1049 Register scratch); 970 Register scratch);
1050 void PrepareCallCFunction(int num_reg_arguments, 971 void PrepareCallCFunction(int num_reg_arguments,
1051 Register scratch); 972 Register scratch);
1052 973
1053 // There are two ways of passing double arguments on ARM, depending on
1054 // whether soft or hard floating point ABI is used. These functions
1055 // abstract parameter passing for the three different ways we call
1056 // C functions from generated code.
1057 void SetCallCDoubleArguments(DoubleRegister dreg);
1058 void SetCallCDoubleArguments(DoubleRegister dreg1, DoubleRegister dreg2);
1059 void SetCallCDoubleArguments(DoubleRegister dreg, Register reg);
1060
1061 // Calls a C function and cleans up the space for arguments allocated 974 // Calls a C function and cleans up the space for arguments allocated
1062 // by PrepareCallCFunction. The called function is not allowed to trigger a 975 // by PrepareCallCFunction. The called function is not allowed to trigger a
1063 // garbage collection, since that might move the code and invalidate the 976 // garbage collection, since that might move the code and invalidate the
1064 // return address (unless this is somehow accounted for by the called 977 // return address (unless this is somehow accounted for by the called
1065 // function). 978 // function).
1066 void CallCFunction(ExternalReference function, int num_arguments); 979 void CallCFunction(ExternalReference function, int num_reg_arguments,
980 int num_double_arguments = 0);
1067 void CallCFunction(Register function, int num_arguments); 981 void CallCFunction(Register function, int num_arguments);
1068 void CallCFunction(ExternalReference function,
1069 int num_reg_arguments,
1070 int num_double_arguments);
1071 void CallCFunction(Register function,
1072 int num_reg_arguments,
1073 int num_double_arguments);
1074
1075 void GetCFunctionDoubleResult(const DoubleRegister dst);
1076 982
1077 // Calls an API function. Allocates HandleScope, extracts returned value 983 // Calls an API function. Allocates HandleScope, extracts returned value
1078 // from handle and propagates exceptions. Restores context. stack_space 984 // from handle and propagates exceptions. Restores context. stack_space
1079 // - space to be unwound on exit (includes the call JS arguments space and 985 // - space to be unwound on exit (includes the call JS arguments space and
1080 // the additional space allocated for the fast call). 986 // the additional space allocated for the fast call).
1081 void CallApiFunctionAndReturn(ExternalReference function, int stack_space); 987 void CallApiFunctionAndReturn(ExternalReference function, int stack_space);
1082 988
1083 // Jump to a runtime routine. 989 // Jump to a runtime routine.
1084 void JumpToExternalReference(const ExternalReference& builtin); 990 void JumpToExternalReference(const ExternalReference& builtin);
1085 991
1086 // Invoke specified builtin JavaScript function. Adds an entry to 992 // Invoke specified builtin JavaScript function. Adds an entry to
1087 // the unresolved list if the name does not resolve. 993 // the unresolved list if the name does not resolve.
1088 void InvokeBuiltin(Builtins::JavaScript id, 994 void InvokeBuiltin(Builtins::JavaScript id,
1089 InvokeFlag flag, 995 InvokeFlag flag,
1090 const CallWrapper& call_wrapper = NullCallWrapper()); 996 const CallWrapper& call_wrapper = NullCallWrapper());
1091 997
1092 // Store the code object for the given builtin in the target register and 998 // Store the code object for the given builtin in the target register and
1093 // setup the function in r1. 999 // setup the function in r1.
1094 void GetBuiltinEntry(Register target, Builtins::JavaScript id); 1000 void GetBuiltinEntry(Register target, Builtins::JavaScript id);
1095 1001
1096 // Store the function for the given builtin in the target register. 1002 // Store the function for the given builtin in the target register.
1097 void GetBuiltinFunction(Register target, Builtins::JavaScript id); 1003 void GetBuiltinFunction(Register target, Builtins::JavaScript id);
1098 1004
1005 // ---------------------------------------------------------------------------
1006 // Utilities
1007
1008 void Ret(Condition cond = al);
1009
1010 void Drop(int stack_elements);
1011 void Ret(int drop);
1012
1013 void Jump(Register target);
1014 void Jump(intptr_t target, RelocInfo::Mode rmode);
1015 void Jump(Handle<Code> code, RelocInfo::Mode rmode);
1016 void Call(Label* target) { call(target); }
1017 void Call(Handle<Code> code,
1018 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
1019 TypeFeedbackId ast_id = TypeFeedbackId::None());
1020
1021 // Emit call to the code we are currently generating.
1022 void CallSelf() {
1023 UNIMPLEMENTED();
1024 }
1025
1026 void Move(Register dst, Handle<Object> value);
1027 // Move if the registers are not identical.
1028 void Move(Register target, Register source);
1029
1030 void Usat(Register dst, int satpos, Register src);
1031 void Ubfx(Register dst, Register src, int lsb, int width);
1032 void Sbfx(Register dst, Register src, int lsb, int width);
1033 void Bfc(Register dst, int lsb, int width);
1034 // scratch can be the same register as src (in which case it is trashed), but
1035 // not the same as dst.
1036 void Bfi(Register dst,
1037 Register src,
1038 Register scratch,
1039 int lsb,
1040 int width);
1041
1099 Handle<Object> CodeObject() { 1042 Handle<Object> CodeObject() {
1100 ASSERT(!code_object_.is_null()); 1043 ASSERT(!code_object_.is_null());
1101 return code_object_; 1044 return code_object_;
1102 } 1045 }
1103 1046
1047 // Record code generator line mapping through comments.
1048 // Use -code_comments to enable.
1049 MacroAssembler* RecordFunctionLine(const char* function, int line);
1104 1050
1105 // --------------------------------------------------------------------------- 1051 // ---------------------------------------------------------------------------
1106 // StatsCounter support 1052 // StatsCounter support
1107 1053
1108 void SetCounter(StatsCounter* counter, int value, 1054 void SetCounter(StatsCounter* counter, int value,
1109 Register scratch1, Register scratch2); 1055 Register scratch1, Register scratch2);
1110 void IncrementCounter(StatsCounter* counter, int value, 1056 void IncrementCounter(StatsCounter* counter, int value,
1111 Register scratch1, Register scratch2); 1057 Register scratch1, Register scratch2);
1112 void DecrementCounter(StatsCounter* counter, int value, 1058 void DecrementCounter(StatsCounter* counter, int value,
1113 Register scratch1, Register scratch2); 1059 Register scratch1, Register scratch2);
1114 1060
1115 1061
1116 // --------------------------------------------------------------------------- 1062 // ---------------------------------------------------------------------------
1117 // Debugging 1063 // Debugging
1118 1064
1119 // Calls Abort(msg) if the condition cond is not satisfied. 1065 // Calls Abort(msg) if the condition cond is not satisfied.
1120 // Use --debug_code to enable. 1066 // Use --debug_code to enable.
1121 void Assert(Condition cond, const char* msg); 1067 void Assert(Condition cond, const char* msg);
1122 void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index); 1068
1069 void AssertRegisterIsRoot(Register reg, Register scratch,
1070 Heap::RootListIndex index);
1123 void AssertFastElements(Register elements); 1071 void AssertFastElements(Register elements);
1124 1072
1125 // Like Assert(), but always enabled. 1073 // Like Assert(), but always enabled.
1126 void Check(Condition cond, const char* msg); 1074 void Check(Condition cond, const char* msg);
1127 1075
1128 // Print a message to stdout and abort execution. 1076 // Print a message to stdout and abort execution.
1129 void Abort(const char* msg); 1077 void Abort(const char* msg);
1130 1078
1079 // Print an object to stdout.
1080 void DebugPrint(Register obj);
1081
1082 // Check that the stack is aligned.
1083 void CheckStackAlignment();
1084
1131 // Verify restrictions about code generated in stubs. 1085 // Verify restrictions about code generated in stubs.
1132 void set_generating_stub(bool value) { generating_stub_ = value; } 1086 void set_generating_stub(bool value) { generating_stub_ = value; }
1133 bool generating_stub() { return generating_stub_; } 1087 bool generating_stub() { return generating_stub_; }
1134 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } 1088 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
1135 bool allow_stub_calls() { return allow_stub_calls_; } 1089 bool allow_stub_calls() { return allow_stub_calls_; }
1136 void set_has_frame(bool value) { has_frame_ = value; } 1090 void set_has_frame(bool value) { has_frame_ = value; }
1137 bool has_frame() { return has_frame_; } 1091 bool has_frame() { return has_frame_; }
1138 inline bool AllowThisStubCall(CodeStub* stub); 1092 inline bool AllowThisStubCall(CodeStub* stub);
1139 1093
1140 // EABI variant for double arguments in use.
1141 bool use_eabi_hardfloat() {
1142 #if USE_EABI_HARDFLOAT
1143 return true;
1144 #else
1145 return false;
1146 #endif
1147 }
1148 1094
1149 // --------------------------------------------------------------------------- 1095 // ---------------------------------------------------------------------------
1150 // Number utilities 1096 // Number utilities
1151 1097
1152 // Check whether the value of reg is a power of two and not zero. If not 1098 // Check whether the value of reg is a power of two and not zero. If not
1153 // control continues at the label not_power_of_two. If reg is a power of two 1099 // control continues at the label not_power_of_two. If reg is a power of two
1154 // the register scratch contains the value of (reg - 1) when control falls 1100 // the register scratch contains the value of (reg - 1) when control falls
1155 // through. 1101 // through.
1156 void JumpIfNotPowerOfTwoOrZero(Register reg, 1102 void JumpIfNotPowerOfTwoOrZero(Register reg,
1157 Register scratch, 1103 Register scratch,
1158 Label* not_power_of_two_or_zero); 1104 Label* not_power_of_two_or_zero);
1159 // Check whether the value of reg is a power of two and not zero. 1105 // Check whether the value of reg is a power of two and not zero.
1160 // Control falls through if it is, with scratch containing the mask 1106 // Control falls through if it is, with scratch containing the mask
1161 // value (reg - 1). 1107 // value (reg - 1).
1162 // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is 1108 // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is
1163 // zero or negative, or jumps to the 'not_power_of_two' label if the value is 1109 // zero or negative, or jumps to the 'not_power_of_two' label if the value is
1164 // strictly positive but not a power of two. 1110 // strictly positive but not a power of two.
1165 void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg, 1111 void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg,
1166 Register scratch, 1112 Register scratch,
1167 Label* zero_and_neg, 1113 Label* zero_and_neg,
1168 Label* not_power_of_two); 1114 Label* not_power_of_two);
1169 1115
1170 // --------------------------------------------------------------------------- 1116 // ---------------------------------------------------------------------------
1171 // Smi utilities 1117 // Smi utilities
1172 1118
1173 void SmiTag(Register reg, SBit s = LeaveCC) { 1119 void SmiTag(Register reg) {
1174 add(reg, reg, Operand(reg), s); 1120 add(reg, reg, reg);
1175 } 1121 }
1176 void SmiTag(Register dst, Register src, SBit s = LeaveCC) { 1122 void SmiTag(Register dst, Register src) {
1177 add(dst, src, Operand(src), s); 1123 add(dst, src, src);
1178 } 1124 }
1179 1125
1180 // Try to convert int32 to smi. If the value is to large, preserve 1126 // Try to convert int32 to smi. If the value is to large, preserve
1181 // the original value and jump to not_a_smi. Destroys scratch and 1127 // the original value and jump to not_a_smi. Destroys scratch and
1182 // sets flags. 1128 // sets flags.
1183 void TrySmiTag(Register reg, Label* not_a_smi, Register scratch) { 1129 void TrySmiTag(Register reg, Label* not_a_smi, Register scratch) {
1184 mov(scratch, reg); 1130 addv(scratch, reg, reg);
1185 SmiTag(scratch, SetCC); 1131 b(t, not_a_smi);
1186 b(vs, not_a_smi);
1187 mov(reg, scratch); 1132 mov(reg, scratch);
1188 } 1133 }
1189 1134
1190 void SmiUntag(Register reg, SBit s = LeaveCC) { 1135 void SmiUntag(Register reg) {
1191 mov(reg, Operand(reg, ASR, kSmiTagSize), s); 1136 asr(reg, reg, Operand(kSmiTagSize));
1192 } 1137 }
1193 void SmiUntag(Register dst, Register src, SBit s = LeaveCC) { 1138 void SmiUntag(Register dst, Register src) {
1194 mov(dst, Operand(src, ASR, kSmiTagSize), s); 1139 asr(dst, src, Operand(kSmiTagSize));
1195 } 1140 }
1196 1141
1197 // Untag the source value into destination and jump if source is a smi. 1142 // Untag the source value into destination and jump if source is a smi.
1198 // Souce and destination can be the same register. 1143 // Souce and destination can be the same register.
1199 void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case); 1144 void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case);
1200 1145
1201 // Untag the source value into destination and jump if source is not a smi. 1146 // Untag the source value into destination and jump if source is not a smi.
1202 // Souce and destination can be the same register. 1147 // Souce and destination can be the same register.
1203 void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case); 1148 void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case);
1204 1149
1205 // Jump the register contains a smi. 1150 // Jump the register contains a smi.
1206 inline void JumpIfSmi(Register value, Label* smi_label) { 1151 inline void JumpIfSmi(Register value, Label* smi_label,
1152 Label::Distance distance = Label::kFar) {
1207 tst(value, Operand(kSmiTagMask)); 1153 tst(value, Operand(kSmiTagMask));
1208 b(eq, smi_label); 1154 if (distance == Label::kFar)
1155 bt(smi_label);
1156 else
1157 bt_near(smi_label);
1209 } 1158 }
1210 // Jump if either of the registers contain a non-smi. 1159 // Jump if either of the registers contain a non-smi.
1211 inline void JumpIfNotSmi(Register value, Label* not_smi_label) { 1160 inline void JumpIfNotSmi(Register value, Label* not_smi_label,
1161 Label::Distance distance = Label::kFar) {
1212 tst(value, Operand(kSmiTagMask)); 1162 tst(value, Operand(kSmiTagMask));
1213 b(ne, not_smi_label); 1163 if (distance == Label::kFar)
1214 } 1164 bf(not_smi_label);
1215 // Jump if either of the registers contain a non-smi. 1165 else
1216 void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi); 1166 bf_near(not_smi_label);
1217 // Jump if either of the registers contain a smi.
1218 void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
1219
1220 // Abort execution if argument is a smi, enabled via --debug-code.
1221 void AssertNotSmi(Register object);
1222 void AssertSmi(Register object);
1223
1224 // Abort execution if argument is a string, enabled via --debug-code.
1225 void AssertString(Register object);
1226
1227 // Abort execution if argument is not the root value with the given index,
1228 // enabled via --debug-code.
1229 void AssertRootValue(Register src,
1230 Heap::RootListIndex root_value_index,
1231 const char* message);
1232
1233 // ---------------------------------------------------------------------------
1234 // HeapNumber utilities
1235
1236 void JumpIfNotHeapNumber(Register object,
1237 Register heap_number_map,
1238 Register scratch,
1239 Label* on_not_heap_number);
1240
1241 // ---------------------------------------------------------------------------
1242 // String utilities
1243
1244 // Checks if both objects are sequential ASCII strings and jumps to label
1245 // if either is not. Assumes that neither object is a smi.
1246 void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1,
1247 Register object2,
1248 Register scratch1,
1249 Register scratch2,
1250 Label* failure);
1251
1252 // Checks if both objects are sequential ASCII strings and jumps to label
1253 // if either is not.
1254 void JumpIfNotBothSequentialAsciiStrings(Register first,
1255 Register second,
1256 Register scratch1,
1257 Register scratch2,
1258 Label* not_flat_ascii_strings);
1259
1260 // Checks if both instance types are sequential ASCII strings and jumps to
1261 // label if either is not.
1262 void JumpIfBothInstanceTypesAreNotSequentialAscii(
1263 Register first_object_instance_type,
1264 Register second_object_instance_type,
1265 Register scratch1,
1266 Register scratch2,
1267 Label* failure);
1268
1269 // Check if instance type is sequential ASCII string and jump to label if
1270 // it is not.
1271 void JumpIfInstanceTypeIsNotSequentialAscii(Register type,
1272 Register scratch,
1273 Label* failure);
1274
1275
1276 // ---------------------------------------------------------------------------
1277 // Patching helpers.
1278
1279 // Get the location of a relocated constant (its address in the constant pool)
1280 // from its load site.
1281 void GetRelocatedValueLocation(Register ldr_location,
1282 Register result);
1283
1284
1285 void ClampUint8(Register output_reg, Register input_reg);
1286
1287 void ClampDoubleToUint8(Register result_reg,
1288 DoubleRegister input_reg,
1289 DoubleRegister temp_double_reg);
1290
1291
1292 void LoadInstanceDescriptors(Register map, Register descriptors);
1293 void EnumLength(Register dst, Register map);
1294 void NumberOfOwnDescriptors(Register dst, Register map);
1295
1296 template<typename Field>
1297 void DecodeField(Register reg) {
1298 static const int shift = Field::kShift;
1299 static const int mask = (Field::kMask >> shift) << kSmiTagSize;
1300 mov(reg, Operand(reg, LSR, shift));
1301 and_(reg, reg, Operand(mask));
1302 } 1167 }
1303 1168
1169 // Jump if either of the registers contain a non-smi.
1170 void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi,
1171 Label::Distance distance = Label::kFar);
1172 // Jump if either of the registers contain a smi.
1173 void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi,
1174 Label::Distance distance = Label::kFar);
1304 // Activation support. 1175 // Activation support.
1305 void EnterFrame(StackFrame::Type type); 1176 void EnterFrame(StackFrame::Type type);
1306 void LeaveFrame(StackFrame::Type type); 1177 void LeaveFrame(StackFrame::Type type);
1307 1178
1308 // Expects object in r0 and returns map with validated enum cache
1309 // in r0. Assumes that any other register can be used as a scratch.
1310 void CheckEnumCache(Register null_value, Label* call_runtime);
1311 1179
1312 private: 1180 private:
1313 void CallCFunctionHelper(Register function, 1181 void CallCFunctionHelper(Register function,
1314 int num_reg_arguments, 1182 int num_reg_arguments,
1315 int num_double_arguments); 1183 int num_double_arguments);
1316 1184
1317 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
1318 1185
1319 // Helper functions for generating invokes. 1186 // Helper functions for generating invokes.
1320 void InvokePrologue(const ParameterCount& expected, 1187 void InvokePrologue(const ParameterCount& expected,
1321 const ParameterCount& actual, 1188 const ParameterCount& actual,
1322 Handle<Code> code_constant, 1189 Handle<Code> code_constant,
1323 Register code_reg, 1190 Register code_reg,
1324 Label* done, 1191 Label* done,
1325 bool* definitely_mismatches, 1192 bool* definitely_mismatches,
1326 InvokeFlag flag, 1193 InvokeFlag flag,
1327 const CallWrapper& call_wrapper, 1194 const CallWrapper& call_wrapper,
1328 CallKind call_kind); 1195 CallKind call_kind);
1329 1196
1197 void LeaveExitFrameEpilogue();
1198
1330 void InitializeNewString(Register string, 1199 void InitializeNewString(Register string,
1331 Register length, 1200 Register length,
1332 Heap::RootListIndex map_index, 1201 Heap::RootListIndex map_index,
1333 Register scratch1, 1202 Register scratch1,
1334 Register scratch2); 1203 Register scratch2);
1335 1204
1336 // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
1337 void InNewSpace(Register object,
1338 Register scratch,
1339 Condition cond, // eq for new space, ne otherwise.
1340 Label* branch);
1341
1342 // Helper for finding the mark bits for an address. Afterwards, the 1205 // Helper for finding the mark bits for an address. Afterwards, the
1343 // bitmap register points at the word with the mark bits and the mask 1206 // bitmap register points at the word with the mark bits and the mask
1344 // the position of the first bit. Leaves addr_reg unchanged. 1207 // the position of the first bit. Leaves addr_reg unchanged.
1345 inline void GetMarkBits(Register addr_reg, 1208 inline void GetMarkBits(Register addr_reg,
1346 Register bitmap_reg, 1209 Register bitmap_reg,
1347 Register mask_reg); 1210 Register mask_reg);
1348 1211
1212 // Allocation support helpers.
1213 void LoadAllocationTopHelper(Register result,
1214 Register scratch,
1215 AllocationFlags flags);
1216 void UpdateAllocationTopHelper(Register result_end, Register scratch);
1217
1218 // Helper for PopHandleScope. Allowed to perform a GC and returns
1219 // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and
1220 // possibly returns a failure object indicating an allocation failure.
1221 MUST_USE_RESULT MaybeObject* PopHandleScopeHelper(Register saved,
1222 Register scratch,
1223 bool gc_allowed);
1224
1349 // Helper for throwing exceptions. Compute a handler address and jump to 1225 // Helper for throwing exceptions. Compute a handler address and jump to
1350 // it. See the implementation for register usage. 1226 // it. See the implementation for register usage.
1351 void JumpToHandlerEntry(); 1227 void JumpToHandlerEntry();
1352 1228
1353 // Compute memory operands for safepoint stack slots. 1229 // Compute memory operands for safepoint stack slots.
1354 static int SafepointRegisterStackIndex(int reg_code); 1230 static int SafepointRegisterStackIndex(int reg_code);
1355 MemOperand SafepointRegisterSlot(Register reg); 1231 MemOperand SafepointRegisterSlot(Register reg);
1356 MemOperand SafepointRegistersAndDoublesSlot(Register reg); 1232 MemOperand SafepointRegistersAndDoublesSlot(Register reg);
1357 1233
1358 bool generating_stub_; 1234 bool generating_stub_;
(...skipping 14 matching lines...) Expand all
1373 // relocation information. If any of these constraints are violated it causes 1249 // relocation information. If any of these constraints are violated it causes
1374 // an assertion to fail. 1250 // an assertion to fail.
1375 class CodePatcher { 1251 class CodePatcher {
1376 public: 1252 public:
1377 CodePatcher(byte* address, int instructions); 1253 CodePatcher(byte* address, int instructions);
1378 virtual ~CodePatcher(); 1254 virtual ~CodePatcher();
1379 1255
1380 // Macro assembler to emit code. 1256 // Macro assembler to emit code.
1381 MacroAssembler* masm() { return &masm_; } 1257 MacroAssembler* masm() { return &masm_; }
1382 1258
1383 // Emit an instruction directly.
1384 void Emit(Instr instr);
1385
1386 // Emit an address directly.
1387 void Emit(Address addr);
1388
1389 // Emit the condition part of an instruction leaving the rest of the current 1259 // Emit the condition part of an instruction leaving the rest of the current
1390 // instruction unchanged. 1260 // instruction unchanged.
1391 void EmitCondition(Condition cond); 1261 void EmitCondition(Condition cond);
1392 1262
1393 private: 1263 private:
1394 byte* address_; // The address of the code being patched. 1264 byte* address_; // The address of the code being patched.
1395 int instructions_; // Number of instructions of the expected patch size. 1265 int instructions_; // Number of instructions of the expected patch size.
1396 int size_; // Number of bytes of the expected patch size. 1266 int size_; // Number of bytes of the expected patch size.
1397 MacroAssembler masm_; // Macro assembler used to generate the code. 1267 MacroAssembler masm_; // Macro assembler used to generate the code.
1398 }; 1268 };
1399 1269
1400 1270
1401 // ----------------------------------------------------------------------------- 1271 // -----------------------------------------------------------------------------
1402 // Static helper functions. 1272 // Static helper functions.
1403 1273
1404 inline MemOperand ContextOperand(Register context, int index) { 1274 inline MemOperand ContextOperand(Register context, int index) {
1405 return MemOperand(context, Context::SlotOffset(index)); 1275 return MemOperand(context, Context::SlotOffset(index));
1406 } 1276 }
1407 1277
1408 1278
1409 inline MemOperand GlobalObjectOperand() { 1279 inline MemOperand GlobalObjectOperand() {
1410 return ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX); 1280 return ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX);
1411 } 1281 }
1412 1282
1413 1283
1414 #ifdef GENERATED_CODE_COVERAGE 1284 #ifdef DEBUG
1415 #define CODE_COVERAGE_STRINGIFY(x) #x 1285 # define ACCESS_MASM(masm) masm->RecordFunctionLine(__FUNCTION__, __LINE__)->
1416 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
1417 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
1418 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm->
1419 #else 1286 #else
1420 #define ACCESS_MASM(masm) masm-> 1287 # define ACCESS_MASM(masm) masm->
1421 #endif 1288 #endif
1422 1289
1423 1290
1424 } } // namespace v8::internal 1291 } } // namespace v8::internal
1425 1292
1426 #endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_ 1293 #endif // V8_SH4_MACRO_ASSEMBLER_SH4_H_
OLDNEW
« no previous file with comments | « src/sh4/lithium-sh4.cc ('k') | src/sh4/macro-assembler-sh4.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698