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

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

Issue 714093002: PowerPC specific sub-directories. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 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 | Annotate | Revision Log
« no previous file with comments | « src/ppc/lithium-ppc.cc ('k') | src/ppc/macro-assembler-ppc.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 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_ 5 #ifndef V8_PPC_MACRO_ASSEMBLER_PPC_H_
6 #define V8_ARM_MACRO_ASSEMBLER_ARM_H_ 6 #define V8_PPC_MACRO_ASSEMBLER_PPC_H_
7 7
8 #include "src/assembler.h" 8 #include "src/assembler.h"
9 #include "src/bailout-reason.h" 9 #include "src/bailout-reason.h"
10 #include "src/frames.h" 10 #include "src/frames.h"
11 #include "src/globals.h" 11 #include "src/globals.h"
12 12
13 namespace v8 { 13 namespace v8 {
14 namespace internal { 14 namespace internal {
15 15
16 // ---------------------------------------------------------------------------- 16 // ----------------------------------------------------------------------------
17 // Static helper functions 17 // Static helper functions
18 18
19 // Generate a MemOperand for loading a field from an object. 19 // Generate a MemOperand for loading a field from an object.
20 inline MemOperand FieldMemOperand(Register object, int offset) { 20 inline MemOperand FieldMemOperand(Register object, int offset) {
21 return MemOperand(object, offset - kHeapObjectTag); 21 return MemOperand(object, offset - kHeapObjectTag);
22 } 22 }
23 23
24 24
25 // Give alias names to registers
26 const Register cp = { kRegister_r7_Code }; // JavaScript context pointer.
27 const Register pp = { kRegister_r8_Code }; // Constant pool pointer.
28 const Register kRootRegister = { kRegister_r10_Code }; // Roots array pointer.
29
30 // Flags used for AllocateHeapNumber 25 // Flags used for AllocateHeapNumber
31 enum TaggingMode { 26 enum TaggingMode {
32 // Tag the result. 27 // Tag the result.
33 TAG_RESULT, 28 TAG_RESULT,
34 // Don't tag 29 // Don't tag
35 DONT_TAG_RESULT 30 DONT_TAG_RESULT
36 }; 31 };
37 32
38 33
39 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET }; 34 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
40 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK }; 35 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
41 enum PointersToHereCheck { 36 enum PointersToHereCheck {
42 kPointersToHereMaybeInteresting, 37 kPointersToHereMaybeInteresting,
43 kPointersToHereAreAlwaysInteresting 38 kPointersToHereAreAlwaysInteresting
44 }; 39 };
45 enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved }; 40 enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved };
46 41
47 42
48 Register GetRegisterThatIsNotOneOf(Register reg1, 43 Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2 = no_reg,
49 Register reg2 = no_reg,
50 Register reg3 = no_reg, 44 Register reg3 = no_reg,
51 Register reg4 = no_reg, 45 Register reg4 = no_reg,
52 Register reg5 = no_reg, 46 Register reg5 = no_reg,
53 Register reg6 = no_reg); 47 Register reg6 = no_reg);
54 48
55 49
56 #ifdef DEBUG 50 #ifdef DEBUG
57 bool AreAliased(Register reg1, 51 bool AreAliased(Register reg1, Register reg2, Register reg3 = no_reg,
58 Register reg2, 52 Register reg4 = no_reg, Register reg5 = no_reg,
59 Register reg3 = no_reg, 53 Register reg6 = no_reg, Register reg7 = no_reg,
60 Register reg4 = no_reg,
61 Register reg5 = no_reg,
62 Register reg6 = no_reg,
63 Register reg7 = no_reg,
64 Register reg8 = no_reg); 54 Register reg8 = no_reg);
65 #endif 55 #endif
66 56
57 // These exist to provide portability between 32 and 64bit
58 #if V8_TARGET_ARCH_PPC64
59 #define LoadPU ldu
60 #define LoadPX ldx
61 #define LoadPUX ldux
62 #define StorePU stdu
63 #define StorePX stdx
64 #define StorePUX stdux
65 #define ShiftLeftImm sldi
66 #define ShiftRightImm srdi
67 #define ClearLeftImm clrldi
68 #define ClearRightImm clrrdi
69 #define ShiftRightArithImm sradi
70 #define ShiftLeft_ sld
71 #define ShiftRight_ srd
72 #define ShiftRightArith srad
73 #define Mul mulld
74 #define Div divd
75 #else
76 #define LoadPU lwzu
77 #define LoadPX lwzx
78 #define LoadPUX lwzux
79 #define StorePU stwu
80 #define StorePX stwx
81 #define StorePUX stwux
82 #define ShiftLeftImm slwi
83 #define ShiftRightImm srwi
84 #define ClearLeftImm clrlwi
85 #define ClearRightImm clrrwi
86 #define ShiftRightArithImm srawi
87 #define ShiftLeft_ slw
88 #define ShiftRight_ srw
89 #define ShiftRightArith sraw
90 #define Mul mullw
91 #define Div divw
92 #endif
67 93
68 enum TargetAddressStorageMode {
69 CAN_INLINE_TARGET_ADDRESS,
70 NEVER_INLINE_TARGET_ADDRESS
71 };
72 94
73 // MacroAssembler implements a collection of frequently used macros. 95 // MacroAssembler implements a collection of frequently used macros.
74 class MacroAssembler: public Assembler { 96 class MacroAssembler : public Assembler {
75 public: 97 public:
76 // The isolate parameter can be NULL if the macro assembler should 98 // The isolate parameter can be NULL if the macro assembler should
77 // not use isolate-dependent functionality. In this case, it's the 99 // not use isolate-dependent functionality. In this case, it's the
78 // responsibility of the caller to never invoke such function on the 100 // responsibility of the caller to never invoke such function on the
79 // macro assembler. 101 // macro assembler.
80 MacroAssembler(Isolate* isolate, void* buffer, int size); 102 MacroAssembler(Isolate* isolate, void* buffer, int size);
81 103
82 104
83 // Returns the size of a call in instructions. Note, the value returned is 105 // Returns the size of a call in instructions. Note, the value returned is
84 // only valid as long as no entries are added to the constant pool between 106 // only valid as long as no entries are added to the constant pool between
85 // checking the call size and emitting the actual call. 107 // checking the call size and emitting the actual call.
86 static int CallSize(Register target, Condition cond = al); 108 static int CallSize(Register target);
87 int CallSize(Address target, RelocInfo::Mode rmode, Condition cond = al); 109 int CallSize(Address target, RelocInfo::Mode rmode, Condition cond = al);
88 int CallStubSize(CodeStub* stub, 110 static int CallSizeNotPredictableCodeSize(Address target,
89 TypeFeedbackId ast_id = TypeFeedbackId::None(),
90 Condition cond = al);
91 static int CallSizeNotPredictableCodeSize(Isolate* isolate,
92 Address target,
93 RelocInfo::Mode rmode, 111 RelocInfo::Mode rmode,
94 Condition cond = al); 112 Condition cond = al);
95 113
96 // Jump, Call, and Ret pseudo instructions implementing inter-working. 114 // Jump, Call, and Ret pseudo instructions implementing inter-working.
97 void Jump(Register target, Condition cond = al); 115 void Jump(Register target);
98 void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al); 116 void JumpToJSEntry(Register target);
117 void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al,
118 CRegister cr = cr7);
99 void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); 119 void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
100 void Call(Register target, Condition cond = al); 120 void Call(Register target);
101 void Call(Address target, RelocInfo::Mode rmode, 121 void CallJSEntry(Register target);
102 Condition cond = al, 122 void Call(Address target, RelocInfo::Mode rmode, Condition cond = al);
103 TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS);
104 int CallSize(Handle<Code> code, 123 int CallSize(Handle<Code> code,
105 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET, 124 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
106 TypeFeedbackId ast_id = TypeFeedbackId::None(), 125 TypeFeedbackId ast_id = TypeFeedbackId::None(),
107 Condition cond = al); 126 Condition cond = al);
108 void Call(Handle<Code> code, 127 void Call(Handle<Code> code, RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
109 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
110 TypeFeedbackId ast_id = TypeFeedbackId::None(), 128 TypeFeedbackId ast_id = TypeFeedbackId::None(),
111 Condition cond = al, 129 Condition cond = al);
112 TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS);
113 void Ret(Condition cond = al); 130 void Ret(Condition cond = al);
114 131
115 // Emit code to discard a non-negative number of pointer-sized elements 132 // Emit code to discard a non-negative number of pointer-sized elements
116 // from the stack, clobbering only the sp register. 133 // from the stack, clobbering only the sp register.
117 void Drop(int count, Condition cond = al); 134 void Drop(int count, Condition cond = al);
118 135
119 void Ret(int drop, Condition cond = al); 136 void Ret(int drop, Condition cond = al);
120 137
121 // Swap two registers. If the scratch register is omitted then a slightly 138 void Call(Label* target);
122 // less efficient form using xor instead of mov is emitted.
123 void Swap(Register reg1,
124 Register reg2,
125 Register scratch = no_reg,
126 Condition cond = al);
127 139
128 void Mls(Register dst, Register src1, Register src2, Register srcA, 140 // Emit call to the code we are currently generating.
129 Condition cond = al); 141 void CallSelf() {
130 void And(Register dst, Register src1, const Operand& src2, 142 Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location()));
131 Condition cond = al); 143 Call(self, RelocInfo::CODE_TARGET);
132 void Ubfx(Register dst, Register src, int lsb, int width, 144 }
133 Condition cond = al);
134 void Sbfx(Register dst, Register src, int lsb, int width,
135 Condition cond = al);
136 // The scratch register is not used for ARMv7.
137 // scratch can be the same register as src (in which case it is trashed), but
138 // not the same as dst.
139 void Bfi(Register dst,
140 Register src,
141 Register scratch,
142 int lsb,
143 int width,
144 Condition cond = al);
145 void Bfc(Register dst, Register src, int lsb, int width, Condition cond = al);
146 void Usat(Register dst, int satpos, const Operand& src,
147 Condition cond = al);
148
149 void Call(Label* target);
150 void Push(Register src) { push(src); }
151 void Pop(Register dst) { pop(dst); }
152 145
153 // Register move. May do nothing if the registers are identical. 146 // Register move. May do nothing if the registers are identical.
154 void Move(Register dst, Handle<Object> value); 147 void Move(Register dst, Handle<Object> value);
155 void Move(Register dst, Register src, Condition cond = al); 148 void Move(Register dst, Register src, Condition cond = al);
156 void Move(Register dst, const Operand& src, SBit sbit = LeaveCC, 149 void Move(DoubleRegister dst, DoubleRegister src);
157 Condition cond = al) {
158 if (!src.is_reg() || !src.rm().is(dst) || sbit != LeaveCC) {
159 mov(dst, src, sbit, cond);
160 }
161 }
162 void Move(DwVfpRegister dst, DwVfpRegister src);
163 150
164 void Load(Register dst, const MemOperand& src, Representation r); 151 void MultiPush(RegList regs);
165 void Store(Register src, const MemOperand& dst, Representation r); 152 void MultiPop(RegList regs);
166 153
167 // Load an object from the root table. 154 // Load an object from the root table.
168 void LoadRoot(Register destination, 155 void LoadRoot(Register destination, Heap::RootListIndex index,
169 Heap::RootListIndex index,
170 Condition cond = al); 156 Condition cond = al);
171 // Store an object to the root table. 157 // Store an object to the root table.
172 void StoreRoot(Register source, 158 void StoreRoot(Register source, Heap::RootListIndex index,
173 Heap::RootListIndex index,
174 Condition cond = al); 159 Condition cond = al);
175 160
176 // --------------------------------------------------------------------------- 161 // ---------------------------------------------------------------------------
177 // GC Support 162 // GC Support
178 163
179 void IncrementalMarkingRecordWriteHelper(Register object, 164 void IncrementalMarkingRecordWriteHelper(Register object, Register value,
180 Register value,
181 Register address); 165 Register address);
182 166
183 enum RememberedSetFinalAction { 167 enum RememberedSetFinalAction { kReturnAtEnd, kFallThroughAtEnd };
184 kReturnAtEnd,
185 kFallThroughAtEnd
186 };
187 168
188 // Record in the remembered set the fact that we have a pointer to new space 169 // Record in the remembered set the fact that we have a pointer to new space
189 // at the address pointed to by the addr register. Only works if addr is not 170 // at the address pointed to by the addr register. Only works if addr is not
190 // in new space. 171 // in new space.
191 void RememberedSetHelper(Register object, // Used for debug code. 172 void RememberedSetHelper(Register object, // Used for debug code.
192 Register addr, 173 Register addr, Register scratch,
193 Register scratch,
194 SaveFPRegsMode save_fp, 174 SaveFPRegsMode save_fp,
195 RememberedSetFinalAction and_then); 175 RememberedSetFinalAction and_then);
196 176
197 void CheckPageFlag(Register object, 177 void CheckPageFlag(Register object, Register scratch, int mask, Condition cc,
198 Register scratch,
199 int mask,
200 Condition cc,
201 Label* condition_met); 178 Label* condition_met);
202 179
203 void CheckMapDeprecated(Handle<Map> map, 180 void CheckMapDeprecated(Handle<Map> map, Register scratch,
204 Register scratch,
205 Label* if_deprecated); 181 Label* if_deprecated);
206 182
207 // Check if object is in new space. Jumps if the object is not in new space. 183 // Check if object is in new space. Jumps if the object is not in new space.
208 // The register scratch can be object itself, but scratch will be clobbered. 184 // The register scratch can be object itself, but scratch will be clobbered.
209 void JumpIfNotInNewSpace(Register object, 185 void JumpIfNotInNewSpace(Register object, Register scratch, Label* branch) {
210 Register scratch,
211 Label* branch) {
212 InNewSpace(object, scratch, ne, branch); 186 InNewSpace(object, scratch, ne, branch);
213 } 187 }
214 188
215 // Check if object is in new space. Jumps if the object is in new space. 189 // Check if object is in new space. Jumps if the object is in new space.
216 // The register scratch can be object itself, but it will be clobbered. 190 // The register scratch can be object itself, but it will be clobbered.
217 void JumpIfInNewSpace(Register object, 191 void JumpIfInNewSpace(Register object, Register scratch, Label* branch) {
218 Register scratch,
219 Label* branch) {
220 InNewSpace(object, scratch, eq, branch); 192 InNewSpace(object, scratch, eq, branch);
221 } 193 }
222 194
223 // Check if an object has a given incremental marking color. 195 // Check if an object has a given incremental marking color.
224 void HasColor(Register object, 196 void HasColor(Register object, Register scratch0, Register scratch1,
225 Register scratch0, 197 Label* has_color, int first_bit, int second_bit);
226 Register scratch1,
227 Label* has_color,
228 int first_bit,
229 int second_bit);
230 198
231 void JumpIfBlack(Register object, 199 void JumpIfBlack(Register object, Register scratch0, Register scratch1,
232 Register scratch0,
233 Register scratch1,
234 Label* on_black); 200 Label* on_black);
235 201
236 // Checks the color of an object. If the object is already grey or black 202 // Checks the color of an object. If the object is already grey or black
237 // then we just fall through, since it is already live. If it is white and 203 // then we just fall through, since it is already live. If it is white and
238 // we can determine that it doesn't need to be scanned, then we just mark it 204 // we can determine that it doesn't need to be scanned, then we just mark it
239 // black and fall through. For the rest we jump to the label so the 205 // black and fall through. For the rest we jump to the label so the
240 // incremental marker can fix its assumptions. 206 // incremental marker can fix its assumptions.
241 void EnsureNotWhite(Register object, 207 void EnsureNotWhite(Register object, Register scratch1, Register scratch2,
242 Register scratch1, 208 Register scratch3, Label* object_is_white_and_not_data);
243 Register scratch2,
244 Register scratch3,
245 Label* object_is_white_and_not_data);
246 209
247 // Detects conservatively whether an object is data-only, i.e. it does need to 210 // Detects conservatively whether an object is data-only, i.e. it does need to
248 // be scanned by the garbage collector. 211 // be scanned by the garbage collector.
249 void JumpIfDataObject(Register value, 212 void JumpIfDataObject(Register value, Register scratch,
250 Register scratch,
251 Label* not_data_object); 213 Label* not_data_object);
252 214
253 // Notify the garbage collector that we wrote a pointer into an object. 215 // Notify the garbage collector that we wrote a pointer into an object.
254 // |object| is the object being stored into, |value| is the object being 216 // |object| is the object being stored into, |value| is the object being
255 // stored. value and scratch registers are clobbered by the operation. 217 // stored. value and scratch registers are clobbered by the operation.
256 // The offset is the offset from the start of the object, not the offset from 218 // The offset is the offset from the start of the object, not the offset from
257 // the tagged HeapObject pointer. For use with FieldOperand(reg, off). 219 // the tagged HeapObject pointer. For use with FieldOperand(reg, off).
258 void RecordWriteField( 220 void RecordWriteField(
259 Register object, 221 Register object, int offset, Register value, Register scratch,
260 int offset, 222 LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
261 Register value,
262 Register scratch,
263 LinkRegisterStatus lr_status,
264 SaveFPRegsMode save_fp,
265 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 223 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
266 SmiCheck smi_check = INLINE_SMI_CHECK, 224 SmiCheck smi_check = INLINE_SMI_CHECK,
267 PointersToHereCheck pointers_to_here_check_for_value = 225 PointersToHereCheck pointers_to_here_check_for_value =
268 kPointersToHereMaybeInteresting); 226 kPointersToHereMaybeInteresting);
269 227
270 // As above, but the offset has the tag presubtracted. For use with 228 // As above, but the offset has the tag presubtracted. For use with
271 // MemOperand(reg, off). 229 // MemOperand(reg, off).
272 inline void RecordWriteContextSlot( 230 inline void RecordWriteContextSlot(
273 Register context, 231 Register context, int offset, Register value, Register scratch,
274 int offset, 232 LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
275 Register value,
276 Register scratch,
277 LinkRegisterStatus lr_status,
278 SaveFPRegsMode save_fp,
279 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 233 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
280 SmiCheck smi_check = INLINE_SMI_CHECK, 234 SmiCheck smi_check = INLINE_SMI_CHECK,
281 PointersToHereCheck pointers_to_here_check_for_value = 235 PointersToHereCheck pointers_to_here_check_for_value =
282 kPointersToHereMaybeInteresting) { 236 kPointersToHereMaybeInteresting) {
283 RecordWriteField(context, 237 RecordWriteField(context, offset + kHeapObjectTag, value, scratch,
284 offset + kHeapObjectTag, 238 lr_status, save_fp, remembered_set_action, smi_check,
285 value,
286 scratch,
287 lr_status,
288 save_fp,
289 remembered_set_action,
290 smi_check,
291 pointers_to_here_check_for_value); 239 pointers_to_here_check_for_value);
292 } 240 }
293 241
294 void RecordWriteForMap( 242 void RecordWriteForMap(Register object, Register map, Register dst,
295 Register object, 243 LinkRegisterStatus lr_status, SaveFPRegsMode save_fp);
296 Register map,
297 Register dst,
298 LinkRegisterStatus lr_status,
299 SaveFPRegsMode save_fp);
300 244
301 // For a given |object| notify the garbage collector that the slot |address| 245 // For a given |object| notify the garbage collector that the slot |address|
302 // has been written. |value| is the object being stored. The value and 246 // has been written. |value| is the object being stored. The value and
303 // address registers are clobbered by the operation. 247 // address registers are clobbered by the operation.
304 void RecordWrite( 248 void RecordWrite(
305 Register object, 249 Register object, Register address, Register value,
306 Register address, 250 LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
307 Register value,
308 LinkRegisterStatus lr_status,
309 SaveFPRegsMode save_fp,
310 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 251 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
311 SmiCheck smi_check = INLINE_SMI_CHECK, 252 SmiCheck smi_check = INLINE_SMI_CHECK,
312 PointersToHereCheck pointers_to_here_check_for_value = 253 PointersToHereCheck pointers_to_here_check_for_value =
313 kPointersToHereMaybeInteresting); 254 kPointersToHereMaybeInteresting);
314 255
256 void Push(Register src) { push(src); }
257
315 // Push a handle. 258 // Push a handle.
316 void Push(Handle<Object> handle); 259 void Push(Handle<Object> handle);
317 void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); } 260 void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); }
318 261
319 // Push two registers. Pushes leftmost register first (to highest address). 262 // Push two registers. Pushes leftmost register first (to highest address).
320 void Push(Register src1, Register src2, Condition cond = al) { 263 void Push(Register src1, Register src2) {
321 DCHECK(!src1.is(src2)); 264 StorePU(src2, MemOperand(sp, -2 * kPointerSize));
322 if (src1.code() > src2.code()) { 265 StoreP(src1, MemOperand(sp, kPointerSize));
323 stm(db_w, sp, src1.bit() | src2.bit(), cond);
324 } else {
325 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
326 str(src2, MemOperand(sp, 4, NegPreIndex), cond);
327 }
328 } 266 }
329 267
330 // Push three registers. Pushes leftmost register first (to highest address). 268 // Push three registers. Pushes leftmost register first (to highest address).
331 void Push(Register src1, Register src2, Register src3, Condition cond = al) { 269 void Push(Register src1, Register src2, Register src3) {
332 DCHECK(!src1.is(src2)); 270 StorePU(src3, MemOperand(sp, -3 * kPointerSize));
333 DCHECK(!src2.is(src3)); 271 StoreP(src2, MemOperand(sp, kPointerSize));
334 DCHECK(!src1.is(src3)); 272 StoreP(src1, MemOperand(sp, 2 * kPointerSize));
335 if (src1.code() > src2.code()) {
336 if (src2.code() > src3.code()) {
337 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
338 } else {
339 stm(db_w, sp, src1.bit() | src2.bit(), cond);
340 str(src3, MemOperand(sp, 4, NegPreIndex), cond);
341 }
342 } else {
343 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
344 Push(src2, src3, cond);
345 }
346 } 273 }
347 274
348 // Push four registers. Pushes leftmost register first (to highest address). 275 // Push four registers. Pushes leftmost register first (to highest address).
349 void Push(Register src1, 276 void Push(Register src1, Register src2, Register src3, Register src4) {
350 Register src2, 277 StorePU(src4, MemOperand(sp, -4 * kPointerSize));
351 Register src3, 278 StoreP(src3, MemOperand(sp, kPointerSize));
352 Register src4, 279 StoreP(src2, MemOperand(sp, 2 * kPointerSize));
353 Condition cond = al) { 280 StoreP(src1, MemOperand(sp, 3 * kPointerSize));
354 DCHECK(!src1.is(src2));
355 DCHECK(!src2.is(src3));
356 DCHECK(!src1.is(src3));
357 DCHECK(!src1.is(src4));
358 DCHECK(!src2.is(src4));
359 DCHECK(!src3.is(src4));
360 if (src1.code() > src2.code()) {
361 if (src2.code() > src3.code()) {
362 if (src3.code() > src4.code()) {
363 stm(db_w,
364 sp,
365 src1.bit() | src2.bit() | src3.bit() | src4.bit(),
366 cond);
367 } else {
368 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
369 str(src4, MemOperand(sp, 4, NegPreIndex), cond);
370 }
371 } else {
372 stm(db_w, sp, src1.bit() | src2.bit(), cond);
373 Push(src3, src4, cond);
374 }
375 } else {
376 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
377 Push(src2, src3, src4, cond);
378 }
379 } 281 }
380 282
283 // Push five registers. Pushes leftmost register first (to highest address).
284 void Push(Register src1, Register src2, Register src3, Register src4,
285 Register src5) {
286 StorePU(src5, MemOperand(sp, -5 * kPointerSize));
287 StoreP(src4, MemOperand(sp, kPointerSize));
288 StoreP(src3, MemOperand(sp, 2 * kPointerSize));
289 StoreP(src2, MemOperand(sp, 3 * kPointerSize));
290 StoreP(src1, MemOperand(sp, 4 * kPointerSize));
291 }
292
293 void Pop(Register dst) { pop(dst); }
294
381 // Pop two registers. Pops rightmost register first (from lower address). 295 // Pop two registers. Pops rightmost register first (from lower address).
382 void Pop(Register src1, Register src2, Condition cond = al) { 296 void Pop(Register src1, Register src2) {
383 DCHECK(!src1.is(src2)); 297 LoadP(src2, MemOperand(sp, 0));
384 if (src1.code() > src2.code()) { 298 LoadP(src1, MemOperand(sp, kPointerSize));
385 ldm(ia_w, sp, src1.bit() | src2.bit(), cond); 299 addi(sp, sp, Operand(2 * kPointerSize));
386 } else {
387 ldr(src2, MemOperand(sp, 4, PostIndex), cond);
388 ldr(src1, MemOperand(sp, 4, PostIndex), cond);
389 }
390 } 300 }
391 301
392 // Pop three registers. Pops rightmost register first (from lower address). 302 // Pop three registers. Pops rightmost register first (from lower address).
393 void Pop(Register src1, Register src2, Register src3, Condition cond = al) { 303 void Pop(Register src1, Register src2, Register src3) {
394 DCHECK(!src1.is(src2)); 304 LoadP(src3, MemOperand(sp, 0));
395 DCHECK(!src2.is(src3)); 305 LoadP(src2, MemOperand(sp, kPointerSize));
396 DCHECK(!src1.is(src3)); 306 LoadP(src1, MemOperand(sp, 2 * kPointerSize));
397 if (src1.code() > src2.code()) { 307 addi(sp, sp, Operand(3 * kPointerSize));
398 if (src2.code() > src3.code()) {
399 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
400 } else {
401 ldr(src3, MemOperand(sp, 4, PostIndex), cond);
402 ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
403 }
404 } else {
405 Pop(src2, src3, cond);
406 ldr(src1, MemOperand(sp, 4, PostIndex), cond);
407 }
408 } 308 }
409 309
410 // Pop four registers. Pops rightmost register first (from lower address). 310 // Pop four registers. Pops rightmost register first (from lower address).
411 void Pop(Register src1, 311 void Pop(Register src1, Register src2, Register src3, Register src4) {
412 Register src2, 312 LoadP(src4, MemOperand(sp, 0));
413 Register src3, 313 LoadP(src3, MemOperand(sp, kPointerSize));
414 Register src4, 314 LoadP(src2, MemOperand(sp, 2 * kPointerSize));
415 Condition cond = al) { 315 LoadP(src1, MemOperand(sp, 3 * kPointerSize));
416 DCHECK(!src1.is(src2)); 316 addi(sp, sp, Operand(4 * kPointerSize));
417 DCHECK(!src2.is(src3));
418 DCHECK(!src1.is(src3));
419 DCHECK(!src1.is(src4));
420 DCHECK(!src2.is(src4));
421 DCHECK(!src3.is(src4));
422 if (src1.code() > src2.code()) {
423 if (src2.code() > src3.code()) {
424 if (src3.code() > src4.code()) {
425 ldm(ia_w,
426 sp,
427 src1.bit() | src2.bit() | src3.bit() | src4.bit(),
428 cond);
429 } else {
430 ldr(src4, MemOperand(sp, 4, PostIndex), cond);
431 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
432 }
433 } else {
434 Pop(src3, src4, cond);
435 ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
436 }
437 } else {
438 Pop(src2, src3, src4, cond);
439 ldr(src1, MemOperand(sp, 4, PostIndex), cond);
440 }
441 } 317 }
442 318
443 // Push a fixed frame, consisting of lr, fp, constant pool (if 319 // Pop five registers. Pops rightmost register first (from lower address).
444 // FLAG_enable_ool_constant_pool), context and JS function / marker id if 320 void Pop(Register src1, Register src2, Register src3, Register src4,
445 // marker_reg is a valid register. 321 Register src5) {
322 LoadP(src5, MemOperand(sp, 0));
323 LoadP(src4, MemOperand(sp, kPointerSize));
324 LoadP(src3, MemOperand(sp, 2 * kPointerSize));
325 LoadP(src2, MemOperand(sp, 3 * kPointerSize));
326 LoadP(src1, MemOperand(sp, 4 * kPointerSize));
327 addi(sp, sp, Operand(5 * kPointerSize));
328 }
329
330 // Push a fixed frame, consisting of lr, fp, context and
331 // JS function / marker id if marker_reg is a valid register.
446 void PushFixedFrame(Register marker_reg = no_reg); 332 void PushFixedFrame(Register marker_reg = no_reg);
447 void PopFixedFrame(Register marker_reg = no_reg); 333 void PopFixedFrame(Register marker_reg = no_reg);
448 334
449 // Push and pop the registers that can hold pointers, as defined by the 335 // Push and pop the registers that can hold pointers, as defined by the
450 // RegList constant kSafepointSavedRegisters. 336 // RegList constant kSafepointSavedRegisters.
451 void PushSafepointRegisters(); 337 void PushSafepointRegisters();
452 void PopSafepointRegisters(); 338 void PopSafepointRegisters();
453 // Store value in register src in the safepoint stack slot for 339 // Store value in register src in the safepoint stack slot for
454 // register dst. 340 // register dst.
455 void StoreToSafepointRegisterSlot(Register src, Register dst); 341 void StoreToSafepointRegisterSlot(Register src, Register dst);
456 // Load the value of the src register from its safepoint stack slot 342 // Load the value of the src register from its safepoint stack slot
457 // into register dst. 343 // into register dst.
458 void LoadFromSafepointRegisterSlot(Register dst, Register src); 344 void LoadFromSafepointRegisterSlot(Register dst, Register src);
459 345
460 // Load two consecutive registers with two consecutive memory locations. 346 // Flush the I-cache from asm code. You should use CpuFeatures::FlushICache
461 void Ldrd(Register dst1, 347 // from C.
462 Register dst2, 348 // Does not handle errors.
463 const MemOperand& src, 349 void FlushICache(Register address, size_t size, Register scratch);
464 Condition cond = al);
465
466 // Store two consecutive registers to two consecutive memory locations.
467 void Strd(Register src1,
468 Register src2,
469 const MemOperand& dst,
470 Condition cond = al);
471
472 // Ensure that FPSCR contains values needed by JavaScript.
473 // We need the NaNModeControlBit to be sure that operations like
474 // vadd and vsub generate the Canonical NaN (if a NaN must be generated).
475 // In VFP3 it will be always the Canonical NaN.
476 // In VFP2 it will be either the Canonical NaN or the negative version
477 // of the Canonical NaN. It doesn't matter if we have two values. The aim
478 // is to be sure to never generate the hole NaN.
479 void VFPEnsureFPSCRState(Register scratch);
480 350
481 // If the value is a NaN, canonicalize the value else, do nothing. 351 // If the value is a NaN, canonicalize the value else, do nothing.
482 void VFPCanonicalizeNaN(const DwVfpRegister dst, 352 void CanonicalizeNaN(const DoubleRegister dst, const DoubleRegister src);
483 const DwVfpRegister src, 353 void CanonicalizeNaN(const DoubleRegister value) {
484 const Condition cond = al); 354 CanonicalizeNaN(value, value);
485 void VFPCanonicalizeNaN(const DwVfpRegister value,
486 const Condition cond = al) {
487 VFPCanonicalizeNaN(value, value, cond);
488 } 355 }
489 356
490 // Compare double values and move the result to the normal condition flags. 357 // Converts the integer (untagged smi) in |src| to a double, storing
491 void VFPCompareAndSetFlags(const DwVfpRegister src1, 358 // the result to |double_dst|
492 const DwVfpRegister src2, 359 void ConvertIntToDouble(Register src, DoubleRegister double_dst);
493 const Condition cond = al);
494 void VFPCompareAndSetFlags(const DwVfpRegister src1,
495 const double src2,
496 const Condition cond = al);
497 360
498 // Compare double values and then load the fpscr flags to a register. 361 // Converts the unsigned integer (untagged smi) in |src| to
499 void VFPCompareAndLoadFlags(const DwVfpRegister src1, 362 // a double, storing the result to |double_dst|
500 const DwVfpRegister src2, 363 void ConvertUnsignedIntToDouble(Register src, DoubleRegister double_dst);
501 const Register fpscr_flags,
502 const Condition cond = al);
503 void VFPCompareAndLoadFlags(const DwVfpRegister src1,
504 const double src2,
505 const Register fpscr_flags,
506 const Condition cond = al);
507 364
508 void Vmov(const DwVfpRegister dst, 365 // Converts the integer (untagged smi) in |src| to
509 const double imm, 366 // a float, storing the result in |dst|
510 const Register scratch = no_reg); 367 // Warning: The value in |int_scrach| will be changed in the process!
368 void ConvertIntToFloat(const DoubleRegister dst, const Register src,
369 const Register int_scratch);
511 370
512 void VmovHigh(Register dst, DwVfpRegister src); 371 // Converts the double_input to an integer. Note that, upon return,
513 void VmovHigh(DwVfpRegister dst, Register src); 372 // the contents of double_dst will also hold the fixed point representation.
514 void VmovLow(Register dst, DwVfpRegister src); 373 void ConvertDoubleToInt64(const DoubleRegister double_input,
515 void VmovLow(DwVfpRegister dst, Register src); 374 #if !V8_TARGET_ARCH_PPC64
516 375 const Register dst_hi,
517 // Loads the number from object into dst register. 376 #endif
518 // If |object| is neither smi nor heap number, |not_number| is jumped to 377 const Register dst, const DoubleRegister double_dst,
519 // with |object| still intact. 378 FPRoundingMode rounding_mode = kRoundToZero);
520 void LoadNumber(Register object,
521 LowDwVfpRegister dst,
522 Register heap_number_map,
523 Register scratch,
524 Label* not_number);
525
526 // Loads the number from object into double_dst in the double format.
527 // Control will jump to not_int32 if the value cannot be exactly represented
528 // by a 32-bit integer.
529 // Floating point value in the 32-bit integer range that are not exact integer
530 // won't be loaded.
531 void LoadNumberAsInt32Double(Register object,
532 DwVfpRegister double_dst,
533 Register heap_number_map,
534 Register scratch,
535 LowDwVfpRegister double_scratch,
536 Label* not_int32);
537
538 // Loads the number from object into dst as a 32-bit integer.
539 // Control will jump to not_int32 if the object cannot be exactly represented
540 // by a 32-bit integer.
541 // Floating point value in the 32-bit integer range that are not exact integer
542 // won't be converted.
543 void LoadNumberAsInt32(Register object,
544 Register dst,
545 Register heap_number_map,
546 Register scratch,
547 DwVfpRegister double_scratch0,
548 LowDwVfpRegister double_scratch1,
549 Label* not_int32);
550 379
551 // Generates function and stub prologue code. 380 // Generates function and stub prologue code.
552 void StubPrologue(); 381 void StubPrologue(int prologue_offset = 0);
553 void Prologue(bool code_pre_aging); 382 void Prologue(bool code_pre_aging, int prologue_offset = 0);
554 383
555 // Enter exit frame. 384 // Enter exit frame.
556 // stack_space - extra stack space, used for alignment before call to C. 385 // stack_space - extra stack space, used for alignment before call to C.
557 void EnterExitFrame(bool save_doubles, int stack_space = 0); 386 void EnterExitFrame(bool save_doubles, int stack_space = 0);
558 387
559 // Leave the current exit frame. Expects the return value in r0. 388 // Leave the current exit frame. Expects the return value in r0.
560 // Expect the number of values, pushed prior to the exit frame, to 389 // Expect the number of values, pushed prior to the exit frame, to
561 // remove in a register (or no_reg, if there is nothing to remove). 390 // remove in a register (or no_reg, if there is nothing to remove).
562 void LeaveExitFrame(bool save_doubles, 391 void LeaveExitFrame(bool save_doubles, Register argument_count,
563 Register argument_count,
564 bool restore_context); 392 bool restore_context);
565 393
566 // Get the actual activation frame alignment for target environment. 394 // Get the actual activation frame alignment for target environment.
567 static int ActivationFrameAlignment(); 395 static int ActivationFrameAlignment();
568 396
569 void LoadContext(Register dst, int context_chain_length); 397 void LoadContext(Register dst, int context_chain_length);
570 398
571 // Conditionally load the cached Array transitioned map of type 399 // Conditionally load the cached Array transitioned map of type
572 // transitioned_kind from the native context if the map in register 400 // transitioned_kind from the native context if the map in register
573 // map_in_out is the cached Array map in the native context of 401 // map_in_out is the cached Array map in the native context of
574 // expected_kind. 402 // expected_kind.
575 void LoadTransitionedArrayMapConditional( 403 void LoadTransitionedArrayMapConditional(ElementsKind expected_kind,
576 ElementsKind expected_kind, 404 ElementsKind transitioned_kind,
577 ElementsKind transitioned_kind, 405 Register map_in_out,
578 Register map_in_out, 406 Register scratch,
579 Register scratch, 407 Label* no_map_match);
580 Label* no_map_match);
581 408
582 void LoadGlobalFunction(int index, Register function); 409 void LoadGlobalFunction(int index, Register function);
583 410
584 // Load the initial map from the global function. The registers 411 // Load the initial map from the global function. The registers
585 // function and map can be the same, function is then overwritten. 412 // function and map can be the same, function is then overwritten.
586 void LoadGlobalFunctionInitialMap(Register function, 413 void LoadGlobalFunctionInitialMap(Register function, Register map,
587 Register map,
588 Register scratch); 414 Register scratch);
589 415
590 void InitializeRootRegister() { 416 void InitializeRootRegister() {
591 ExternalReference roots_array_start = 417 ExternalReference roots_array_start =
592 ExternalReference::roots_array_start(isolate()); 418 ExternalReference::roots_array_start(isolate());
593 mov(kRootRegister, Operand(roots_array_start)); 419 mov(kRootRegister, Operand(roots_array_start));
594 } 420 }
595 421
422 // ----------------------------------------------------------------
423 // new PPC macro-assembler interfaces that are slightly higher level
424 // than assembler-ppc and may generate variable length sequences
425
426 // load a literal signed int value <value> to GPR <dst>
427 void LoadIntLiteral(Register dst, int value);
428
429 // load an SMI value <value> to GPR <dst>
430 void LoadSmiLiteral(Register dst, Smi* smi);
431
432 // load a literal double value <value> to FPR <result>
433 void LoadDoubleLiteral(DoubleRegister result, double value, Register scratch);
434
435 void LoadWord(Register dst, const MemOperand& mem, Register scratch);
436
437 void LoadWordArith(Register dst, const MemOperand& mem,
438 Register scratch = no_reg);
439
440 void StoreWord(Register src, const MemOperand& mem, Register scratch);
441
442 void LoadHalfWord(Register dst, const MemOperand& mem, Register scratch);
443
444 void StoreHalfWord(Register src, const MemOperand& mem, Register scratch);
445
446 void LoadByte(Register dst, const MemOperand& mem, Register scratch);
447
448 void StoreByte(Register src, const MemOperand& mem, Register scratch);
449
450 void LoadRepresentation(Register dst, const MemOperand& mem, Representation r,
451 Register scratch = no_reg);
452
453 void StoreRepresentation(Register src, const MemOperand& mem,
454 Representation r, Register scratch = no_reg);
455
456 // Move values between integer and floating point registers.
457 void MovIntToDouble(DoubleRegister dst, Register src, Register scratch);
458 void MovUnsignedIntToDouble(DoubleRegister dst, Register src,
459 Register scratch);
460 void MovInt64ToDouble(DoubleRegister dst,
461 #if !V8_TARGET_ARCH_PPC64
462 Register src_hi,
463 #endif
464 Register src);
465 #if V8_TARGET_ARCH_PPC64
466 void MovInt64ComponentsToDouble(DoubleRegister dst, Register src_hi,
467 Register src_lo, Register scratch);
468 #endif
469 void MovDoubleLowToInt(Register dst, DoubleRegister src);
470 void MovDoubleHighToInt(Register dst, DoubleRegister src);
471 void MovDoubleToInt64(
472 #if !V8_TARGET_ARCH_PPC64
473 Register dst_hi,
474 #endif
475 Register dst, DoubleRegister src);
476
477 void Add(Register dst, Register src, intptr_t value, Register scratch);
478 void Cmpi(Register src1, const Operand& src2, Register scratch,
479 CRegister cr = cr7);
480 void Cmpli(Register src1, const Operand& src2, Register scratch,
481 CRegister cr = cr7);
482 void Cmpwi(Register src1, const Operand& src2, Register scratch,
483 CRegister cr = cr7);
484 void Cmplwi(Register src1, const Operand& src2, Register scratch,
485 CRegister cr = cr7);
486 void And(Register ra, Register rs, const Operand& rb, RCBit rc = LeaveRC);
487 void Or(Register ra, Register rs, const Operand& rb, RCBit rc = LeaveRC);
488 void Xor(Register ra, Register rs, const Operand& rb, RCBit rc = LeaveRC);
489
490 void AddSmiLiteral(Register dst, Register src, Smi* smi, Register scratch);
491 void SubSmiLiteral(Register dst, Register src, Smi* smi, Register scratch);
492 void CmpSmiLiteral(Register src1, Smi* smi, Register scratch,
493 CRegister cr = cr7);
494 void CmplSmiLiteral(Register src1, Smi* smi, Register scratch,
495 CRegister cr = cr7);
496 void AndSmiLiteral(Register dst, Register src, Smi* smi, Register scratch,
497 RCBit rc = LeaveRC);
498
499 // Set new rounding mode RN to FPSCR
500 void SetRoundingMode(FPRoundingMode RN);
501
502 // reset rounding mode to default (kRoundToNearest)
503 void ResetRoundingMode();
504
505 // These exist to provide portability between 32 and 64bit
506 void LoadP(Register dst, const MemOperand& mem, Register scratch = no_reg);
507 void StoreP(Register src, const MemOperand& mem, Register scratch = no_reg);
508
596 // --------------------------------------------------------------------------- 509 // ---------------------------------------------------------------------------
597 // JavaScript invokes 510 // JavaScript invokes
598 511
599 // Invoke the JavaScript function code by either calling or jumping. 512 // Invoke the JavaScript function code by either calling or jumping.
600 void InvokeCode(Register code, 513 void InvokeCode(Register code, const ParameterCount& expected,
601 const ParameterCount& expected, 514 const ParameterCount& actual, InvokeFlag flag,
602 const ParameterCount& actual,
603 InvokeFlag flag,
604 const CallWrapper& call_wrapper); 515 const CallWrapper& call_wrapper);
605 516
606 // Invoke the JavaScript function in the given register. Changes the 517 // Invoke the JavaScript function in the given register. Changes the
607 // current context to the context in the function before invoking. 518 // current context to the context in the function before invoking.
608 void InvokeFunction(Register function, 519 void InvokeFunction(Register function, const ParameterCount& actual,
609 const ParameterCount& actual, 520 InvokeFlag flag, const CallWrapper& call_wrapper);
610 InvokeFlag flag,
611 const CallWrapper& call_wrapper);
612 521
613 void InvokeFunction(Register function, 522 void InvokeFunction(Register function, const ParameterCount& expected,
614 const ParameterCount& expected, 523 const ParameterCount& actual, InvokeFlag flag,
615 const ParameterCount& actual,
616 InvokeFlag flag,
617 const CallWrapper& call_wrapper); 524 const CallWrapper& call_wrapper);
618 525
619 void InvokeFunction(Handle<JSFunction> function, 526 void InvokeFunction(Handle<JSFunction> function,
620 const ParameterCount& expected, 527 const ParameterCount& expected,
621 const ParameterCount& actual, 528 const ParameterCount& actual, InvokeFlag flag,
622 InvokeFlag flag,
623 const CallWrapper& call_wrapper); 529 const CallWrapper& call_wrapper);
624 530
625 void IsObjectJSObjectType(Register heap_object, 531 void IsObjectJSObjectType(Register heap_object, Register map,
626 Register map, 532 Register scratch, Label* fail);
627 Register scratch,
628 Label* fail);
629 533
630 void IsInstanceJSObjectType(Register map, 534 void IsInstanceJSObjectType(Register map, Register scratch, Label* fail);
631 Register scratch,
632 Label* fail);
633 535
634 void IsObjectJSStringType(Register object, 536 void IsObjectJSStringType(Register object, Register scratch, Label* fail);
635 Register scratch,
636 Label* fail);
637 537
638 void IsObjectNameType(Register object, 538 void IsObjectNameType(Register object, Register scratch, Label* fail);
639 Register scratch,
640 Label* fail);
641 539
642 // --------------------------------------------------------------------------- 540 // ---------------------------------------------------------------------------
643 // Debugger Support 541 // Debugger Support
644 542
645 void DebugBreak(); 543 void DebugBreak();
646 544
647 // --------------------------------------------------------------------------- 545 // ---------------------------------------------------------------------------
648 // Exception handling 546 // Exception handling
649 547
650 // Push a new try handler and link into try handler chain. 548 // Push a new try handler and link into try handler chain.
651 void PushTryHandler(StackHandler::Kind kind, int handler_index); 549 void PushTryHandler(StackHandler::Kind kind, int handler_index);
652 550
653 // Unlink the stack handler on top of the stack from the try handler chain. 551 // Unlink the stack handler on top of the stack from the try handler chain.
654 // Must preserve the result register. 552 // Must preserve the result register.
655 void PopTryHandler(); 553 void PopTryHandler();
656 554
657 // Passes thrown value to the handler of top of the try handler chain. 555 // Passes thrown value to the handler of top of the try handler chain.
658 void Throw(Register value); 556 void Throw(Register value);
659 557
660 // Propagates an uncatchable exception to the top of the current JS stack's 558 // Propagates an uncatchable exception to the top of the current JS stack's
661 // handler chain. 559 // handler chain.
662 void ThrowUncatchable(Register value); 560 void ThrowUncatchable(Register value);
663 561
664 // --------------------------------------------------------------------------- 562 // ---------------------------------------------------------------------------
665 // Inline caching support 563 // Inline caching support
666 564
667 // Generate code for checking access rights - used for security checks 565 // Generate code for checking access rights - used for security checks
668 // on access to global objects across environments. The holder register 566 // on access to global objects across environments. The holder register
669 // is left untouched, whereas both scratch registers are clobbered. 567 // is left untouched, whereas both scratch registers are clobbered.
670 void CheckAccessGlobalProxy(Register holder_reg, 568 void CheckAccessGlobalProxy(Register holder_reg, Register scratch,
671 Register scratch,
672 Label* miss); 569 Label* miss);
673 570
674 void GetNumberHash(Register t0, Register scratch); 571 void GetNumberHash(Register t0, Register scratch);
675 572
676 void LoadFromNumberDictionary(Label* miss, 573 void LoadFromNumberDictionary(Label* miss, Register elements, Register key,
677 Register elements, 574 Register result, Register t0, Register t1,
678 Register key,
679 Register result,
680 Register t0,
681 Register t1,
682 Register t2); 575 Register t2);
683 576
684 577
685 inline void MarkCode(NopMarkerTypes type) { 578 inline void MarkCode(NopMarkerTypes type) { nop(type); }
686 nop(type);
687 }
688 579
689 // Check if the given instruction is a 'type' marker. 580 // Check if the given instruction is a 'type' marker.
690 // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type)) 581 // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type))
691 // These instructions are generated to mark special location in the code, 582 // These instructions are generated to mark special location in the code,
692 // like some special IC code. 583 // like some special IC code.
693 static inline bool IsMarkedCode(Instr instr, int type) { 584 static inline bool IsMarkedCode(Instr instr, int type) {
694 DCHECK((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)); 585 DCHECK((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
695 return IsNop(instr, type); 586 return IsNop(instr, type);
696 } 587 }
697 588
698 589
699 static inline int GetCodeMarker(Instr instr) { 590 static inline int GetCodeMarker(Instr instr) {
700 int dst_reg_offset = 12; 591 int dst_reg_offset = 12;
701 int dst_mask = 0xf << dst_reg_offset; 592 int dst_mask = 0xf << dst_reg_offset;
702 int src_mask = 0xf; 593 int src_mask = 0xf;
703 int dst_reg = (instr & dst_mask) >> dst_reg_offset; 594 int dst_reg = (instr & dst_mask) >> dst_reg_offset;
704 int src_reg = instr & src_mask; 595 int src_reg = instr & src_mask;
705 uint32_t non_register_mask = ~(dst_mask | src_mask); 596 uint32_t non_register_mask = ~(dst_mask | src_mask);
706 uint32_t mov_mask = al | 13 << 21; 597 uint32_t mov_mask = al | 13 << 21;
707 598
708 // Return <n> if we have a mov rn rn, else return -1. 599 // Return <n> if we have a mov rn rn, else return -1.
709 int type = ((instr & non_register_mask) == mov_mask) && 600 int type = ((instr & non_register_mask) == mov_mask) &&
710 (dst_reg == src_reg) && 601 (dst_reg == src_reg) && (FIRST_IC_MARKER <= dst_reg) &&
711 (FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER) 602 (dst_reg < LAST_CODE_MARKER)
712 ? src_reg 603 ? src_reg
713 : -1; 604 : -1;
714 DCHECK((type == -1) || 605 DCHECK((type == -1) ||
715 ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER))); 606 ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
716 return type; 607 return type;
717 } 608 }
718 609
719 610
720 // --------------------------------------------------------------------------- 611 // ---------------------------------------------------------------------------
721 // Allocation support 612 // Allocation support
722 613
723 // Allocate an object in new space or old pointer space. The object_size is 614 // Allocate an object in new space or old pointer space. The object_size is
724 // specified either in bytes or in words if the allocation flag SIZE_IN_WORDS 615 // specified either in bytes or in words if the allocation flag SIZE_IN_WORDS
725 // is passed. If the space is exhausted control continues at the gc_required 616 // is passed. If the space is exhausted control continues at the gc_required
726 // label. The allocated object is returned in result. If the flag 617 // label. The allocated object is returned in result. If the flag
727 // tag_allocated_object is true the result is tagged as as a heap object. 618 // tag_allocated_object is true the result is tagged as as a heap object.
728 // All registers are clobbered also when control continues at the gc_required 619 // All registers are clobbered also when control continues at the gc_required
729 // label. 620 // label.
730 void Allocate(int object_size, 621 void Allocate(int object_size, Register result, Register scratch1,
731 Register result, 622 Register scratch2, Label* gc_required, AllocationFlags flags);
732 Register scratch1,
733 Register scratch2,
734 Label* gc_required,
735 AllocationFlags flags);
736 623
737 void Allocate(Register object_size, 624 void Allocate(Register object_size, Register result, Register scratch1,
738 Register result, 625 Register scratch2, Label* gc_required, AllocationFlags flags);
739 Register scratch1,
740 Register scratch2,
741 Label* gc_required,
742 AllocationFlags flags);
743 626
744 // Undo allocation in new space. The object passed and objects allocated after 627 // Undo allocation in new space. The object passed and objects allocated after
745 // it will no longer be allocated. The caller must make sure that no pointers 628 // it will no longer be allocated. The caller must make sure that no pointers
746 // are left to the object(s) no longer allocated as they would be invalid when 629 // are left to the object(s) no longer allocated as they would be invalid when
747 // allocation is undone. 630 // allocation is undone.
748 void UndoAllocationInNewSpace(Register object, Register scratch); 631 void UndoAllocationInNewSpace(Register object, Register scratch);
749 632
750 633
751 void AllocateTwoByteString(Register result, 634 void AllocateTwoByteString(Register result, Register length,
752 Register length, 635 Register scratch1, Register scratch2,
753 Register scratch1, 636 Register scratch3, Label* gc_required);
754 Register scratch2,
755 Register scratch3,
756 Label* gc_required);
757 void AllocateOneByteString(Register result, Register length, 637 void AllocateOneByteString(Register result, Register length,
758 Register scratch1, Register scratch2, 638 Register scratch1, Register scratch2,
759 Register scratch3, Label* gc_required); 639 Register scratch3, Label* gc_required);
760 void AllocateTwoByteConsString(Register result, 640 void AllocateTwoByteConsString(Register result, Register length,
761 Register length, 641 Register scratch1, Register scratch2,
762 Register scratch1,
763 Register scratch2,
764 Label* gc_required); 642 Label* gc_required);
765 void AllocateOneByteConsString(Register result, Register length, 643 void AllocateOneByteConsString(Register result, Register length,
766 Register scratch1, Register scratch2, 644 Register scratch1, Register scratch2,
767 Label* gc_required); 645 Label* gc_required);
768 void AllocateTwoByteSlicedString(Register result, 646 void AllocateTwoByteSlicedString(Register result, Register length,
769 Register length, 647 Register scratch1, Register scratch2,
770 Register scratch1,
771 Register scratch2,
772 Label* gc_required); 648 Label* gc_required);
773 void AllocateOneByteSlicedString(Register result, Register length, 649 void AllocateOneByteSlicedString(Register result, Register length,
774 Register scratch1, Register scratch2, 650 Register scratch1, Register scratch2,
775 Label* gc_required); 651 Label* gc_required);
776 652
777 // Allocates a heap number or jumps to the gc_required label if the young 653 // Allocates a heap number or jumps to the gc_required label if the young
778 // space is full and a scavenge is needed. All registers are clobbered also 654 // space is full and a scavenge is needed. All registers are clobbered also
779 // when control continues at the gc_required label. 655 // when control continues at the gc_required label.
780 void AllocateHeapNumber(Register result, 656 void AllocateHeapNumber(Register result, Register scratch1, Register scratch2,
781 Register scratch1, 657 Register heap_number_map, Label* gc_required,
782 Register scratch2,
783 Register heap_number_map,
784 Label* gc_required,
785 TaggingMode tagging_mode = TAG_RESULT, 658 TaggingMode tagging_mode = TAG_RESULT,
786 MutableMode mode = IMMUTABLE); 659 MutableMode mode = IMMUTABLE);
787 void AllocateHeapNumberWithValue(Register result, 660 void AllocateHeapNumberWithValue(Register result, DoubleRegister value,
788 DwVfpRegister value, 661 Register scratch1, Register scratch2,
789 Register scratch1,
790 Register scratch2,
791 Register heap_number_map, 662 Register heap_number_map,
792 Label* gc_required); 663 Label* gc_required);
793 664
794 // Copies a fixed number of fields of heap objects from src to dst. 665 // Copies a fixed number of fields of heap objects from src to dst.
795 void CopyFields(Register dst, 666 void CopyFields(Register dst, Register src, RegList temps, int field_count);
796 Register src,
797 LowDwVfpRegister double_scratch,
798 int field_count);
799 667
800 // Copies a number of bytes from src to dst. All registers are clobbered. On 668 // Copies a number of bytes from src to dst. All registers are clobbered. On
801 // exit src and dst will point to the place just after where the last byte was 669 // exit src and dst will point to the place just after where the last byte was
802 // read or written and length will be zero. 670 // read or written and length will be zero.
803 void CopyBytes(Register src, 671 void CopyBytes(Register src, Register dst, Register length, Register scratch);
804 Register dst, 672
805 Register length, 673 // Initialize fields with filler values. |count| fields starting at
806 Register scratch); 674 // |start_offset| are overwritten with the value in |filler|. At the end the
675 // loop, |start_offset| points at the next uninitialized field. |count| is
676 // assumed to be non-zero.
677 void InitializeNFieldsWithFiller(Register start_offset, Register count,
678 Register filler);
807 679
808 // Initialize fields with filler values. Fields starting at |start_offset| 680 // Initialize fields with filler values. Fields starting at |start_offset|
809 // not including end_offset are overwritten with the value in |filler|. At 681 // not including end_offset are overwritten with the value in |filler|. At
810 // the end the loop, |start_offset| takes the value of |end_offset|. 682 // the end the loop, |start_offset| takes the value of |end_offset|.
811 void InitializeFieldsWithFiller(Register start_offset, 683 void InitializeFieldsWithFiller(Register start_offset, Register end_offset,
812 Register end_offset,
813 Register filler); 684 Register filler);
814 685
815 // --------------------------------------------------------------------------- 686 // ---------------------------------------------------------------------------
816 // Support functions. 687 // Support functions.
817 688
818 // Try to get function prototype of a function and puts the value in 689 // Try to get function prototype of a function and puts the value in
819 // the result register. Checks that the function really is a 690 // the result register. Checks that the function really is a
820 // function and jumps to the miss label if the fast checks fail. The 691 // function and jumps to the miss label if the fast checks fail. The
821 // function register will be untouched; the other registers may be 692 // function register will be untouched; the other registers may be
822 // clobbered. 693 // clobbered.
823 void TryGetFunctionPrototype(Register function, 694 void TryGetFunctionPrototype(Register function, Register result,
824 Register result, 695 Register scratch, Label* miss,
825 Register scratch,
826 Label* miss,
827 bool miss_on_bound_function = false); 696 bool miss_on_bound_function = false);
828 697
829 // Compare object type for heap object. heap_object contains a non-Smi 698 // Compare object type for heap object. heap_object contains a non-Smi
830 // whose object type should be compared with the given type. This both 699 // whose object type should be compared with the given type. This both
831 // sets the flags and leaves the object type in the type_reg register. 700 // sets the flags and leaves the object type in the type_reg register.
832 // It leaves the map in the map register (unless the type_reg and map register 701 // It leaves the map in the map register (unless the type_reg and map register
833 // are the same register). It leaves the heap object in the heap_object 702 // are the same register). It leaves the heap object in the heap_object
834 // register unless the heap_object register is the same register as one of the 703 // register unless the heap_object register is the same register as one of the
835 // other registers. 704 // other registers.
836 // Type_reg can be no_reg. In that case ip is used. 705 // Type_reg can be no_reg. In that case ip is used.
837 void CompareObjectType(Register heap_object, 706 void CompareObjectType(Register heap_object, Register map, Register type_reg,
838 Register map,
839 Register type_reg,
840 InstanceType type); 707 InstanceType type);
841 708
842 // Compare object type for heap object. Branch to false_label if type 709 // Compare object type for heap object. Branch to false_label if type
843 // is lower than min_type or greater than max_type. 710 // is lower than min_type or greater than max_type.
844 // Load map into the register map. 711 // Load map into the register map.
845 void CheckObjectTypeRange(Register heap_object, 712 void CheckObjectTypeRange(Register heap_object, Register map,
846 Register map, 713 InstanceType min_type, InstanceType max_type,
847 InstanceType min_type,
848 InstanceType max_type,
849 Label* false_label); 714 Label* false_label);
850 715
851 // Compare instance type in a map. map contains a valid map object whose 716 // Compare instance type in a map. map contains a valid map object whose
852 // object type should be compared with the given type. This both 717 // object type should be compared with the given type. This both
853 // sets the flags and leaves the object type in the type_reg register. 718 // sets the flags and leaves the object type in the type_reg register.
854 void CompareInstanceType(Register map, 719 void CompareInstanceType(Register map, Register type_reg, InstanceType type);
855 Register type_reg,
856 InstanceType type);
857 720
858 721
859 // Check if a map for a JSObject indicates that the object has fast elements. 722 // Check if a map for a JSObject indicates that the object has fast elements.
860 // Jump to the specified label if it does not. 723 // Jump to the specified label if it does not.
861 void CheckFastElements(Register map, 724 void CheckFastElements(Register map, Register scratch, Label* fail);
862 Register scratch,
863 Label* fail);
864 725
865 // Check if a map for a JSObject indicates that the object can have both smi 726 // Check if a map for a JSObject indicates that the object can have both smi
866 // and HeapObject elements. Jump to the specified label if it does not. 727 // and HeapObject elements. Jump to the specified label if it does not.
867 void CheckFastObjectElements(Register map, 728 void CheckFastObjectElements(Register map, Register scratch, Label* fail);
868 Register scratch,
869 Label* fail);
870 729
871 // Check if a map for a JSObject indicates that the object has fast smi only 730 // Check if a map for a JSObject indicates that the object has fast smi only
872 // elements. Jump to the specified label if it does not. 731 // elements. Jump to the specified label if it does not.
873 void CheckFastSmiElements(Register map, 732 void CheckFastSmiElements(Register map, Register scratch, Label* fail);
874 Register scratch,
875 Label* fail);
876 733
877 // Check to see if maybe_number can be stored as a double in 734 // Check to see if maybe_number can be stored as a double in
878 // FastDoubleElements. If it can, store it at the index specified by key in 735 // FastDoubleElements. If it can, store it at the index specified by key in
879 // the FastDoubleElements array elements. Otherwise jump to fail. 736 // the FastDoubleElements array elements. Otherwise jump to fail.
880 void StoreNumberToDoubleElements(Register value_reg, 737 void StoreNumberToDoubleElements(Register value_reg, Register key_reg,
881 Register key_reg, 738 Register elements_reg, Register scratch1,
882 Register elements_reg, 739 DoubleRegister double_scratch, Label* fail,
883 Register scratch1,
884 LowDwVfpRegister double_scratch,
885 Label* fail,
886 int elements_offset = 0); 740 int elements_offset = 0);
887 741
888 // Compare an object's map with the specified map and its transitioned 742 // Compare an object's map with the specified map and its transitioned
889 // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Condition flags are 743 // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Condition flags are
890 // set with result of map compare. If multiple map compares are required, the 744 // set with result of map compare. If multiple map compares are required, the
891 // compare sequences branches to early_success. 745 // compare sequences branches to early_success.
892 void CompareMap(Register obj, 746 void CompareMap(Register obj, Register scratch, Handle<Map> map,
893 Register scratch,
894 Handle<Map> map,
895 Label* early_success); 747 Label* early_success);
896 748
897 // As above, but the map of the object is already loaded into the register 749 // As above, but the map of the object is already loaded into the register
898 // which is preserved by the code generated. 750 // which is preserved by the code generated.
899 void CompareMap(Register obj_map, 751 void CompareMap(Register obj_map, Handle<Map> map, Label* early_success);
900 Handle<Map> map,
901 Label* early_success);
902 752
903 // Check if the map of an object is equal to a specified map and branch to 753 // Check if the map of an object is equal to a specified map and branch to
904 // label if not. Skip the smi check if not required (object is known to be a 754 // label if not. Skip the smi check if not required (object is known to be a
905 // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match 755 // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
906 // against maps that are ElementsKind transition maps of the specified map. 756 // against maps that are ElementsKind transition maps of the specified map.
907 void CheckMap(Register obj, 757 void CheckMap(Register obj, Register scratch, Handle<Map> map, Label* fail,
908 Register scratch,
909 Handle<Map> map,
910 Label* fail,
911 SmiCheckType smi_check_type); 758 SmiCheckType smi_check_type);
912 759
913 760
914 void CheckMap(Register obj, 761 void CheckMap(Register obj, Register scratch, Heap::RootListIndex index,
915 Register scratch, 762 Label* fail, SmiCheckType smi_check_type);
916 Heap::RootListIndex index,
917 Label* fail,
918 SmiCheckType smi_check_type);
919 763
920 764
921 // Check if the map of an object is equal to a specified map and branch to a 765 // Check if the map of an object is equal to a specified map and branch to a
922 // specified target if equal. Skip the smi check if not required (object is 766 // specified target if equal. Skip the smi check if not required (object is
923 // known to be a heap object) 767 // known to be a heap object)
924 void DispatchMap(Register obj, 768 void DispatchMap(Register obj, Register scratch, Handle<Map> map,
925 Register scratch, 769 Handle<Code> success, SmiCheckType smi_check_type);
926 Handle<Map> map,
927 Handle<Code> success,
928 SmiCheckType smi_check_type);
929 770
930 771
931 // Compare the object in a register to a value from the root list. 772 // Compare the object in a register to a value from the root list.
932 // Uses the ip register as scratch. 773 // Uses the ip register as scratch.
933 void CompareRoot(Register obj, Heap::RootListIndex index); 774 void CompareRoot(Register obj, Heap::RootListIndex index);
934 775
935 776
936 // Load and check the instance type of an object for being a string. 777 // Load and check the instance type of an object for being a string.
937 // Loads the type into the second argument register. 778 // Loads the type into the second argument register.
938 // Returns a condition that will be enabled if the object was a string 779 // Returns a condition that will be enabled if the object was a string.
939 // and the passed-in condition passed. If the passed-in condition failed 780 Condition IsObjectStringType(Register obj, Register type) {
940 // then flags remain unchanged. 781 LoadP(type, FieldMemOperand(obj, HeapObject::kMapOffset));
941 Condition IsObjectStringType(Register obj, 782 lbz(type, FieldMemOperand(type, Map::kInstanceTypeOffset));
942 Register type, 783 andi(r0, type, Operand(kIsNotStringMask));
943 Condition cond = al) {
944 ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset), cond);
945 ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset), cond);
946 tst(type, Operand(kIsNotStringMask), cond);
947 DCHECK_EQ(0, kStringTag); 784 DCHECK_EQ(0, kStringTag);
948 return eq; 785 return eq;
949 } 786 }
950 787
951 788
952 // Picks out an array index from the hash field. 789 // Picks out an array index from the hash field.
953 // Register use: 790 // Register use:
954 // hash - holds the index's hash. Clobbered. 791 // hash - holds the index's hash. Clobbered.
955 // index - holds the overwritten index on exit. 792 // index - holds the overwritten index on exit.
956 void IndexFromHash(Register hash, Register index); 793 void IndexFromHash(Register hash, Register index);
957 794
958 // Get the number of least significant bits from a register 795 // Get the number of least significant bits from a register
959 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits); 796 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
960 void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits); 797 void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits);
961 798
962 // Load the value of a smi object into a double register. 799 // Load the value of a smi object into a double register.
963 // The register value must be between d0 and d15. 800 void SmiToDouble(DoubleRegister value, Register smi);
964 void SmiToDouble(LowDwVfpRegister value, Register smi);
965 801
966 // Check if a double can be exactly represented as a signed 32-bit integer. 802 // Check if a double can be exactly represented as a signed 32-bit integer.
967 // Z flag set to one if true. 803 // CR_EQ in cr7 is set if true.
968 void TestDoubleIsInt32(DwVfpRegister double_input, 804 void TestDoubleIsInt32(DoubleRegister double_input, Register scratch1,
969 LowDwVfpRegister double_scratch); 805 Register scratch2, DoubleRegister double_scratch);
970 806
971 // Try to convert a double to a signed 32-bit integer. 807 // Try to convert a double to a signed 32-bit integer.
972 // Z flag set to one and result assigned if the conversion is exact. 808 // CR_EQ in cr7 is set and result assigned if the conversion is exact.
973 void TryDoubleToInt32Exact(Register result, 809 void TryDoubleToInt32Exact(Register result, DoubleRegister double_input,
974 DwVfpRegister double_input, 810 Register scratch, DoubleRegister double_scratch);
975 LowDwVfpRegister double_scratch);
976 811
977 // Floor a double and writes the value to the result register. 812 // Floor a double and writes the value to the result register.
978 // Go to exact if the conversion is exact (to be able to test -0), 813 // Go to exact if the conversion is exact (to be able to test -0),
979 // fall through calling code if an overflow occurred, else go to done. 814 // fall through calling code if an overflow occurred, else go to done.
980 // In return, input_high is loaded with high bits of input. 815 // In return, input_high is loaded with high bits of input.
981 void TryInt32Floor(Register result, 816 void TryInt32Floor(Register result, DoubleRegister double_input,
982 DwVfpRegister double_input, 817 Register input_high, Register scratch,
983 Register input_high, 818 DoubleRegister double_scratch, Label* done, Label* exact);
984 LowDwVfpRegister double_scratch,
985 Label* done,
986 Label* exact);
987 819
988 // Performs a truncating conversion of a floating point number as used by 820 // Performs a truncating conversion of a floating point number as used by
989 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it 821 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it
990 // succeeds, otherwise falls through if result is saturated. On return 822 // succeeds, otherwise falls through if result is saturated. On return
991 // 'result' either holds answer, or is clobbered on fall through. 823 // 'result' either holds answer, or is clobbered on fall through.
992 // 824 //
993 // Only public for the test code in test-code-stubs-arm.cc. 825 // Only public for the test code in test-code-stubs-arm.cc.
994 void TryInlineTruncateDoubleToI(Register result, 826 void TryInlineTruncateDoubleToI(Register result, DoubleRegister input,
995 DwVfpRegister input,
996 Label* done); 827 Label* done);
997 828
998 // Performs a truncating conversion of a floating point number as used by 829 // Performs a truncating conversion of a floating point number as used by
999 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 830 // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
1000 // Exits with 'result' holding the answer. 831 // Exits with 'result' holding the answer.
1001 void TruncateDoubleToI(Register result, DwVfpRegister double_input); 832 void TruncateDoubleToI(Register result, DoubleRegister double_input);
1002 833
1003 // Performs a truncating conversion of a heap number as used by 834 // Performs a truncating conversion of a heap number as used by
1004 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input' 835 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input'
1005 // must be different registers. Exits with 'result' holding the answer. 836 // must be different registers. Exits with 'result' holding the answer.
1006 void TruncateHeapNumberToI(Register result, Register object); 837 void TruncateHeapNumberToI(Register result, Register object);
1007 838
1008 // Converts the smi or heap number in object to an int32 using the rules 839 // Converts the smi or heap number in object to an int32 using the rules
1009 // for ToInt32 as described in ECMAScript 9.5.: the value is truncated 840 // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
1010 // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be 841 // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be
1011 // different registers. 842 // different registers.
1012 void TruncateNumberToI(Register object, 843 void TruncateNumberToI(Register object, Register result,
1013 Register result, 844 Register heap_number_map, Register scratch1,
1014 Register heap_number_map,
1015 Register scratch1,
1016 Label* not_int32); 845 Label* not_int32);
1017 846
1018 // Check whether d16-d31 are available on the CPU. The result is given by the 847 // Overflow handling functions.
1019 // Z condition flag: Z==0 if d16-d31 available, Z==1 otherwise. 848 // Usage: call the appropriate arithmetic function and then call one of the
1020 void CheckFor32DRegs(Register scratch); 849 // flow control functions with the corresponding label.
1021 850
1022 // Does a runtime check for 16/32 FP registers. Either way, pushes 32 double 851 // Compute dst = left + right, setting condition codes. dst may be same as
1023 // values to location, saving [d0..(d15|d31)]. 852 // either left or right (or a unique register). left and right must not be
1024 void SaveFPRegs(Register location, Register scratch); 853 // the same register.
854 void AddAndCheckForOverflow(Register dst, Register left, Register right,
855 Register overflow_dst, Register scratch = r0);
856 void AddAndCheckForOverflow(Register dst, Register left, intptr_t right,
857 Register overflow_dst, Register scratch = r0);
1025 858
1026 // Does a runtime check for 16/32 FP registers. Either way, pops 32 double 859 // Compute dst = left - right, setting condition codes. dst may be same as
1027 // values to location, restoring [d0..(d15|d31)]. 860 // either left or right (or a unique register). left and right must not be
1028 void RestoreFPRegs(Register location, Register scratch); 861 // the same register.
862 void SubAndCheckForOverflow(Register dst, Register left, Register right,
863 Register overflow_dst, Register scratch = r0);
864
865 void BranchOnOverflow(Label* label) { blt(label, cr0); }
866
867 void BranchOnNoOverflow(Label* label) { bge(label, cr0); }
868
869 void RetOnOverflow(void) {
870 Label label;
871
872 blt(&label, cr0);
873 Ret();
874 bind(&label);
875 }
876
877 void RetOnNoOverflow(void) {
878 Label label;
879
880 bge(&label, cr0);
881 Ret();
882 bind(&label);
883 }
884
885 // Pushes <count> double values to <location>, starting from d<first>.
886 void SaveFPRegs(Register location, int first, int count);
887
888 // Pops <count> double values from <location>, starting from d<first>.
889 void RestoreFPRegs(Register location, int first, int count);
1029 890
1030 // --------------------------------------------------------------------------- 891 // ---------------------------------------------------------------------------
1031 // Runtime calls 892 // Runtime calls
1032 893
1033 // Call a code stub. 894 // Call a code stub.
1034 void CallStub(CodeStub* stub, 895 void CallStub(CodeStub* stub, TypeFeedbackId ast_id = TypeFeedbackId::None(),
1035 TypeFeedbackId ast_id = TypeFeedbackId::None(),
1036 Condition cond = al); 896 Condition cond = al);
1037 897
1038 // Call a code stub. 898 // Call a code stub.
1039 void TailCallStub(CodeStub* stub, Condition cond = al); 899 void TailCallStub(CodeStub* stub, Condition cond = al);
1040 900
1041 // Call a runtime routine. 901 // Call a runtime routine.
1042 void CallRuntime(const Runtime::Function* f, 902 void CallRuntime(const Runtime::Function* f, int num_arguments,
1043 int num_arguments,
1044 SaveFPRegsMode save_doubles = kDontSaveFPRegs); 903 SaveFPRegsMode save_doubles = kDontSaveFPRegs);
1045 void CallRuntimeSaveDoubles(Runtime::FunctionId id) { 904 void CallRuntimeSaveDoubles(Runtime::FunctionId id) {
1046 const Runtime::Function* function = Runtime::FunctionForId(id); 905 const Runtime::Function* function = Runtime::FunctionForId(id);
1047 CallRuntime(function, function->nargs, kSaveFPRegs); 906 CallRuntime(function, function->nargs, kSaveFPRegs);
1048 } 907 }
1049 908
1050 // Convenience function: Same as above, but takes the fid instead. 909 // Convenience function: Same as above, but takes the fid instead.
1051 void CallRuntime(Runtime::FunctionId id, 910 void CallRuntime(Runtime::FunctionId id, int num_arguments,
1052 int num_arguments,
1053 SaveFPRegsMode save_doubles = kDontSaveFPRegs) { 911 SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
1054 CallRuntime(Runtime::FunctionForId(id), num_arguments, save_doubles); 912 CallRuntime(Runtime::FunctionForId(id), num_arguments, save_doubles);
1055 } 913 }
1056 914
1057 // Convenience function: call an external reference. 915 // Convenience function: call an external reference.
1058 void CallExternalReference(const ExternalReference& ext, 916 void CallExternalReference(const ExternalReference& ext, int num_arguments);
1059 int num_arguments);
1060 917
1061 // Tail call of a runtime routine (jump). 918 // Tail call of a runtime routine (jump).
1062 // Like JumpToExternalReference, but also takes care of passing the number 919 // Like JumpToExternalReference, but also takes care of passing the number
1063 // of parameters. 920 // of parameters.
1064 void TailCallExternalReference(const ExternalReference& ext, 921 void TailCallExternalReference(const ExternalReference& ext,
1065 int num_arguments, 922 int num_arguments, int result_size);
1066 int result_size);
1067 923
1068 // Convenience function: tail call a runtime routine (jump). 924 // Convenience function: tail call a runtime routine (jump).
1069 void TailCallRuntime(Runtime::FunctionId fid, 925 void TailCallRuntime(Runtime::FunctionId fid, int num_arguments,
1070 int num_arguments,
1071 int result_size); 926 int result_size);
1072 927
1073 int CalculateStackPassedWords(int num_reg_arguments, 928 int CalculateStackPassedWords(int num_reg_arguments,
1074 int num_double_arguments); 929 int num_double_arguments);
1075 930
1076 // Before calling a C-function from generated code, align arguments on stack. 931 // Before calling a C-function from generated code, align arguments on stack.
1077 // After aligning the frame, non-register arguments must be stored in 932 // After aligning the frame, non-register arguments must be stored in
1078 // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments 933 // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments
1079 // are word sized. If double arguments are used, this function assumes that 934 // are word sized. If double arguments are used, this function assumes that
1080 // all double arguments are stored before core registers; otherwise the 935 // all double arguments are stored before core registers; otherwise the
1081 // correct alignment of the double values is not guaranteed. 936 // correct alignment of the double values is not guaranteed.
1082 // Some compilers/platforms require the stack to be aligned when calling 937 // Some compilers/platforms require the stack to be aligned when calling
1083 // C++ code. 938 // C++ code.
1084 // Needs a scratch register to do some arithmetic. This register will be 939 // Needs a scratch register to do some arithmetic. This register will be
1085 // trashed. 940 // trashed.
1086 void PrepareCallCFunction(int num_reg_arguments, 941 void PrepareCallCFunction(int num_reg_arguments, int num_double_registers,
1087 int num_double_registers,
1088 Register scratch); 942 Register scratch);
1089 void PrepareCallCFunction(int num_reg_arguments, 943 void PrepareCallCFunction(int num_reg_arguments, Register scratch);
1090 Register scratch);
1091 944
1092 // There are two ways of passing double arguments on ARM, depending on 945 // There are two ways of passing double arguments on ARM, depending on
1093 // whether soft or hard floating point ABI is used. These functions 946 // whether soft or hard floating point ABI is used. These functions
1094 // abstract parameter passing for the three different ways we call 947 // abstract parameter passing for the three different ways we call
1095 // C functions from generated code. 948 // C functions from generated code.
1096 void MovToFloatParameter(DwVfpRegister src); 949 void MovToFloatParameter(DoubleRegister src);
1097 void MovToFloatParameters(DwVfpRegister src1, DwVfpRegister src2); 950 void MovToFloatParameters(DoubleRegister src1, DoubleRegister src2);
1098 void MovToFloatResult(DwVfpRegister src); 951 void MovToFloatResult(DoubleRegister src);
1099 952
1100 // Calls a C function and cleans up the space for arguments allocated 953 // Calls a C function and cleans up the space for arguments allocated
1101 // by PrepareCallCFunction. The called function is not allowed to trigger a 954 // by PrepareCallCFunction. The called function is not allowed to trigger a
1102 // garbage collection, since that might move the code and invalidate the 955 // garbage collection, since that might move the code and invalidate the
1103 // return address (unless this is somehow accounted for by the called 956 // return address (unless this is somehow accounted for by the called
1104 // function). 957 // function).
1105 void CallCFunction(ExternalReference function, int num_arguments); 958 void CallCFunction(ExternalReference function, int num_arguments);
1106 void CallCFunction(Register function, int num_arguments); 959 void CallCFunction(Register function, int num_arguments);
1107 void CallCFunction(ExternalReference function, 960 void CallCFunction(ExternalReference function, int num_reg_arguments,
1108 int num_reg_arguments,
1109 int num_double_arguments); 961 int num_double_arguments);
1110 void CallCFunction(Register function, 962 void CallCFunction(Register function, int num_reg_arguments,
1111 int num_reg_arguments,
1112 int num_double_arguments); 963 int num_double_arguments);
1113 964
1114 void MovFromFloatParameter(DwVfpRegister dst); 965 void MovFromFloatParameter(DoubleRegister dst);
1115 void MovFromFloatResult(DwVfpRegister dst); 966 void MovFromFloatResult(DoubleRegister dst);
1116 967
1117 // Calls an API function. Allocates HandleScope, extracts returned value 968 // Calls an API function. Allocates HandleScope, extracts returned value
1118 // from handle and propagates exceptions. Restores context. stack_space 969 // from handle and propagates exceptions. Restores context. stack_space
1119 // - space to be unwound on exit (includes the call JS arguments space and 970 // - space to be unwound on exit (includes the call JS arguments space and
1120 // the additional space allocated for the fast call). 971 // the additional space allocated for the fast call).
1121 void CallApiFunctionAndReturn(Register function_address, 972 void CallApiFunctionAndReturn(Register function_address,
1122 ExternalReference thunk_ref, 973 ExternalReference thunk_ref, int stack_space,
1123 int stack_space,
1124 MemOperand return_value_operand, 974 MemOperand return_value_operand,
1125 MemOperand* context_restore_operand); 975 MemOperand* context_restore_operand);
1126 976
1127 // Jump to a runtime routine. 977 // Jump to a runtime routine.
1128 void JumpToExternalReference(const ExternalReference& builtin); 978 void JumpToExternalReference(const ExternalReference& builtin);
1129 979
1130 // Invoke specified builtin JavaScript function. Adds an entry to 980 // Invoke specified builtin JavaScript function. Adds an entry to
1131 // the unresolved list if the name does not resolve. 981 // the unresolved list if the name does not resolve.
1132 void InvokeBuiltin(Builtins::JavaScript id, 982 void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag,
1133 InvokeFlag flag,
1134 const CallWrapper& call_wrapper = NullCallWrapper()); 983 const CallWrapper& call_wrapper = NullCallWrapper());
1135 984
1136 // Store the code object for the given builtin in the target register and 985 // Store the code object for the given builtin in the target register and
1137 // setup the function in r1. 986 // setup the function in r1.
1138 void GetBuiltinEntry(Register target, Builtins::JavaScript id); 987 void GetBuiltinEntry(Register target, Builtins::JavaScript id);
1139 988
1140 // Store the function for the given builtin in the target register. 989 // Store the function for the given builtin in the target register.
1141 void GetBuiltinFunction(Register target, Builtins::JavaScript id); 990 void GetBuiltinFunction(Register target, Builtins::JavaScript id);
1142 991
1143 Handle<Object> CodeObject() { 992 Handle<Object> CodeObject() {
1144 DCHECK(!code_object_.is_null()); 993 DCHECK(!code_object_.is_null());
1145 return code_object_; 994 return code_object_;
1146 } 995 }
1147 996
1148 997
1149 // Emit code for a truncating division by a constant. The dividend register is 998 // Emit code for a truncating division by a constant. The dividend register is
1150 // unchanged and ip gets clobbered. Dividend and result must be different. 999 // unchanged and ip gets clobbered. Dividend and result must be different.
1151 void TruncatingDiv(Register result, Register dividend, int32_t divisor); 1000 void TruncatingDiv(Register result, Register dividend, int32_t divisor);
1152 1001
1153 // --------------------------------------------------------------------------- 1002 // ---------------------------------------------------------------------------
1154 // StatsCounter support 1003 // StatsCounter support
1155 1004
1156 void SetCounter(StatsCounter* counter, int value, 1005 void SetCounter(StatsCounter* counter, int value, Register scratch1,
1157 Register scratch1, Register scratch2); 1006 Register scratch2);
1158 void IncrementCounter(StatsCounter* counter, int value, 1007 void IncrementCounter(StatsCounter* counter, int value, Register scratch1,
1159 Register scratch1, Register scratch2); 1008 Register scratch2);
1160 void DecrementCounter(StatsCounter* counter, int value, 1009 void DecrementCounter(StatsCounter* counter, int value, Register scratch1,
1161 Register scratch1, Register scratch2); 1010 Register scratch2);
1162 1011
1163 1012
1164 // --------------------------------------------------------------------------- 1013 // ---------------------------------------------------------------------------
1165 // Debugging 1014 // Debugging
1166 1015
1167 // Calls Abort(msg) if the condition cond is not satisfied. 1016 // Calls Abort(msg) if the condition cond is not satisfied.
1168 // Use --debug_code to enable. 1017 // Use --debug_code to enable.
1169 void Assert(Condition cond, BailoutReason reason); 1018 void Assert(Condition cond, BailoutReason reason, CRegister cr = cr7);
1170 void AssertFastElements(Register elements); 1019 void AssertFastElements(Register elements);
1171 1020
1172 // Like Assert(), but always enabled. 1021 // Like Assert(), but always enabled.
1173 void Check(Condition cond, BailoutReason reason); 1022 void Check(Condition cond, BailoutReason reason, CRegister cr = cr7);
1174 1023
1175 // Print a message to stdout and abort execution. 1024 // Print a message to stdout and abort execution.
1176 void Abort(BailoutReason msg); 1025 void Abort(BailoutReason reason);
1177 1026
1178 // Verify restrictions about code generated in stubs. 1027 // Verify restrictions about code generated in stubs.
1179 void set_generating_stub(bool value) { generating_stub_ = value; } 1028 void set_generating_stub(bool value) { generating_stub_ = value; }
1180 bool generating_stub() { return generating_stub_; } 1029 bool generating_stub() { return generating_stub_; }
1181 void set_has_frame(bool value) { has_frame_ = value; } 1030 void set_has_frame(bool value) { has_frame_ = value; }
1182 bool has_frame() { return has_frame_; } 1031 bool has_frame() { return has_frame_; }
1183 inline bool AllowThisStubCall(CodeStub* stub); 1032 inline bool AllowThisStubCall(CodeStub* stub);
1184 1033
1185 // EABI variant for double arguments in use.
1186 bool use_eabi_hardfloat() {
1187 #ifdef __arm__
1188 return base::OS::ArmUsingHardFloat();
1189 #elif USE_EABI_HARDFLOAT
1190 return true;
1191 #else
1192 return false;
1193 #endif
1194 }
1195
1196 // --------------------------------------------------------------------------- 1034 // ---------------------------------------------------------------------------
1197 // Number utilities 1035 // Number utilities
1198 1036
1199 // Check whether the value of reg is a power of two and not zero. If not 1037 // Check whether the value of reg is a power of two and not zero. If not
1200 // control continues at the label not_power_of_two. If reg is a power of two 1038 // control continues at the label not_power_of_two. If reg is a power of two
1201 // the register scratch contains the value of (reg - 1) when control falls 1039 // the register scratch contains the value of (reg - 1) when control falls
1202 // through. 1040 // through.
1203 void JumpIfNotPowerOfTwoOrZero(Register reg, 1041 void JumpIfNotPowerOfTwoOrZero(Register reg, Register scratch,
1204 Register scratch,
1205 Label* not_power_of_two_or_zero); 1042 Label* not_power_of_two_or_zero);
1206 // Check whether the value of reg is a power of two and not zero. 1043 // Check whether the value of reg is a power of two and not zero.
1207 // Control falls through if it is, with scratch containing the mask 1044 // Control falls through if it is, with scratch containing the mask
1208 // value (reg - 1). 1045 // value (reg - 1).
1209 // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is 1046 // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is
1210 // zero or negative, or jumps to the 'not_power_of_two' label if the value is 1047 // zero or negative, or jumps to the 'not_power_of_two' label if the value is
1211 // strictly positive but not a power of two. 1048 // strictly positive but not a power of two.
1212 void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg, 1049 void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg, Register scratch,
1213 Register scratch,
1214 Label* zero_and_neg, 1050 Label* zero_and_neg,
1215 Label* not_power_of_two); 1051 Label* not_power_of_two);
1216 1052
1217 // --------------------------------------------------------------------------- 1053 // ---------------------------------------------------------------------------
1218 // Smi utilities 1054 // Bit testing/extraction
1055 //
1056 // Bit numbering is such that the least significant bit is bit 0
1057 // (for consistency between 32/64-bit).
1219 1058
1220 void SmiTag(Register reg, SBit s = LeaveCC) { 1059 // Extract consecutive bits (defined by rangeStart - rangeEnd) from src
1221 add(reg, reg, Operand(reg), s); 1060 // and place them into the least significant bits of dst.
1222 } 1061 inline void ExtractBitRange(Register dst, Register src, int rangeStart,
1223 void SmiTag(Register dst, Register src, SBit s = LeaveCC) { 1062 int rangeEnd, RCBit rc = LeaveRC) {
1224 add(dst, src, Operand(src), s); 1063 DCHECK(rangeStart >= rangeEnd && rangeStart < kBitsPerPointer);
1064 int rotate = (rangeEnd == 0) ? 0 : kBitsPerPointer - rangeEnd;
1065 int width = rangeStart - rangeEnd + 1;
1066 #if V8_TARGET_ARCH_PPC64
1067 rldicl(dst, src, rotate, kBitsPerPointer - width, rc);
1068 #else
1069 rlwinm(dst, src, rotate, kBitsPerPointer - width, kBitsPerPointer - 1, rc);
1070 #endif
1225 } 1071 }
1226 1072
1227 // Try to convert int32 to smi. If the value is to large, preserve 1073 inline void ExtractBit(Register dst, Register src, uint32_t bitNumber,
1228 // the original value and jump to not_a_smi. Destroys scratch and 1074 RCBit rc = LeaveRC) {
1229 // sets flags. 1075 ExtractBitRange(dst, src, bitNumber, bitNumber, rc);
1230 void TrySmiTag(Register reg, Label* not_a_smi) {
1231 TrySmiTag(reg, reg, not_a_smi);
1232 } 1076 }
1233 void TrySmiTag(Register reg, Register src, Label* not_a_smi) { 1077
1234 SmiTag(ip, src, SetCC); 1078 // Extract consecutive bits (defined by mask) from src and place them
1235 b(vs, not_a_smi); 1079 // into the least significant bits of dst.
1236 mov(reg, ip); 1080 inline void ExtractBitMask(Register dst, Register src, uintptr_t mask,
1081 RCBit rc = LeaveRC) {
1082 int start = kBitsPerPointer - 1;
1083 int end;
1084 uintptr_t bit = (1L << start);
1085
1086 while (bit && (mask & bit) == 0) {
1087 start--;
1088 bit >>= 1;
1089 }
1090 end = start;
1091 bit >>= 1;
1092
1093 while (bit && (mask & bit)) {
1094 end--;
1095 bit >>= 1;
1096 }
1097
1098 // 1-bits in mask must be contiguous
1099 DCHECK(bit == 0 || (mask & ((bit << 1) - 1)) == 0);
1100
1101 ExtractBitRange(dst, src, start, end, rc);
1102 }
1103
1104 // Test single bit in value.
1105 inline void TestBit(Register value, int bitNumber, Register scratch = r0) {
1106 ExtractBitRange(scratch, value, bitNumber, bitNumber, SetRC);
1107 }
1108
1109 // Test consecutive bit range in value. Range is defined by
1110 // rangeStart - rangeEnd.
1111 inline void TestBitRange(Register value, int rangeStart, int rangeEnd,
1112 Register scratch = r0) {
1113 ExtractBitRange(scratch, value, rangeStart, rangeEnd, SetRC);
1114 }
1115
1116 // Test consecutive bit range in value. Range is defined by mask.
1117 inline void TestBitMask(Register value, uintptr_t mask,
1118 Register scratch = r0) {
1119 ExtractBitMask(scratch, value, mask, SetRC);
1237 } 1120 }
1238 1121
1239 1122
1240 void SmiUntag(Register reg, SBit s = LeaveCC) { 1123 // ---------------------------------------------------------------------------
1241 mov(reg, Operand::SmiUntag(reg), s); 1124 // Smi utilities
1125
1126 // Shift left by 1
1127 void SmiTag(Register reg, RCBit rc = LeaveRC) { SmiTag(reg, reg, rc); }
1128 void SmiTag(Register dst, Register src, RCBit rc = LeaveRC) {
1129 ShiftLeftImm(dst, src, Operand(kSmiShift), rc);
1242 } 1130 }
1243 void SmiUntag(Register dst, Register src, SBit s = LeaveCC) { 1131
1244 mov(dst, Operand::SmiUntag(src), s); 1132 #if !V8_TARGET_ARCH_PPC64
1133 // Test for overflow < 0: use BranchOnOverflow() or BranchOnNoOverflow().
1134 void SmiTagCheckOverflow(Register reg, Register overflow);
1135 void SmiTagCheckOverflow(Register dst, Register src, Register overflow);
1136
1137 inline void JumpIfNotSmiCandidate(Register value, Register scratch,
1138 Label* not_smi_label) {
1139 // High bits must be identical to fit into an Smi
1140 addis(scratch, value, Operand(0x40000000u >> 16));
1141 cmpi(scratch, Operand::Zero());
1142 blt(not_smi_label);
1143 }
1144 #endif
1145 inline void TestUnsignedSmiCandidate(Register value, Register scratch) {
1146 // The test is different for unsigned int values. Since we need
1147 // the value to be in the range of a positive smi, we can't
1148 // handle any of the high bits being set in the value.
1149 TestBitRange(value, kBitsPerPointer - 1, kBitsPerPointer - 1 - kSmiShift,
1150 scratch);
1151 }
1152 inline void JumpIfNotUnsignedSmiCandidate(Register value, Register scratch,
1153 Label* not_smi_label) {
1154 TestUnsignedSmiCandidate(value, scratch);
1155 bne(not_smi_label, cr0);
1156 }
1157
1158 void SmiUntag(Register reg, RCBit rc = LeaveRC) { SmiUntag(reg, reg, rc); }
1159
1160 void SmiUntag(Register dst, Register src, RCBit rc = LeaveRC) {
1161 ShiftRightArithImm(dst, src, kSmiShift, rc);
1162 }
1163
1164 void SmiToPtrArrayOffset(Register dst, Register src) {
1165 #if V8_TARGET_ARCH_PPC64
1166 STATIC_ASSERT(kSmiTag == 0 && kSmiShift > kPointerSizeLog2);
1167 ShiftRightArithImm(dst, src, kSmiShift - kPointerSizeLog2);
1168 #else
1169 STATIC_ASSERT(kSmiTag == 0 && kSmiShift < kPointerSizeLog2);
1170 ShiftLeftImm(dst, src, Operand(kPointerSizeLog2 - kSmiShift));
1171 #endif
1172 }
1173
1174 void SmiToByteArrayOffset(Register dst, Register src) { SmiUntag(dst, src); }
1175
1176 void SmiToShortArrayOffset(Register dst, Register src) {
1177 #if V8_TARGET_ARCH_PPC64
1178 STATIC_ASSERT(kSmiTag == 0 && kSmiShift > 1);
1179 ShiftRightArithImm(dst, src, kSmiShift - 1);
1180 #else
1181 STATIC_ASSERT(kSmiTag == 0 && kSmiShift == 1);
1182 if (!dst.is(src)) {
1183 mr(dst, src);
1184 }
1185 #endif
1186 }
1187
1188 void SmiToIntArrayOffset(Register dst, Register src) {
1189 #if V8_TARGET_ARCH_PPC64
1190 STATIC_ASSERT(kSmiTag == 0 && kSmiShift > 2);
1191 ShiftRightArithImm(dst, src, kSmiShift - 2);
1192 #else
1193 STATIC_ASSERT(kSmiTag == 0 && kSmiShift < 2);
1194 ShiftLeftImm(dst, src, Operand(2 - kSmiShift));
1195 #endif
1196 }
1197
1198 #define SmiToFloatArrayOffset SmiToIntArrayOffset
1199
1200 void SmiToDoubleArrayOffset(Register dst, Register src) {
1201 #if V8_TARGET_ARCH_PPC64
1202 STATIC_ASSERT(kSmiTag == 0 && kSmiShift > kDoubleSizeLog2);
1203 ShiftRightArithImm(dst, src, kSmiShift - kDoubleSizeLog2);
1204 #else
1205 STATIC_ASSERT(kSmiTag == 0 && kSmiShift < kDoubleSizeLog2);
1206 ShiftLeftImm(dst, src, Operand(kDoubleSizeLog2 - kSmiShift));
1207 #endif
1208 }
1209
1210 void SmiToArrayOffset(Register dst, Register src, int elementSizeLog2) {
1211 if (kSmiShift < elementSizeLog2) {
1212 ShiftLeftImm(dst, src, Operand(elementSizeLog2 - kSmiShift));
1213 } else if (kSmiShift > elementSizeLog2) {
1214 ShiftRightArithImm(dst, src, kSmiShift - elementSizeLog2);
1215 } else if (!dst.is(src)) {
1216 mr(dst, src);
1217 }
1218 }
1219
1220 void IndexToArrayOffset(Register dst, Register src, int elementSizeLog2,
1221 bool isSmi) {
1222 if (isSmi) {
1223 SmiToArrayOffset(dst, src, elementSizeLog2);
1224 } else {
1225 ShiftLeftImm(dst, src, Operand(elementSizeLog2));
1226 }
1245 } 1227 }
1246 1228
1247 // Untag the source value into destination and jump if source is a smi. 1229 // Untag the source value into destination and jump if source is a smi.
1248 // Souce and destination can be the same register. 1230 // Souce and destination can be the same register.
1249 void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case); 1231 void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case);
1250 1232
1251 // Untag the source value into destination and jump if source is not a smi. 1233 // Untag the source value into destination and jump if source is not a smi.
1252 // Souce and destination can be the same register. 1234 // Souce and destination can be the same register.
1253 void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case); 1235 void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case);
1254 1236
1255 // Test if the register contains a smi (Z == 0 (eq) if true). 1237 inline void TestIfSmi(Register value, Register scratch) {
1256 inline void SmiTst(Register value) { 1238 TestBit(value, 0, scratch); // tst(value, Operand(kSmiTagMask));
1257 tst(value, Operand(kSmiTagMask));
1258 } 1239 }
1259 inline void NonNegativeSmiTst(Register value) { 1240
1260 tst(value, Operand(kSmiTagMask | kSmiSignMask)); 1241 inline void TestIfPositiveSmi(Register value, Register scratch) {
1242 STATIC_ASSERT((kSmiTagMask | kSmiSignMask) ==
1243 (intptr_t)(1UL << (kBitsPerPointer - 1) | 1));
1244 #if V8_TARGET_ARCH_PPC64
1245 rldicl(scratch, value, 1, kBitsPerPointer - 2, SetRC);
1246 #else
1247 rlwinm(scratch, value, 1, kBitsPerPointer - 2, kBitsPerPointer - 1, SetRC);
1248 #endif
1261 } 1249 }
1262 // Jump if the register contains a smi. 1250
1251 // Jump the register contains a smi.
1263 inline void JumpIfSmi(Register value, Label* smi_label) { 1252 inline void JumpIfSmi(Register value, Label* smi_label) {
1264 tst(value, Operand(kSmiTagMask)); 1253 TestIfSmi(value, r0);
1265 b(eq, smi_label); 1254 beq(smi_label, cr0); // branch if SMI
1266 } 1255 }
1267 // Jump if either of the registers contain a non-smi. 1256 // Jump if either of the registers contain a non-smi.
1268 inline void JumpIfNotSmi(Register value, Label* not_smi_label) { 1257 inline void JumpIfNotSmi(Register value, Label* not_smi_label) {
1269 tst(value, Operand(kSmiTagMask)); 1258 TestIfSmi(value, r0);
1270 b(ne, not_smi_label); 1259 bne(not_smi_label, cr0);
1271 } 1260 }
1272 // Jump if either of the registers contain a non-smi. 1261 // Jump if either of the registers contain a non-smi.
1273 void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi); 1262 void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
1274 // Jump if either of the registers contain a smi. 1263 // Jump if either of the registers contain a smi.
1275 void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi); 1264 void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
1276 1265
1277 // Abort execution if argument is a smi, enabled via --debug-code. 1266 // Abort execution if argument is a smi, enabled via --debug-code.
1278 void AssertNotSmi(Register object); 1267 void AssertNotSmi(Register object);
1279 void AssertSmi(Register object); 1268 void AssertSmi(Register object);
1280 1269
1270
1271 #if V8_TARGET_ARCH_PPC64
1272 inline void TestIfInt32(Register value, Register scratch1, Register scratch2,
1273 CRegister cr = cr7) {
1274 // High bits must be identical to fit into an 32-bit integer
1275 srawi(scratch1, value, 31);
1276 sradi(scratch2, value, 32);
1277 cmp(scratch1, scratch2, cr);
1278 }
1279 #else
1280 inline void TestIfInt32(Register hi_word, Register lo_word, Register scratch,
1281 CRegister cr = cr7) {
1282 // High bits must be identical to fit into an 32-bit integer
1283 srawi(scratch, lo_word, 31);
1284 cmp(scratch, hi_word, cr);
1285 }
1286 #endif
1287
1281 // Abort execution if argument is not a string, enabled via --debug-code. 1288 // Abort execution if argument is not a string, enabled via --debug-code.
1282 void AssertString(Register object); 1289 void AssertString(Register object);
1283 1290
1284 // Abort execution if argument is not a name, enabled via --debug-code. 1291 // Abort execution if argument is not a name, enabled via --debug-code.
1285 void AssertName(Register object); 1292 void AssertName(Register object);
1286 1293
1287 // Abort execution if argument is not undefined or an AllocationSite, enabled 1294 // Abort execution if argument is not undefined or an AllocationSite, enabled
1288 // via --debug-code. 1295 // via --debug-code.
1289 void AssertUndefinedOrAllocationSite(Register object, Register scratch); 1296 void AssertUndefinedOrAllocationSite(Register object, Register scratch);
1290 1297
1291 // Abort execution if reg is not the root value with the given index, 1298 // Abort execution if reg is not the root value with the given index,
1292 // enabled via --debug-code. 1299 // enabled via --debug-code.
1293 void AssertIsRoot(Register reg, Heap::RootListIndex index); 1300 void AssertIsRoot(Register reg, Heap::RootListIndex index);
1294 1301
1295 // --------------------------------------------------------------------------- 1302 // ---------------------------------------------------------------------------
1296 // HeapNumber utilities 1303 // HeapNumber utilities
1297 1304
1298 void JumpIfNotHeapNumber(Register object, 1305 void JumpIfNotHeapNumber(Register object, Register heap_number_map,
1299 Register heap_number_map, 1306 Register scratch, Label* on_not_heap_number);
1300 Register scratch,
1301 Label* on_not_heap_number);
1302 1307
1303 // --------------------------------------------------------------------------- 1308 // ---------------------------------------------------------------------------
1304 // String utilities 1309 // String utilities
1305 1310
1306 // Generate code to do a lookup in the number string cache. If the number in 1311 // Generate code to do a lookup in the number string cache. If the number in
1307 // the register object is found in the cache the generated code falls through 1312 // the register object is found in the cache the generated code falls through
1308 // with the result in the result register. The object and the result register 1313 // with the result in the result register. The object and the result register
1309 // can be the same. If the number is not found in the cache the code jumps to 1314 // can be the same. If the number is not found in the cache the code jumps to
1310 // the label not_found with only the content of register object unchanged. 1315 // the label not_found with only the content of register object unchanged.
1311 void LookupNumberStringCache(Register object, 1316 void LookupNumberStringCache(Register object, Register result,
1312 Register result, 1317 Register scratch1, Register scratch2,
1313 Register scratch1, 1318 Register scratch3, Label* not_found);
1314 Register scratch2,
1315 Register scratch3,
1316 Label* not_found);
1317 1319
1318 // Checks if both objects are sequential one-byte strings and jumps to label 1320 // Checks if both objects are sequential one-byte strings and jumps to label
1319 // if either is not. Assumes that neither object is a smi. 1321 // if either is not. Assumes that neither object is a smi.
1320 void JumpIfNonSmisNotBothSequentialOneByteStrings(Register object1, 1322 void JumpIfNonSmisNotBothSequentialOneByteStrings(Register object1,
1321 Register object2, 1323 Register object2,
1322 Register scratch1, 1324 Register scratch1,
1323 Register scratch2, 1325 Register scratch2,
1324 Label* failure); 1326 Label* failure);
1325 1327
1326 // Checks if both objects are sequential one-byte strings and jumps to label 1328 // Checks if both objects are sequential one-byte strings and jumps to label
1327 // if either is not. 1329 // if either is not.
1328 void JumpIfNotBothSequentialOneByteStrings(Register first, Register second, 1330 void JumpIfNotBothSequentialOneByteStrings(Register first, Register second,
1329 Register scratch1, 1331 Register scratch1,
1330 Register scratch2, 1332 Register scratch2,
1331 Label* not_flat_one_byte_strings); 1333 Label* not_flat_one_byte_strings);
1332 1334
1333 // Checks if both instance types are sequential one-byte strings and jumps to 1335 // Checks if both instance types are sequential one-byte strings and jumps to
1334 // label if either is not. 1336 // label if either is not.
1335 void JumpIfBothInstanceTypesAreNotSequentialOneByte( 1337 void JumpIfBothInstanceTypesAreNotSequentialOneByte(
1336 Register first_object_instance_type, Register second_object_instance_type, 1338 Register first_object_instance_type, Register second_object_instance_type,
1337 Register scratch1, Register scratch2, Label* failure); 1339 Register scratch1, Register scratch2, Label* failure);
1338 1340
1339 // Check if instance type is sequential one-byte string and jump to label if 1341 // Check if instance type is sequential one-byte string and jump to label if
1340 // it is not. 1342 // it is not.
1341 void JumpIfInstanceTypeIsNotSequentialOneByte(Register type, Register scratch, 1343 void JumpIfInstanceTypeIsNotSequentialOneByte(Register type, Register scratch,
1342 Label* failure); 1344 Label* failure);
1343 1345
1344 void JumpIfNotUniqueNameInstanceType(Register reg, Label* not_unique_name); 1346 void JumpIfNotUniqueNameInstanceType(Register reg, Label* not_unique_name);
1345 1347
1346 void EmitSeqStringSetCharCheck(Register string, 1348 void EmitSeqStringSetCharCheck(Register string, Register index,
1347 Register index, 1349 Register value, uint32_t encoding_mask);
1348 Register value,
1349 uint32_t encoding_mask);
1350 1350
1351 // --------------------------------------------------------------------------- 1351 // ---------------------------------------------------------------------------
1352 // Patching helpers. 1352 // Patching helpers.
1353 1353
1354 // Get the location of a relocated constant (its address in the constant pool) 1354 // Retrieve/patch the relocated value (lis/ori pair or constant pool load).
1355 // from its load site. 1355 void GetRelocatedValue(Register location, Register result, Register scratch);
1356 void GetRelocatedValueLocation(Register ldr_location, Register result, 1356 void SetRelocatedValue(Register location, Register scratch,
1357 Register scratch); 1357 Register new_value);
1358
1359 1358
1360 void ClampUint8(Register output_reg, Register input_reg); 1359 void ClampUint8(Register output_reg, Register input_reg);
1361 1360
1362 void ClampDoubleToUint8(Register result_reg, 1361 // Saturate a value into 8-bit unsigned integer
1363 DwVfpRegister input_reg, 1362 // if input_value < 0, output_value is 0
1364 LowDwVfpRegister double_scratch); 1363 // if input_value > 255, output_value is 255
1364 // otherwise output_value is the (int)input_value (round to nearest)
1365 void ClampDoubleToUint8(Register result_reg, DoubleRegister input_reg,
1366 DoubleRegister temp_double_reg);
1365 1367
1366 1368
1367 void LoadInstanceDescriptors(Register map, Register descriptors); 1369 void LoadInstanceDescriptors(Register map, Register descriptors);
1368 void EnumLength(Register dst, Register map); 1370 void EnumLength(Register dst, Register map);
1369 void NumberOfOwnDescriptors(Register dst, Register map); 1371 void NumberOfOwnDescriptors(Register dst, Register map);
1370 1372
1371 template<typename Field> 1373 template <typename Field>
1372 void DecodeField(Register dst, Register src) { 1374 void DecodeField(Register dst, Register src) {
1373 Ubfx(dst, src, Field::kShift, Field::kSize); 1375 ExtractBitRange(dst, src, Field::kShift + Field::kSize - 1, Field::kShift);
1374 } 1376 }
1375 1377
1376 template<typename Field> 1378 template <typename Field>
1377 void DecodeField(Register reg) { 1379 void DecodeField(Register reg) {
1378 DecodeField<Field>(reg, reg); 1380 DecodeField<Field>(reg, reg);
1379 } 1381 }
1380 1382
1381 template<typename Field> 1383 template <typename Field>
1382 void DecodeFieldToSmi(Register dst, Register src) { 1384 void DecodeFieldToSmi(Register dst, Register src) {
1383 static const int shift = Field::kShift; 1385 #if V8_TARGET_ARCH_PPC64
1384 static const int mask = Field::kMask >> shift << kSmiTagSize; 1386 DecodeField<Field>(dst, src);
1385 STATIC_ASSERT((mask & (0x80000000u >> (kSmiTagSize - 1))) == 0); 1387 SmiTag(dst);
1386 STATIC_ASSERT(kSmiTag == 0); 1388 #else
1387 if (shift < kSmiTagSize) { 1389 // 32-bit can do this in one instruction:
1388 mov(dst, Operand(src, LSL, kSmiTagSize - shift)); 1390 int start = Field::kSize + kSmiShift - 1;
1389 and_(dst, dst, Operand(mask)); 1391 int end = kSmiShift;
1390 } else if (shift > kSmiTagSize) { 1392 int rotate = kSmiShift - Field::kShift;
1391 mov(dst, Operand(src, LSR, shift - kSmiTagSize)); 1393 if (rotate < 0) {
1392 and_(dst, dst, Operand(mask)); 1394 rotate += kBitsPerPointer;
1393 } else {
1394 and_(dst, src, Operand(mask));
1395 } 1395 }
1396 rlwinm(dst, src, rotate, kBitsPerPointer - start - 1,
1397 kBitsPerPointer - end - 1);
1398 #endif
1396 } 1399 }
1397 1400
1398 template<typename Field> 1401 template <typename Field>
1399 void DecodeFieldToSmi(Register reg) { 1402 void DecodeFieldToSmi(Register reg) {
1400 DecodeField<Field>(reg, reg); 1403 DecodeFieldToSmi<Field>(reg, reg);
1401 } 1404 }
1402 1405
1403 // Activation support. 1406 // Activation support.
1404 void EnterFrame(StackFrame::Type type, 1407 void EnterFrame(StackFrame::Type type,
1405 bool load_constant_pool_pointer_reg = false); 1408 bool load_constant_pool_pointer_reg = false);
1406 // Returns the pc offset at which the frame ends. 1409 // Returns the pc offset at which the frame ends.
1407 int LeaveFrame(StackFrame::Type type); 1410 int LeaveFrame(StackFrame::Type type, int stack_adjustment = 0);
1408 1411
1409 // Expects object in r0 and returns map with validated enum cache 1412 // Expects object in r0 and returns map with validated enum cache
1410 // in r0. Assumes that any other register can be used as a scratch. 1413 // in r0. Assumes that any other register can be used as a scratch.
1411 void CheckEnumCache(Register null_value, Label* call_runtime); 1414 void CheckEnumCache(Register null_value, Label* call_runtime);
1412 1415
1413 // AllocationMemento support. Arrays may have an associated 1416 // AllocationMemento support. Arrays may have an associated
1414 // AllocationMemento object that can be checked for in order to pretransition 1417 // AllocationMemento object that can be checked for in order to pretransition
1415 // to another type. 1418 // to another type.
1416 // On entry, receiver_reg should point to the array object. 1419 // On entry, receiver_reg should point to the array object.
1417 // scratch_reg gets clobbered. 1420 // scratch_reg gets clobbered.
1418 // If allocation info is present, condition flags are set to eq. 1421 // If allocation info is present, condition flags are set to eq.
1419 void TestJSArrayForAllocationMemento(Register receiver_reg, 1422 void TestJSArrayForAllocationMemento(Register receiver_reg,
1420 Register scratch_reg, 1423 Register scratch_reg,
1421 Label* no_memento_found); 1424 Label* no_memento_found);
1422 1425
1423 void JumpIfJSArrayHasAllocationMemento(Register receiver_reg, 1426 void JumpIfJSArrayHasAllocationMemento(Register receiver_reg,
1424 Register scratch_reg, 1427 Register scratch_reg,
1425 Label* memento_found) { 1428 Label* memento_found) {
1426 Label no_memento_found; 1429 Label no_memento_found;
1427 TestJSArrayForAllocationMemento(receiver_reg, scratch_reg, 1430 TestJSArrayForAllocationMemento(receiver_reg, scratch_reg,
1428 &no_memento_found); 1431 &no_memento_found);
1429 b(eq, memento_found); 1432 beq(memento_found);
1430 bind(&no_memento_found); 1433 bind(&no_memento_found);
1431 } 1434 }
1432 1435
1433 // Jumps to found label if a prototype map has dictionary elements. 1436 // Jumps to found label if a prototype map has dictionary elements.
1434 void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0, 1437 void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0,
1435 Register scratch1, Label* found); 1438 Register scratch1, Label* found);
1436 1439
1437 private: 1440 private:
1438 void CallCFunctionHelper(Register function, 1441 static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
1439 int num_reg_arguments, 1442
1443 void CallCFunctionHelper(Register function, int num_reg_arguments,
1440 int num_double_arguments); 1444 int num_double_arguments);
1441 1445
1442 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); 1446 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al,
1447 CRegister cr = cr7);
1443 1448
1444 // Helper functions for generating invokes. 1449 // Helper functions for generating invokes.
1445 void InvokePrologue(const ParameterCount& expected, 1450 void InvokePrologue(const ParameterCount& expected,
1446 const ParameterCount& actual, 1451 const ParameterCount& actual, Handle<Code> code_constant,
1447 Handle<Code> code_constant, 1452 Register code_reg, Label* done,
1448 Register code_reg, 1453 bool* definitely_mismatches, InvokeFlag flag,
1449 Label* done,
1450 bool* definitely_mismatches,
1451 InvokeFlag flag,
1452 const CallWrapper& call_wrapper); 1454 const CallWrapper& call_wrapper);
1453 1455
1454 void InitializeNewString(Register string, 1456 void InitializeNewString(Register string, Register length,
1455 Register length, 1457 Heap::RootListIndex map_index, Register scratch1,
1456 Heap::RootListIndex map_index,
1457 Register scratch1,
1458 Register scratch2); 1458 Register scratch2);
1459 1459
1460 // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace. 1460 // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
1461 void InNewSpace(Register object, 1461 void InNewSpace(Register object, Register scratch,
1462 Register scratch,
1463 Condition cond, // eq for new space, ne otherwise. 1462 Condition cond, // eq for new space, ne otherwise.
1464 Label* branch); 1463 Label* branch);
1465 1464
1466 // Helper for finding the mark bits for an address. Afterwards, the 1465 // Helper for finding the mark bits for an address. Afterwards, the
1467 // bitmap register points at the word with the mark bits and the mask 1466 // bitmap register points at the word with the mark bits and the mask
1468 // the position of the first bit. Leaves addr_reg unchanged. 1467 // the position of the first bit. Leaves addr_reg unchanged.
1469 inline void GetMarkBits(Register addr_reg, 1468 inline void GetMarkBits(Register addr_reg, Register bitmap_reg,
1470 Register bitmap_reg,
1471 Register mask_reg); 1469 Register mask_reg);
1472 1470
1473 // Helper for throwing exceptions. Compute a handler address and jump to 1471 // Helper for throwing exceptions. Compute a handler address and jump to
1474 // it. See the implementation for register usage. 1472 // it. See the implementation for register usage.
1475 void JumpToHandlerEntry(); 1473 void JumpToHandlerEntry();
1476 1474
1477 // Compute memory operands for safepoint stack slots. 1475 // Compute memory operands for safepoint stack slots.
1478 static int SafepointRegisterStackIndex(int reg_code); 1476 static int SafepointRegisterStackIndex(int reg_code);
1479 MemOperand SafepointRegisterSlot(Register reg); 1477 MemOperand SafepointRegisterSlot(Register reg);
1480 MemOperand SafepointRegistersAndDoublesSlot(Register reg); 1478 MemOperand SafepointRegistersAndDoublesSlot(Register reg);
1481 1479
1482 // Loads the constant pool pointer (pp) register. 1480 #if V8_OOL_CONSTANT_POOL
1483 void LoadConstantPoolPointerRegister(); 1481 // Loads the constant pool pointer (kConstantPoolRegister).
1482 enum CodeObjectAccessMethod { CAN_USE_IP, CONSTRUCT_INTERNAL_REFERENCE };
1483 void LoadConstantPoolPointerRegister(CodeObjectAccessMethod access_method,
1484 int ip_code_entry_delta = 0);
1485 #endif
1484 1486
1485 bool generating_stub_; 1487 bool generating_stub_;
1486 bool has_frame_; 1488 bool has_frame_;
1487 // This handle will be patched with the code object on installation. 1489 // This handle will be patched with the code object on installation.
1488 Handle<Object> code_object_; 1490 Handle<Object> code_object_;
1489 1491
1490 // Needs access to SafepointRegisterStackIndex for compiled frame 1492 // Needs access to SafepointRegisterStackIndex for compiled frame
1491 // traversal. 1493 // traversal.
1492 friend class StandardFrame; 1494 friend class StandardFrame;
1493 }; 1495 };
1494 1496
1495 1497
1496 // The code patcher is used to patch (typically) small parts of code e.g. for 1498 // The code patcher is used to patch (typically) small parts of code e.g. for
1497 // debugging and other types of instrumentation. When using the code patcher 1499 // debugging and other types of instrumentation. When using the code patcher
1498 // the exact number of bytes specified must be emitted. It is not legal to emit 1500 // the exact number of bytes specified must be emitted. It is not legal to emit
1499 // relocation information. If any of these constraints are violated it causes 1501 // relocation information. If any of these constraints are violated it causes
1500 // an assertion to fail. 1502 // an assertion to fail.
1501 class CodePatcher { 1503 class CodePatcher {
1502 public: 1504 public:
1503 enum FlushICache { 1505 enum FlushICache { FLUSH, DONT_FLUSH };
1504 FLUSH,
1505 DONT_FLUSH
1506 };
1507 1506
1508 CodePatcher(byte* address, 1507 CodePatcher(byte* address, int instructions, FlushICache flush_cache = FLUSH);
1509 int instructions,
1510 FlushICache flush_cache = FLUSH);
1511 virtual ~CodePatcher(); 1508 virtual ~CodePatcher();
1512 1509
1513 // Macro assembler to emit code. 1510 // Macro assembler to emit code.
1514 MacroAssembler* masm() { return &masm_; } 1511 MacroAssembler* masm() { return &masm_; }
1515 1512
1516 // Emit an instruction directly. 1513 // Emit an instruction directly.
1517 void Emit(Instr instr); 1514 void Emit(Instr instr);
1518 1515
1519 // Emit an address directly.
1520 void Emit(Address addr);
1521
1522 // Emit the condition part of an instruction leaving the rest of the current 1516 // Emit the condition part of an instruction leaving the rest of the current
1523 // instruction unchanged. 1517 // instruction unchanged.
1524 void EmitCondition(Condition cond); 1518 void EmitCondition(Condition cond);
1525 1519
1526 private: 1520 private:
1527 byte* address_; // The address of the code being patched. 1521 byte* address_; // The address of the code being patched.
1528 int size_; // Number of bytes of the expected patch size. 1522 int size_; // Number of bytes of the expected patch size.
1529 MacroAssembler masm_; // Macro assembler used to generate the code. 1523 MacroAssembler masm_; // Macro assembler used to generate the code.
1530 FlushICache flush_cache_; // Whether to flush the I cache after patching. 1524 FlushICache flush_cache_; // Whether to flush the I cache after patching.
1531 }; 1525 };
1532 1526
1533 1527
1534 // ----------------------------------------------------------------------------- 1528 // -----------------------------------------------------------------------------
1535 // Static helper functions. 1529 // Static helper functions.
1536 1530
1537 inline MemOperand ContextOperand(Register context, int index) { 1531 inline MemOperand ContextOperand(Register context, int index) {
1538 return MemOperand(context, Context::SlotOffset(index)); 1532 return MemOperand(context, Context::SlotOffset(index));
1539 } 1533 }
1540 1534
1541 1535
1542 inline MemOperand GlobalObjectOperand() { 1536 inline MemOperand GlobalObjectOperand() {
1543 return ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX); 1537 return ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX);
1544 } 1538 }
1545 1539
1546 1540
1547 #ifdef GENERATED_CODE_COVERAGE 1541 #ifdef GENERATED_CODE_COVERAGE
1548 #define CODE_COVERAGE_STRINGIFY(x) #x 1542 #define CODE_COVERAGE_STRINGIFY(x) #x
1549 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) 1543 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
1550 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) 1544 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
1551 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> 1545 #define ACCESS_MASM(masm) \
1546 masm->stop(__FILE_LINE__); \
1547 masm->
1552 #else 1548 #else
1553 #define ACCESS_MASM(masm) masm-> 1549 #define ACCESS_MASM(masm) masm->
1554 #endif 1550 #endif
1551 }
1552 } // namespace v8::internal
1555 1553
1556 1554 #endif // V8_PPC_MACRO_ASSEMBLER_PPC_H_
1557 } } // namespace v8::internal
1558
1559 #endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_
OLDNEW
« no previous file with comments | « src/ppc/lithium-ppc.cc ('k') | src/ppc/macro-assembler-ppc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698