89fda10b0596e28bbac4ff7cd40e8df50f1c26d7
[platform/upstream/nodejs.git] / deps / v8 / src / mips64 / builtins-mips64.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5
6
7 #include "src/v8.h"
8
9 #if V8_TARGET_ARCH_MIPS64
10
11 #include "src/codegen.h"
12 #include "src/debug.h"
13 #include "src/deoptimizer.h"
14 #include "src/full-codegen.h"
15 #include "src/runtime/runtime.h"
16
17 namespace v8 {
18 namespace internal {
19
20
21 #define __ ACCESS_MASM(masm)
22
23
24 void Builtins::Generate_Adaptor(MacroAssembler* masm,
25                                 CFunctionId id,
26                                 BuiltinExtraArguments extra_args) {
27   // ----------- S t a t e -------------
28   //  -- a0                 : number of arguments excluding receiver
29   //  -- a1                 : called function (only guaranteed when
30   //  --                      extra_args requires it)
31   //  -- cp                 : context
32   //  -- sp[0]              : last argument
33   //  -- ...
34   //  -- sp[8 * (argc - 1)] : first argument
35   //  -- sp[8 * agrc]       : receiver
36   // -----------------------------------
37
38   // Insert extra arguments.
39   int num_extra_args = 0;
40   if (extra_args == NEEDS_CALLED_FUNCTION) {
41     num_extra_args = 1;
42     __ push(a1);
43   } else {
44     DCHECK(extra_args == NO_EXTRA_ARGUMENTS);
45   }
46
47   // JumpToExternalReference expects a0 to contain the number of arguments
48   // including the receiver and the extra arguments.
49   __ Daddu(a0, a0, num_extra_args + 1);
50   __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
51 }
52
53
54 // Load the built-in InternalArray function from the current context.
55 static void GenerateLoadInternalArrayFunction(MacroAssembler* masm,
56                                               Register result) {
57   // Load the native context.
58
59   __ ld(result,
60         MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
61   __ ld(result,
62         FieldMemOperand(result, GlobalObject::kNativeContextOffset));
63   // Load the InternalArray function from the native context.
64   __ ld(result,
65          MemOperand(result,
66                     Context::SlotOffset(
67                         Context::INTERNAL_ARRAY_FUNCTION_INDEX)));
68 }
69
70
71 // Load the built-in Array function from the current context.
72 static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
73   // Load the native context.
74
75   __ ld(result,
76         MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
77   __ ld(result,
78         FieldMemOperand(result, GlobalObject::kNativeContextOffset));
79   // Load the Array function from the native context.
80   __ ld(result,
81         MemOperand(result,
82                    Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
83 }
84
85
86 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
87   // ----------- S t a t e -------------
88   //  -- a0     : number of arguments
89   //  -- ra     : return address
90   //  -- sp[...]: constructor arguments
91   // -----------------------------------
92   Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
93
94   // Get the InternalArray function.
95   GenerateLoadInternalArrayFunction(masm, a1);
96
97   if (FLAG_debug_code) {
98     // Initial map for the builtin InternalArray functions should be maps.
99     __ ld(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
100     __ SmiTst(a2, a4);
101     __ Assert(ne, kUnexpectedInitialMapForInternalArrayFunction,
102               a4, Operand(zero_reg));
103     __ GetObjectType(a2, a3, a4);
104     __ Assert(eq, kUnexpectedInitialMapForInternalArrayFunction,
105               a4, Operand(MAP_TYPE));
106   }
107
108   // Run the native code for the InternalArray function called as a normal
109   // function.
110   // Tail call a stub.
111   InternalArrayConstructorStub stub(masm->isolate());
112   __ TailCallStub(&stub);
113 }
114
115
116 void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
117   // ----------- S t a t e -------------
118   //  -- a0     : number of arguments
119   //  -- ra     : return address
120   //  -- sp[...]: constructor arguments
121   // -----------------------------------
122   Label generic_array_code;
123
124   // Get the Array function.
125   GenerateLoadArrayFunction(masm, a1);
126
127   if (FLAG_debug_code) {
128     // Initial map for the builtin Array functions should be maps.
129     __ ld(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
130     __ SmiTst(a2, a4);
131     __ Assert(ne, kUnexpectedInitialMapForArrayFunction1,
132               a4, Operand(zero_reg));
133     __ GetObjectType(a2, a3, a4);
134     __ Assert(eq, kUnexpectedInitialMapForArrayFunction2,
135               a4, Operand(MAP_TYPE));
136   }
137
138   // Run the native code for the Array function called as a normal function.
139   // Tail call a stub.
140   __ mov(a3, a1);
141   __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
142   ArrayConstructorStub stub(masm->isolate());
143   __ TailCallStub(&stub);
144 }
145
146
147 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
148   // ----------- S t a t e -------------
149   //  -- a0                     : number of arguments
150   //  -- a1                     : constructor function
151   //  -- ra                     : return address
152   //  -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
153   //  -- sp[argc * 8]           : receiver
154   // -----------------------------------
155   Counters* counters = masm->isolate()->counters();
156   __ IncrementCounter(counters->string_ctor_calls(), 1, a2, a3);
157
158   Register function = a1;
159   if (FLAG_debug_code) {
160     __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, a2);
161     __ Assert(eq, kUnexpectedStringFunction, function, Operand(a2));
162   }
163
164   // Load the first arguments in a0 and get rid of the rest.
165   Label no_arguments;
166   __ Branch(&no_arguments, eq, a0, Operand(zero_reg));
167   // First args = sp[(argc - 1) * 8].
168   __ Dsubu(a0, a0, Operand(1));
169   __ dsll(a0, a0, kPointerSizeLog2);
170   __ Daddu(sp, a0, sp);
171   __ ld(a0, MemOperand(sp));
172   // sp now point to args[0], drop args[0] + receiver.
173   __ Drop(2);
174
175   Register argument = a2;
176   Label not_cached, argument_is_string;
177   __ LookupNumberStringCache(a0,        // Input.
178                              argument,  // Result.
179                              a3,        // Scratch.
180                              a4,        // Scratch.
181                              a5,        // Scratch.
182                              &not_cached);
183   __ IncrementCounter(counters->string_ctor_cached_number(), 1, a3, a4);
184   __ bind(&argument_is_string);
185
186   // ----------- S t a t e -------------
187   //  -- a2     : argument converted to string
188   //  -- a1     : constructor function
189   //  -- ra     : return address
190   // -----------------------------------
191
192   Label gc_required;
193   __ Allocate(JSValue::kSize,
194               v0,  // Result.
195               a3,  // Scratch.
196               a4,  // Scratch.
197               &gc_required,
198               TAG_OBJECT);
199
200   // Initialising the String Object.
201   Register map = a3;
202   __ LoadGlobalFunctionInitialMap(function, map, a4);
203   if (FLAG_debug_code) {
204     __ lbu(a4, FieldMemOperand(map, Map::kInstanceSizeOffset));
205     __ Assert(eq, kUnexpectedStringWrapperInstanceSize,
206         a4, Operand(JSValue::kSize >> kPointerSizeLog2));
207     __ lbu(a4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
208     __ Assert(eq, kUnexpectedUnusedPropertiesOfStringWrapper,
209         a4, Operand(zero_reg));
210   }
211   __ sd(map, FieldMemOperand(v0, HeapObject::kMapOffset));
212
213   __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex);
214   __ sd(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset));
215   __ sd(a3, FieldMemOperand(v0, JSObject::kElementsOffset));
216
217   __ sd(argument, FieldMemOperand(v0, JSValue::kValueOffset));
218
219   // Ensure the object is fully initialized.
220   STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
221
222   __ Ret();
223
224   // The argument was not found in the number to string cache. Check
225   // if it's a string already before calling the conversion builtin.
226   Label convert_argument;
227   __ bind(&not_cached);
228   __ JumpIfSmi(a0, &convert_argument);
229
230   // Is it a String?
231   __ ld(a2, FieldMemOperand(a0, HeapObject::kMapOffset));
232   __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
233   STATIC_ASSERT(kNotStringTag != 0);
234   __ And(a4, a3, Operand(kIsNotStringMask));
235   __ Branch(&convert_argument, ne, a4, Operand(zero_reg));
236   __ mov(argument, a0);
237   __ IncrementCounter(counters->string_ctor_conversions(), 1, a3, a4);
238   __ Branch(&argument_is_string);
239
240   // Invoke the conversion builtin and put the result into a2.
241   __ bind(&convert_argument);
242   __ push(function);  // Preserve the function.
243   __ IncrementCounter(counters->string_ctor_conversions(), 1, a3, a4);
244   {
245     FrameScope scope(masm, StackFrame::INTERNAL);
246     __ push(a0);
247     __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
248   }
249   __ pop(function);
250   __ mov(argument, v0);
251   __ Branch(&argument_is_string);
252
253   // Load the empty string into a2, remove the receiver from the
254   // stack, and jump back to the case where the argument is a string.
255   __ bind(&no_arguments);
256   __ LoadRoot(argument, Heap::kempty_stringRootIndex);
257   __ Drop(1);
258   __ Branch(&argument_is_string);
259
260   // At this point the argument is already a string. Call runtime to
261   // create a string wrapper.
262   __ bind(&gc_required);
263   __ IncrementCounter(counters->string_ctor_gc_required(), 1, a3, a4);
264   {
265     FrameScope scope(masm, StackFrame::INTERNAL);
266     __ push(argument);
267     __ CallRuntime(Runtime::kNewStringWrapper, 1);
268   }
269   __ Ret();
270 }
271
272
273 static void CallRuntimePassFunction(
274     MacroAssembler* masm, Runtime::FunctionId function_id) {
275   FrameScope scope(masm, StackFrame::INTERNAL);
276   // Push a copy of the function onto the stack.
277   // Push call kind information and function as parameter to the runtime call.
278   __ Push(a1, a1);
279
280   __ CallRuntime(function_id, 1);
281   // Restore call kind information and receiver.
282   __ Pop(a1);
283 }
284
285
286 static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
287   __ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
288   __ ld(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset));
289   __ Daddu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag));
290   __ Jump(at);
291 }
292
293
294 static void GenerateTailCallToReturnedCode(MacroAssembler* masm) {
295   __ Daddu(at, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
296   __ Jump(at);
297 }
298
299
300 void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
301   // Checking whether the queued function is ready for install is optional,
302   // since we come across interrupts and stack checks elsewhere.  However,
303   // not checking may delay installing ready functions, and always checking
304   // would be quite expensive.  A good compromise is to first check against
305   // stack limit as a cue for an interrupt signal.
306   Label ok;
307   __ LoadRoot(a4, Heap::kStackLimitRootIndex);
308   __ Branch(&ok, hs, sp, Operand(a4));
309
310   CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode);
311   GenerateTailCallToReturnedCode(masm);
312
313   __ bind(&ok);
314   GenerateTailCallToSharedCode(masm);
315 }
316
317
318 static void Generate_Runtime_NewObject(MacroAssembler* masm,
319                                        bool create_memento,
320                                        Register original_constructor,
321                                        Label* count_incremented,
322                                        Label* allocated) {
323   if (create_memento) {
324     // Get the cell or allocation site.
325     __ ld(a2, MemOperand(sp, 2 * kPointerSize));
326     __ push(a2);
327   }
328
329   __ push(a1);                    // argument for Runtime_NewObject
330   __ push(original_constructor);  // original constructor
331   if (create_memento) {
332     __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3);
333   } else {
334     __ CallRuntime(Runtime::kNewObject, 2);
335   }
336   __ mov(t0, v0);
337
338   // Runtime_NewObjectWithAllocationSite increments allocation count.
339   // Skip the increment.
340   if (create_memento) {
341     __ jmp(count_incremented);
342   } else {
343     __ jmp(allocated);
344   }
345 }
346
347
348 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
349                                            bool is_api_function,
350                                            bool create_memento) {
351   // ----------- S t a t e -------------
352   //  -- a0     : number of arguments
353   //  -- a1     : constructor function
354   //  -- a2     : allocation site or undefined
355   //  -- a3     : original constructor
356   //  -- ra     : return address
357   //  -- sp[...]: constructor arguments
358   // -----------------------------------
359
360   // Should never create mementos for api functions.
361   DCHECK(!is_api_function || !create_memento);
362
363   Isolate* isolate = masm->isolate();
364
365   // ----------- S t a t e -------------
366   //  -- a0     : number of arguments
367   //  -- a1     : constructor function
368   //  -- ra     : return address
369   //  -- sp[...]: constructor arguments
370   // -----------------------------------
371
372   // Enter a construct frame.
373   {
374     FrameScope scope(masm, StackFrame::CONSTRUCT);
375
376     if (create_memento) {
377       __ AssertUndefinedOrAllocationSite(a2, t0);
378       __ push(a2);
379     }
380
381     // Preserve the two incoming parameters on the stack.
382     // Tag arguments count.
383     __ dsll32(a0, a0, 0);
384     __ MultiPushReversed(a0.bit() | a1.bit());
385
386     Label rt_call, allocated, normal_new, count_incremented;
387     __ Branch(&normal_new, eq, a1, Operand(a3));
388
389     // Original constructor and function are different.
390     Generate_Runtime_NewObject(masm, create_memento, a3, &count_incremented,
391                                &allocated);
392     __ bind(&normal_new);
393
394     // Try to allocate the object without transitioning into C code. If any of
395     // the preconditions is not met, the code bails out to the runtime call.
396     if (FLAG_inline_new) {
397       Label undo_allocation;
398       ExternalReference debug_step_in_fp =
399           ExternalReference::debug_step_in_fp_address(isolate);
400       __ li(a2, Operand(debug_step_in_fp));
401       __ ld(a2, MemOperand(a2));
402       __ Branch(&rt_call, ne, a2, Operand(zero_reg));
403
404       // Load the initial map and verify that it is in fact a map.
405       // a1: constructor function
406       __ ld(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
407       __ JumpIfSmi(a2, &rt_call);
408       __ GetObjectType(a2, a3, t0);
409       __ Branch(&rt_call, ne, t0, Operand(MAP_TYPE));
410
411       // Check that the constructor is not constructing a JSFunction (see
412       // comments in Runtime_NewObject in runtime.cc). In which case the
413       // initial map's instance type would be JS_FUNCTION_TYPE.
414       // a1: constructor function
415       // a2: initial map
416       __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
417       __ Branch(&rt_call, eq, a3, Operand(JS_FUNCTION_TYPE));
418
419       if (!is_api_function) {
420         Label allocate;
421         MemOperand bit_field3 = FieldMemOperand(a2, Map::kBitField3Offset);
422         // Check if slack tracking is enabled.
423         __ lwu(a4, bit_field3);
424         __ DecodeField<Map::Counter>(a6, a4);
425         __ Branch(&allocate, lt, a6,
426                   Operand(static_cast<int64_t>(Map::kSlackTrackingCounterEnd)));
427         // Decrease generous allocation count.
428         __ Dsubu(a4, a4, Operand(1 << Map::Counter::kShift));
429         __ Branch(USE_DELAY_SLOT, &allocate, ne, a6,
430                   Operand(Map::kSlackTrackingCounterEnd));
431         __ sw(a4, bit_field3);  // In delay slot.
432
433         __ Push(a1, a2, a1);  // a1 = Constructor.
434         __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
435
436         __ Pop(a1, a2);
437         // Slack tracking counter is Map::kSlackTrackingCounterEnd after runtime
438         // call.
439         __ li(a6, Map::kSlackTrackingCounterEnd);
440
441         __ bind(&allocate);
442       }
443
444       // Now allocate the JSObject on the heap.
445       // a1: constructor function
446       // a2: initial map
447       __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset));
448       if (create_memento) {
449         __ Daddu(a3, a3, Operand(AllocationMemento::kSize / kPointerSize));
450       }
451
452       __ Allocate(a3, t0, t1, t2, &rt_call, SIZE_IN_WORDS);
453
454       // Allocated the JSObject, now initialize the fields. Map is set to
455       // initial map and properties and elements are set to empty fixed array.
456       // a1: constructor function
457       // a2: initial map
458       // a3: object size (not including memento if create_memento)
459       // t0: JSObject (not tagged)
460       __ LoadRoot(t2, Heap::kEmptyFixedArrayRootIndex);
461       __ mov(t1, t0);
462       __ sd(a2, MemOperand(t1, JSObject::kMapOffset));
463       __ sd(t2, MemOperand(t1, JSObject::kPropertiesOffset));
464       __ sd(t2, MemOperand(t1, JSObject::kElementsOffset));
465       __ Daddu(t1, t1, Operand(3*kPointerSize));
466       DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset);
467       DCHECK_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
468       DCHECK_EQ(2 * kPointerSize, JSObject::kElementsOffset);
469
470       // Fill all the in-object properties with appropriate filler.
471       // a1: constructor function
472       // a2: initial map
473       // a3: object size (in words, including memento if create_memento)
474       // t0: JSObject (not tagged)
475       // t1: First in-object property of JSObject (not tagged)
476       // a6: slack tracking counter (non-API function case)
477       DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize);
478
479       // Use t3 to hold undefined, which is used in several places below.
480       __ LoadRoot(t3, Heap::kUndefinedValueRootIndex);
481
482       if (!is_api_function) {
483         Label no_inobject_slack_tracking;
484
485         // Check if slack tracking is enabled.
486         __ Branch(&no_inobject_slack_tracking, lt, a6,
487                   Operand(static_cast<int64_t>(Map::kSlackTrackingCounterEnd)));
488
489         // Allocate object with a slack.
490         __ lwu(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
491         __ Ext(a0, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
492                 kBitsPerByte);
493         __ dsll(at, a0, kPointerSizeLog2);
494         __ daddu(a0, t1, at);
495         // a0: offset of first field after pre-allocated fields
496         if (FLAG_debug_code) {
497           __ dsll(at, a3, kPointerSizeLog2);
498           __ Daddu(t2, t0, Operand(at));   // End of object.
499           __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields,
500               a0, Operand(t2));
501         }
502         __ InitializeFieldsWithFiller(t1, a0, t3);
503         // To allow for truncation.
504         __ LoadRoot(t3, Heap::kOnePointerFillerMapRootIndex);
505         // Fill the remaining fields with one pointer filler map.
506
507         __ bind(&no_inobject_slack_tracking);
508       }
509
510       if (create_memento) {
511         __ Dsubu(a0, a3, Operand(AllocationMemento::kSize / kPointerSize));
512         __ dsll(a0, a0, kPointerSizeLog2);
513         __ Daddu(a0, t0, Operand(a0));  // End of object.
514         __ InitializeFieldsWithFiller(t1, a0, t3);
515
516         // Fill in memento fields.
517         // t1: points to the allocated but uninitialized memento.
518         __ LoadRoot(t3, Heap::kAllocationMementoMapRootIndex);
519         DCHECK_EQ(0 * kPointerSize, AllocationMemento::kMapOffset);
520         __ sd(t3, MemOperand(t1));
521         __ Daddu(t1, t1, kPointerSize);
522         // Load the AllocationSite.
523         __ ld(t3, MemOperand(sp, 2 * kPointerSize));
524         DCHECK_EQ(1 * kPointerSize, AllocationMemento::kAllocationSiteOffset);
525         __ sd(t3, MemOperand(t1));
526         __ Daddu(t1, t1, kPointerSize);
527       } else {
528         __ dsll(at, a3, kPointerSizeLog2);
529         __ Daddu(a0, t0, Operand(at));  // End of object.
530         __ InitializeFieldsWithFiller(t1, a0, t3);
531       }
532
533       // Add the object tag to make the JSObject real, so that we can continue
534       // and jump into the continuation code at any time from now on. Any
535       // failures need to undo the allocation, so that the heap is in a
536       // consistent state and verifiable.
537       __ Daddu(t0, t0, Operand(kHeapObjectTag));
538
539       // Check if a non-empty properties array is needed. Continue with
540       // allocated object if not fall through to runtime call if it is.
541       // a1: constructor function
542       // t0: JSObject
543       // t1: start of next object (not tagged)
544       __ lbu(a3, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
545       // The field instance sizes contains both pre-allocated property fields
546       // and in-object properties.
547       __ lw(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
548       __ Ext(t2, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
549              kBitsPerByte);
550       __ Daddu(a3, a3, Operand(t2));
551       __ Ext(t2, a0, Map::kInObjectPropertiesByte * kBitsPerByte,
552               kBitsPerByte);
553       __ dsubu(a3, a3, t2);
554
555       // Done if no extra properties are to be allocated.
556       __ Branch(&allocated, eq, a3, Operand(zero_reg));
557       __ Assert(greater_equal, kPropertyAllocationCountFailed,
558           a3, Operand(zero_reg));
559
560       // Scale the number of elements by pointer size and add the header for
561       // FixedArrays to the start of the next object calculation from above.
562       // a1: constructor
563       // a3: number of elements in properties array
564       // t0: JSObject
565       // t1: start of next object
566       __ Daddu(a0, a3, Operand(FixedArray::kHeaderSize / kPointerSize));
567       __ Allocate(
568           a0,
569           t1,
570           t2,
571           a2,
572           &undo_allocation,
573           static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
574
575       // Initialize the FixedArray.
576       // a1: constructor
577       // a3: number of elements in properties array (untagged)
578       // t0: JSObject
579       // t1: start of next object
580       __ LoadRoot(t2, Heap::kFixedArrayMapRootIndex);
581       __ mov(a2, t1);
582       __ sd(t2, MemOperand(a2, JSObject::kMapOffset));
583       // Tag number of elements.
584       __ dsll32(a0, a3, 0);
585       __ sd(a0, MemOperand(a2, FixedArray::kLengthOffset));
586       __ Daddu(a2, a2, Operand(2 * kPointerSize));
587
588       DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset);
589       DCHECK_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
590
591       // Initialize the fields to undefined.
592       // a1: constructor
593       // a2: First element of FixedArray (not tagged)
594       // a3: number of elements in properties array
595       // t0: JSObject
596       // t1: FixedArray (not tagged)
597       __ dsll(a7, a3, kPointerSizeLog2);
598       __ daddu(t2, a2, a7);  // End of object.
599       DCHECK_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
600       { Label loop, entry;
601         if (!is_api_function || create_memento) {
602           __ LoadRoot(t3, Heap::kUndefinedValueRootIndex);
603         } else if (FLAG_debug_code) {
604           __ LoadRoot(a6, Heap::kUndefinedValueRootIndex);
605           __ Assert(eq, kUndefinedValueNotLoaded, t3, Operand(a6));
606         }
607         __ jmp(&entry);
608         __ bind(&loop);
609         __ sd(t3, MemOperand(a2));
610         __ daddiu(a2, a2, kPointerSize);
611         __ bind(&entry);
612         __ Branch(&loop, less, a2, Operand(t2));
613       }
614
615       // Store the initialized FixedArray into the properties field of
616       // the JSObject.
617       // a1: constructor function
618       // t0: JSObject
619       // t1: FixedArray (not tagged)
620       __ Daddu(t1, t1, Operand(kHeapObjectTag));  // Add the heap tag.
621       __ sd(t1, FieldMemOperand(t0, JSObject::kPropertiesOffset));
622
623       // Continue with JSObject being successfully allocated.
624       // a1: constructor function
625       // a4: JSObject
626       __ jmp(&allocated);
627
628       // Undo the setting of the new top so that the heap is verifiable. For
629       // example, the map's unused properties potentially do not match the
630       // allocated objects unused properties.
631       // t0: JSObject (previous new top)
632       __ bind(&undo_allocation);
633       __ UndoAllocationInNewSpace(t0, t1);
634     }
635
636     // Allocate the new receiver object using the runtime call.
637     // a1: constructor function
638     __ bind(&rt_call);
639     Generate_Runtime_NewObject(masm, create_memento, a1, &count_incremented,
640                                &allocated);
641
642
643     // Receiver for constructor call allocated.
644     // t0: JSObject
645     __ bind(&allocated);
646
647     if (create_memento) {
648       __ ld(a2, MemOperand(sp, kPointerSize * 2));
649       __ LoadRoot(t1, Heap::kUndefinedValueRootIndex);
650       __ Branch(&count_incremented, eq, a2, Operand(t1));
651       // a2 is an AllocationSite. We are creating a memento from it, so we
652       // need to increment the memento create count.
653       __ ld(a3, FieldMemOperand(a2,
654                                 AllocationSite::kPretenureCreateCountOffset));
655       __ Daddu(a3, a3, Operand(Smi::FromInt(1)));
656       __ sd(a3, FieldMemOperand(a2,
657                                 AllocationSite::kPretenureCreateCountOffset));
658       __ bind(&count_incremented);
659     }
660
661     __ Push(t0, t0);
662
663     // Reload the number of arguments from the stack.
664     // sp[0]: receiver
665     // sp[1]: receiver
666     // sp[2]: constructor function
667     // sp[3]: number of arguments (smi-tagged)
668     __ ld(a1, MemOperand(sp, 2 * kPointerSize));
669     __ ld(a3, MemOperand(sp, 3 * kPointerSize));
670
671     // Set up pointer to last argument.
672     __ Daddu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
673
674     // Set up number of arguments for function call below.
675     __ SmiUntag(a0, a3);
676
677     // Copy arguments and receiver to the expression stack.
678     // a0: number of arguments
679     // a1: constructor function
680     // a2: address of last argument (caller sp)
681     // a3: number of arguments (smi-tagged)
682     // sp[0]: receiver
683     // sp[1]: receiver
684     // sp[2]: constructor function
685     // sp[3]: number of arguments (smi-tagged)
686     Label loop, entry;
687     __ SmiUntag(a3);
688     __ jmp(&entry);
689     __ bind(&loop);
690     __ dsll(a4, a3, kPointerSizeLog2);
691     __ Daddu(a4, a2, Operand(a4));
692     __ ld(a5, MemOperand(a4));
693     __ push(a5);
694     __ bind(&entry);
695     __ Daddu(a3, a3, Operand(-1));
696     __ Branch(&loop, greater_equal, a3, Operand(zero_reg));
697
698     // Call the function.
699     // a0: number of arguments
700     // a1: constructor function
701     if (is_api_function) {
702       __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
703       Handle<Code> code =
704           masm->isolate()->builtins()->HandleApiCallConstruct();
705       __ Call(code, RelocInfo::CODE_TARGET);
706     } else {
707       ParameterCount actual(a0);
708       __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
709     }
710
711     // Store offset of return address for deoptimizer.
712     if (!is_api_function) {
713       masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
714     }
715
716     // Restore context from the frame.
717     __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
718
719     // If the result is an object (in the ECMA sense), we should get rid
720     // of the receiver and use the result; see ECMA-262 section 13.2.2-7
721     // on page 74.
722     Label use_receiver, exit;
723
724     // If the result is a smi, it is *not* an object in the ECMA sense.
725     // v0: result
726     // sp[0]: receiver (newly allocated object)
727     // sp[1]: constructor function
728     // sp[2]: number of arguments (smi-tagged)
729     __ JumpIfSmi(v0, &use_receiver);
730
731     // If the type of the result (stored in its map) is less than
732     // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
733     __ GetObjectType(v0, a1, a3);
734     __ Branch(&exit, greater_equal, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
735
736     // Throw away the result of the constructor invocation and use the
737     // on-stack receiver as the result.
738     __ bind(&use_receiver);
739     __ ld(v0, MemOperand(sp));
740
741     // Remove receiver from the stack, remove caller arguments, and
742     // return.
743     __ bind(&exit);
744     // v0: result
745     // sp[0]: receiver (newly allocated object)
746     // sp[1]: constructor function
747     // sp[2]: number of arguments (smi-tagged)
748     __ ld(a1, MemOperand(sp, 2 * kPointerSize));
749
750     // Leave construct frame.
751   }
752
753   __ SmiScale(a4, a1, kPointerSizeLog2);
754   __ Daddu(sp, sp, a4);
755   __ Daddu(sp, sp, kPointerSize);
756   __ IncrementCounter(isolate->counters()->constructed_objects(), 1, a1, a2);
757   __ Ret();
758 }
759
760
761 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
762   Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new);
763 }
764
765
766 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
767   Generate_JSConstructStubHelper(masm, true, false);
768 }
769
770
771 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
772   // ----------- S t a t e -------------
773   //  -- a0     : number of arguments
774   //  -- a1     : constructor function
775   //  -- a2     : allocation site or undefined
776   //  -- a3     : original constructor
777   //  -- ra     : return address
778   //  -- sp[...]: constructor arguments
779   // -----------------------------------
780
781   // TODO(dslomov): support pretenuring
782   CHECK(!FLAG_pretenuring_call_new);
783
784   {
785     FrameScope frame_scope(masm, StackFrame::CONSTRUCT);
786
787     __ mov(a4, a0);
788     __ SmiTag(a4);
789     __ push(a4);  // Smi-tagged arguments count.
790
791     // Push new.target.
792     __ push(a3);
793
794     // receiver is the hole.
795     __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
796     __ push(at);
797
798     // Set up pointer to last argument.
799     __ Daddu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
800
801     // Copy arguments and receiver to the expression stack.
802     // a0: number of arguments
803     // a1: constructor function
804     // a2: address of last argument (caller sp)
805     // a4: number of arguments (smi-tagged)
806     // sp[0]: receiver
807     // sp[1]: new.target
808     // sp[2]: number of arguments (smi-tagged)
809     Label loop, entry;
810     __ SmiUntag(a4);
811     __ jmp(&entry);
812     __ bind(&loop);
813     __ dsll(at, a4, kPointerSizeLog2);
814     __ Daddu(at, a2, Operand(at));
815     __ ld(at, MemOperand(at));
816     __ push(at);
817     __ bind(&entry);
818     __ Daddu(a4, a4, Operand(-1));
819     __ Branch(&loop, ge, a4, Operand(zero_reg));
820
821     __ Daddu(a0, a0, Operand(1));
822
823     // Handle step in.
824     Label skip_step_in;
825     ExternalReference debug_step_in_fp =
826         ExternalReference::debug_step_in_fp_address(masm->isolate());
827     __ li(a2, Operand(debug_step_in_fp));
828     __ ld(a2, MemOperand(a2));
829     __ Branch(&skip_step_in, eq, a2, Operand(zero_reg));
830
831     __ Push(a0, a1, a1);
832     __ CallRuntime(Runtime::kHandleStepInForDerivedConstructors, 1);
833     __ Pop(a0, a1);
834
835     __ bind(&skip_step_in);
836
837
838     // Call the function.
839     // a0: number of arguments
840     // a1: constructor function
841     ParameterCount actual(a0);
842     __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
843
844     // Restore context from the frame.
845     // v0: result
846     // sp[0]: number of arguments (smi-tagged)
847     __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
848     __ ld(a1, MemOperand(sp, 0));
849
850     // Leave construct frame.
851   }
852
853   __ SmiScale(at, a1, kPointerSizeLog2);
854   __ Daddu(sp, sp, Operand(at));
855   __ Daddu(sp, sp, Operand(kPointerSize));
856   __ Jump(ra);
857 }
858
859
860 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
861                                              bool is_construct) {
862   // Called from JSEntryStub::GenerateBody
863
864   // ----------- S t a t e -------------
865   //  -- a0: code entry
866   //  -- a1: function
867   //  -- a2: receiver_pointer
868   //  -- a3: argc
869   //  -- s0: argv
870   // -----------------------------------
871   ProfileEntryHookStub::MaybeCallEntryHook(masm);
872   // Clear the context before we push it when entering the JS frame.
873   __ mov(cp, zero_reg);
874
875   // Enter an internal frame.
876   {
877     FrameScope scope(masm, StackFrame::INTERNAL);
878
879     // Set up the context from the function argument.
880     __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
881
882     // Push the function and the receiver onto the stack.
883     __ Push(a1, a2);
884
885     // Copy arguments to the stack in a loop.
886     // a3: argc
887     // s0: argv, i.e. points to first arg
888     Label loop, entry;
889     __ dsll(a4, a3, kPointerSizeLog2);
890     __ daddu(a6, s0, a4);
891     __ b(&entry);
892     __ nop();   // Branch delay slot nop.
893     // a6 points past last arg.
894     __ bind(&loop);
895     __ ld(a4, MemOperand(s0));  // Read next parameter.
896     __ daddiu(s0, s0, kPointerSize);
897     __ ld(a4, MemOperand(a4));  // Dereference handle.
898     __ push(a4);  // Push parameter.
899     __ bind(&entry);
900     __ Branch(&loop, ne, s0, Operand(a6));
901
902     // Initialize all JavaScript callee-saved registers, since they will be seen
903     // by the garbage collector as part of handlers.
904     __ LoadRoot(a4, Heap::kUndefinedValueRootIndex);
905     __ mov(s1, a4);
906     __ mov(s2, a4);
907     __ mov(s3, a4);
908     __ mov(s4, a4);
909     __ mov(s5, a4);
910     // s6 holds the root address. Do not clobber.
911     // s7 is cp. Do not init.
912
913     // Invoke the code and pass argc as a0.
914     __ mov(a0, a3);
915     if (is_construct) {
916       // No type feedback cell is available
917       __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
918       CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
919       __ CallStub(&stub);
920     } else {
921       ParameterCount actual(a0);
922       __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
923     }
924
925     // Leave internal frame.
926   }
927   __ Jump(ra);
928 }
929
930
931 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
932   Generate_JSEntryTrampolineHelper(masm, false);
933 }
934
935
936 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
937   Generate_JSEntryTrampolineHelper(masm, true);
938 }
939
940
941 void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
942   CallRuntimePassFunction(masm, Runtime::kCompileLazy);
943   GenerateTailCallToReturnedCode(masm);
944 }
945
946
947 static void CallCompileOptimized(MacroAssembler* masm, bool concurrent) {
948   FrameScope scope(masm, StackFrame::INTERNAL);
949   // Push a copy of the function onto the stack.
950   // Push function as parameter to the runtime call.
951   __ Push(a1, a1);
952   // Whether to compile in a background thread.
953   __ Push(masm->isolate()->factory()->ToBoolean(concurrent));
954
955   __ CallRuntime(Runtime::kCompileOptimized, 2);
956   // Restore receiver.
957   __ Pop(a1);
958 }
959
960
961 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
962   CallCompileOptimized(masm, false);
963   GenerateTailCallToReturnedCode(masm);
964 }
965
966
967 void Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) {
968   CallCompileOptimized(masm, true);
969   GenerateTailCallToReturnedCode(masm);
970 }
971
972
973 static void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) {
974   // For now, we are relying on the fact that make_code_young doesn't do any
975   // garbage collection which allows us to save/restore the registers without
976   // worrying about which of them contain pointers. We also don't build an
977   // internal frame to make the code faster, since we shouldn't have to do stack
978   // crawls in MakeCodeYoung. This seems a bit fragile.
979
980   // Set a0 to point to the head of the PlatformCodeAge sequence.
981   __ Dsubu(a0, a0,
982       Operand(kNoCodeAgeSequenceLength - Assembler::kInstrSize));
983
984   // The following registers must be saved and restored when calling through to
985   // the runtime:
986   //   a0 - contains return address (beginning of patch sequence)
987   //   a1 - isolate
988   RegList saved_regs =
989       (a0.bit() | a1.bit() | ra.bit() | fp.bit()) & ~sp.bit();
990   FrameScope scope(masm, StackFrame::MANUAL);
991   __ MultiPush(saved_regs);
992   __ PrepareCallCFunction(2, 0, a2);
993   __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate())));
994   __ CallCFunction(
995       ExternalReference::get_make_code_young_function(masm->isolate()), 2);
996   __ MultiPop(saved_regs);
997   __ Jump(a0);
998 }
999
1000 #define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C)                 \
1001 void Builtins::Generate_Make##C##CodeYoungAgainEvenMarking(  \
1002     MacroAssembler* masm) {                                  \
1003   GenerateMakeCodeYoungAgainCommon(masm);                    \
1004 }                                                            \
1005 void Builtins::Generate_Make##C##CodeYoungAgainOddMarking(   \
1006     MacroAssembler* masm) {                                  \
1007   GenerateMakeCodeYoungAgainCommon(masm);                    \
1008 }
1009 CODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR)
1010 #undef DEFINE_CODE_AGE_BUILTIN_GENERATOR
1011
1012
1013 void Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) {
1014   // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact
1015   // that make_code_young doesn't do any garbage collection which allows us to
1016   // save/restore the registers without worrying about which of them contain
1017   // pointers.
1018
1019   // Set a0 to point to the head of the PlatformCodeAge sequence.
1020   __ Dsubu(a0, a0,
1021       Operand(kNoCodeAgeSequenceLength - Assembler::kInstrSize));
1022
1023   // The following registers must be saved and restored when calling through to
1024   // the runtime:
1025   //   a0 - contains return address (beginning of patch sequence)
1026   //   a1 - isolate
1027   RegList saved_regs =
1028       (a0.bit() | a1.bit() | ra.bit() | fp.bit()) & ~sp.bit();
1029   FrameScope scope(masm, StackFrame::MANUAL);
1030   __ MultiPush(saved_regs);
1031   __ PrepareCallCFunction(2, 0, a2);
1032   __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate())));
1033   __ CallCFunction(
1034       ExternalReference::get_mark_code_as_executed_function(masm->isolate()),
1035       2);
1036   __ MultiPop(saved_regs);
1037
1038   // Perform prologue operations usually performed by the young code stub.
1039   __ Push(ra, fp, cp, a1);
1040   __ Daddu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
1041
1042   // Jump to point after the code-age stub.
1043   __ Daddu(a0, a0, Operand((kNoCodeAgeSequenceLength)));
1044   __ Jump(a0);
1045 }
1046
1047
1048 void Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) {
1049   GenerateMakeCodeYoungAgainCommon(masm);
1050 }
1051
1052
1053 static void Generate_NotifyStubFailureHelper(MacroAssembler* masm,
1054                                              SaveFPRegsMode save_doubles) {
1055   {
1056     FrameScope scope(masm, StackFrame::INTERNAL);
1057
1058     // Preserve registers across notification, this is important for compiled
1059     // stubs that tail call the runtime on deopts passing their parameters in
1060     // registers.
1061     __ MultiPush(kJSCallerSaved | kCalleeSaved);
1062     // Pass the function and deoptimization type to the runtime system.
1063     __ CallRuntime(Runtime::kNotifyStubFailure, 0, save_doubles);
1064     __ MultiPop(kJSCallerSaved | kCalleeSaved);
1065   }
1066
1067   __ Daddu(sp, sp, Operand(kPointerSize));  // Ignore state
1068   __ Jump(ra);  // Jump to miss handler
1069 }
1070
1071
1072 void Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) {
1073   Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs);
1074 }
1075
1076
1077 void Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) {
1078   Generate_NotifyStubFailureHelper(masm, kSaveFPRegs);
1079 }
1080
1081
1082 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
1083                                              Deoptimizer::BailoutType type) {
1084   {
1085     FrameScope scope(masm, StackFrame::INTERNAL);
1086     // Pass the function and deoptimization type to the runtime system.
1087     __ li(a0, Operand(Smi::FromInt(static_cast<int>(type))));
1088     __ push(a0);
1089     __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
1090   }
1091
1092   // Get the full codegen state from the stack and untag it -> a6.
1093   __ ld(a6, MemOperand(sp, 0 * kPointerSize));
1094   __ SmiUntag(a6);
1095   // Switch on the state.
1096   Label with_tos_register, unknown_state;
1097   __ Branch(&with_tos_register,
1098             ne, a6, Operand(FullCodeGenerator::NO_REGISTERS));
1099   __ Ret(USE_DELAY_SLOT);
1100   // Safe to fill delay slot Addu will emit one instruction.
1101   __ Daddu(sp, sp, Operand(1 * kPointerSize));  // Remove state.
1102
1103   __ bind(&with_tos_register);
1104   __ ld(v0, MemOperand(sp, 1 * kPointerSize));
1105   __ Branch(&unknown_state, ne, a6, Operand(FullCodeGenerator::TOS_REG));
1106
1107   __ Ret(USE_DELAY_SLOT);
1108   // Safe to fill delay slot Addu will emit one instruction.
1109   __ Daddu(sp, sp, Operand(2 * kPointerSize));  // Remove state.
1110
1111   __ bind(&unknown_state);
1112   __ stop("no cases left");
1113 }
1114
1115
1116 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
1117   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
1118 }
1119
1120
1121 void Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) {
1122   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
1123 }
1124
1125
1126 void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
1127   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
1128 }
1129
1130
1131 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1132   // Lookup the function in the JavaScript frame.
1133   __ ld(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1134   {
1135     FrameScope scope(masm, StackFrame::INTERNAL);
1136     // Pass function as argument.
1137     __ push(a0);
1138     __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1139   }
1140
1141   // If the code object is null, just return to the unoptimized code.
1142   __ Ret(eq, v0, Operand(Smi::FromInt(0)));
1143
1144   // Load deoptimization data from the code object.
1145   // <deopt_data> = <code>[#deoptimization_data_offset]
1146   __ ld(a1, MemOperand(v0, Code::kDeoptimizationDataOffset - kHeapObjectTag));
1147
1148   // Load the OSR entrypoint offset from the deoptimization data.
1149   // <osr_offset> = <deopt_data>[#header_size + #osr_pc_offset]
1150   __ ld(a1, MemOperand(a1, FixedArray::OffsetOfElementAt(
1151       DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag));
1152   __ SmiUntag(a1);
1153
1154   // Compute the target address = code_obj + header_size + osr_offset
1155   // <entry_addr> = <code_obj> + #header_size + <osr_offset>
1156   __ daddu(v0, v0, a1);
1157   __ daddiu(ra, v0, Code::kHeaderSize - kHeapObjectTag);
1158
1159   // And "return" to the OSR entry point of the function.
1160   __ Ret();
1161 }
1162
1163
1164 void Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) {
1165   // We check the stack limit as indicator that recompilation might be done.
1166   Label ok;
1167   __ LoadRoot(at, Heap::kStackLimitRootIndex);
1168   __ Branch(&ok, hs, sp, Operand(at));
1169   {
1170     FrameScope scope(masm, StackFrame::INTERNAL);
1171     __ CallRuntime(Runtime::kStackGuard, 0);
1172   }
1173   __ Jump(masm->isolate()->builtins()->OnStackReplacement(),
1174           RelocInfo::CODE_TARGET);
1175
1176   __ bind(&ok);
1177   __ Ret();
1178 }
1179
1180
1181 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
1182   // 1. Make sure we have at least one argument.
1183   // a0: actual number of arguments
1184   { Label done;
1185     __ Branch(&done, ne, a0, Operand(zero_reg));
1186     __ LoadRoot(a6, Heap::kUndefinedValueRootIndex);
1187     __ push(a6);
1188     __ Daddu(a0, a0, Operand(1));
1189     __ bind(&done);
1190   }
1191
1192   // 2. Get the function to call (passed as receiver) from the stack, check
1193   //    if it is a function.
1194   // a0: actual number of arguments
1195   Label slow, non_function;
1196   __ dsll(at, a0, kPointerSizeLog2);
1197   __ daddu(at, sp, at);
1198   __ ld(a1, MemOperand(at));
1199   __ JumpIfSmi(a1, &non_function);
1200   __ GetObjectType(a1, a2, a2);
1201   __ Branch(&slow, ne, a2, Operand(JS_FUNCTION_TYPE));
1202
1203   // 3a. Patch the first argument if necessary when calling a function.
1204   // a0: actual number of arguments
1205   // a1: function
1206   Label shift_arguments;
1207   __ li(a4, Operand(0, RelocInfo::NONE32));  // Indicate regular JS_FUNCTION.
1208   { Label convert_to_object, use_global_proxy, patch_receiver;
1209     // Change context eagerly in case we need the global receiver.
1210     __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
1211
1212     // Do not transform the receiver for strict mode functions.
1213     __ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1214     __ lbu(a3, FieldMemOperand(a2, SharedFunctionInfo::kStrictModeByteOffset));
1215     __ And(a7, a3, Operand(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
1216     __ Branch(&shift_arguments, ne, a7, Operand(zero_reg));
1217
1218     // Do not transform the receiver for native (Compilerhints already in a3).
1219     __ lbu(a3, FieldMemOperand(a2, SharedFunctionInfo::kNativeByteOffset));
1220     __ And(a7, a3, Operand(1 << SharedFunctionInfo::kNativeBitWithinByte));
1221     __ Branch(&shift_arguments, ne, a7, Operand(zero_reg));
1222
1223     // Compute the receiver in sloppy mode.
1224     // Load first argument in a2. a2 = -kPointerSize(sp + n_args << 2).
1225     __ dsll(at, a0, kPointerSizeLog2);
1226     __ daddu(a2, sp, at);
1227     __ ld(a2, MemOperand(a2, -kPointerSize));
1228     // a0: actual number of arguments
1229     // a1: function
1230     // a2: first argument
1231     __ JumpIfSmi(a2, &convert_to_object, a6);
1232
1233     __ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
1234     __ Branch(&use_global_proxy, eq, a2, Operand(a3));
1235     __ LoadRoot(a3, Heap::kNullValueRootIndex);
1236     __ Branch(&use_global_proxy, eq, a2, Operand(a3));
1237
1238     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1239     __ GetObjectType(a2, a3, a3);
1240     __ Branch(&shift_arguments, ge, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
1241
1242     __ bind(&convert_to_object);
1243     // Enter an internal frame in order to preserve argument count.
1244     {
1245       FrameScope scope(masm, StackFrame::INTERNAL);
1246       __ SmiTag(a0);
1247       __ Push(a0, a2);
1248       __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1249       __ mov(a2, v0);
1250
1251       __ pop(a0);
1252       __ SmiUntag(a0);
1253       // Leave internal frame.
1254     }
1255     // Restore the function to a1, and the flag to a4.
1256     __ dsll(at, a0, kPointerSizeLog2);
1257     __ daddu(at, sp, at);
1258     __ ld(a1, MemOperand(at));
1259     __ Branch(USE_DELAY_SLOT, &patch_receiver);
1260     __ li(a4, Operand(0, RelocInfo::NONE32));
1261
1262     __ bind(&use_global_proxy);
1263     __ ld(a2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
1264     __ ld(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset));
1265
1266     __ bind(&patch_receiver);
1267     __ dsll(at, a0, kPointerSizeLog2);
1268     __ daddu(a3, sp, at);
1269     __ sd(a2, MemOperand(a3, -kPointerSize));
1270
1271     __ Branch(&shift_arguments);
1272   }
1273
1274   // 3b. Check for function proxy.
1275   __ bind(&slow);
1276   __ li(a4, Operand(1, RelocInfo::NONE32));  // Indicate function proxy.
1277   __ Branch(&shift_arguments, eq, a2, Operand(JS_FUNCTION_PROXY_TYPE));
1278
1279   __ bind(&non_function);
1280   __ li(a4, Operand(2, RelocInfo::NONE32));  // Indicate non-function.
1281
1282   // 3c. Patch the first argument when calling a non-function.  The
1283   //     CALL_NON_FUNCTION builtin expects the non-function callee as
1284   //     receiver, so overwrite the first argument which will ultimately
1285   //     become the receiver.
1286   // a0: actual number of arguments
1287   // a1: function
1288   // a4: call type (0: JS function, 1: function proxy, 2: non-function)
1289   __ dsll(at, a0, kPointerSizeLog2);
1290   __ daddu(a2, sp, at);
1291   __ sd(a1, MemOperand(a2, -kPointerSize));
1292
1293   // 4. Shift arguments and return address one slot down on the stack
1294   //    (overwriting the original receiver).  Adjust argument count to make
1295   //    the original first argument the new receiver.
1296   // a0: actual number of arguments
1297   // a1: function
1298   // a4: call type (0: JS function, 1: function proxy, 2: non-function)
1299   __ bind(&shift_arguments);
1300   { Label loop;
1301     // Calculate the copy start address (destination). Copy end address is sp.
1302     __ dsll(at, a0, kPointerSizeLog2);
1303     __ daddu(a2, sp, at);
1304
1305     __ bind(&loop);
1306     __ ld(at, MemOperand(a2, -kPointerSize));
1307     __ sd(at, MemOperand(a2));
1308     __ Dsubu(a2, a2, Operand(kPointerSize));
1309     __ Branch(&loop, ne, a2, Operand(sp));
1310     // Adjust the actual number of arguments and remove the top element
1311     // (which is a copy of the last argument).
1312     __ Dsubu(a0, a0, Operand(1));
1313     __ Pop();
1314   }
1315
1316   // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
1317   //     or a function proxy via CALL_FUNCTION_PROXY.
1318   // a0: actual number of arguments
1319   // a1: function
1320   // a4: call type (0: JS function, 1: function proxy, 2: non-function)
1321   { Label function, non_proxy;
1322     __ Branch(&function, eq, a4, Operand(zero_reg));
1323     // Expected number of arguments is 0 for CALL_NON_FUNCTION.
1324     __ mov(a2, zero_reg);
1325     __ Branch(&non_proxy, ne, a4, Operand(1));
1326
1327     __ push(a1);  // Re-add proxy object as additional argument.
1328     __ Daddu(a0, a0, Operand(1));
1329     __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY);
1330     __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1331             RelocInfo::CODE_TARGET);
1332
1333     __ bind(&non_proxy);
1334     __ GetBuiltinFunction(a1, Builtins::CALL_NON_FUNCTION);
1335     __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1336             RelocInfo::CODE_TARGET);
1337     __ bind(&function);
1338   }
1339
1340   // 5b. Get the code to call from the function and check that the number of
1341   //     expected arguments matches what we're providing.  If so, jump
1342   //     (tail-call) to the code in register edx without checking arguments.
1343   // a0: actual number of arguments
1344   // a1: function
1345   __ ld(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1346   // The argument count is stored as int32_t on 64-bit platforms.
1347   // TODO(plind): Smi on 32-bit platforms.
1348   __ lw(a2,
1349          FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
1350   // Check formal and actual parameter counts.
1351   __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1352           RelocInfo::CODE_TARGET, ne, a2, Operand(a0));
1353
1354   __ ld(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
1355   ParameterCount expected(0);
1356   __ InvokeCode(a3, expected, expected, JUMP_FUNCTION, NullCallWrapper());
1357 }
1358
1359
1360 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1361   const int kIndexOffset    =
1362       StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
1363   const int kLimitOffset    =
1364       StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
1365   const int kArgsOffset     = 2 * kPointerSize;
1366   const int kRecvOffset     = 3 * kPointerSize;
1367   const int kFunctionOffset = 4 * kPointerSize;
1368
1369   {
1370     FrameScope frame_scope(masm, StackFrame::INTERNAL);
1371     __ ld(a0, MemOperand(fp, kFunctionOffset));  // Get the function.
1372     __ push(a0);
1373     __ ld(a0, MemOperand(fp, kArgsOffset));  // Get the args array.
1374     __ push(a0);
1375     // Returns (in v0) number of arguments to copy to stack as Smi.
1376     __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
1377
1378     // Check the stack for overflow. We are not trying to catch
1379     // interruptions (e.g. debug break and preemption) here, so the "real stack
1380     // limit" is checked.
1381     Label okay;
1382     __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
1383     // Make a2 the space we have left. The stack might already be overflowed
1384     // here which will cause a2 to become negative.
1385     __ dsubu(a2, sp, a2);
1386     // Check if the arguments will overflow the stack.
1387     __ SmiScale(a7, v0, kPointerSizeLog2);
1388     __ Branch(&okay, gt, a2, Operand(a7));  // Signed comparison.
1389
1390     // Out of stack space.
1391     __ ld(a1, MemOperand(fp, kFunctionOffset));
1392     __ Push(a1, v0);
1393     __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1394     // End of stack check.
1395
1396     // Push current limit and index.
1397     __ bind(&okay);
1398     __ mov(a1, zero_reg);
1399     __ Push(v0, a1);  // Limit and initial index.
1400
1401     // Get the receiver.
1402     __ ld(a0, MemOperand(fp, kRecvOffset));
1403
1404     // Check that the function is a JS function (otherwise it must be a proxy).
1405     Label push_receiver;
1406     __ ld(a1, MemOperand(fp, kFunctionOffset));
1407     __ GetObjectType(a1, a2, a2);
1408     __ Branch(&push_receiver, ne, a2, Operand(JS_FUNCTION_TYPE));
1409
1410     // Change context eagerly to get the right global object if necessary.
1411     __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
1412     // Load the shared function info while the function is still in a1.
1413     __ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1414
1415     // Compute the receiver.
1416     // Do not transform the receiver for strict mode functions.
1417     Label call_to_object, use_global_proxy;
1418     __ lbu(a7, FieldMemOperand(a2, SharedFunctionInfo::kStrictModeByteOffset));
1419     __ And(a7, a7, Operand(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
1420     __ Branch(&push_receiver, ne, a7, Operand(zero_reg));
1421
1422     // Do not transform the receiver for native (Compilerhints already in a2).
1423     __ lbu(a7, FieldMemOperand(a2, SharedFunctionInfo::kNativeByteOffset));
1424     __ And(a7, a7, Operand(1 << SharedFunctionInfo::kNativeBitWithinByte));
1425     __ Branch(&push_receiver, ne, a7, Operand(zero_reg));
1426
1427     // Compute the receiver in sloppy mode.
1428     __ JumpIfSmi(a0, &call_to_object);
1429     __ LoadRoot(a1, Heap::kNullValueRootIndex);
1430     __ Branch(&use_global_proxy, eq, a0, Operand(a1));
1431     __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
1432     __ Branch(&use_global_proxy, eq, a0, Operand(a2));
1433
1434     // Check if the receiver is already a JavaScript object.
1435     // a0: receiver
1436     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1437     __ GetObjectType(a0, a1, a1);
1438     __ Branch(&push_receiver, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
1439
1440     // Convert the receiver to a regular object.
1441     // a0: receiver
1442     __ bind(&call_to_object);
1443     __ push(a0);
1444     __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1445     __ mov(a0, v0);  // Put object in a0 to match other paths to push_receiver.
1446     __ Branch(&push_receiver);
1447
1448     __ bind(&use_global_proxy);
1449     __ ld(a0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
1450     __ ld(a0, FieldMemOperand(a0, GlobalObject::kGlobalProxyOffset));
1451
1452     // Push the receiver.
1453     // a0: receiver
1454     __ bind(&push_receiver);
1455     __ push(a0);
1456
1457     // Copy all arguments from the array to the stack.
1458     Label entry, loop;
1459     __ ld(a0, MemOperand(fp, kIndexOffset));
1460     __ Branch(&entry);
1461
1462     // Load the current argument from the arguments array and push it to the
1463     // stack.
1464     // a0: current argument index
1465     __ bind(&loop);
1466     __ ld(a1, MemOperand(fp, kArgsOffset));
1467     __ Push(a1, a0);
1468
1469     // Call the runtime to access the property in the arguments array.
1470     __ CallRuntime(Runtime::kGetProperty, 2);
1471     __ push(v0);
1472
1473     // Use inline caching to access the arguments.
1474     __ ld(a0, MemOperand(fp, kIndexOffset));
1475     __ Daddu(a0, a0, Operand(Smi::FromInt(1)));
1476     __ sd(a0, MemOperand(fp, kIndexOffset));
1477
1478     // Test if the copy loop has finished copying all the elements from the
1479     // arguments object.
1480     __ bind(&entry);
1481     __ ld(a1, MemOperand(fp, kLimitOffset));
1482     __ Branch(&loop, ne, a0, Operand(a1));
1483
1484     // Call the function.
1485     Label call_proxy;
1486     ParameterCount actual(a0);
1487     __ SmiUntag(a0);
1488     __ ld(a1, MemOperand(fp, kFunctionOffset));
1489     __ GetObjectType(a1, a2, a2);
1490     __ Branch(&call_proxy, ne, a2, Operand(JS_FUNCTION_TYPE));
1491
1492     __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
1493
1494     frame_scope.GenerateLeaveFrame();
1495     __ Ret(USE_DELAY_SLOT);
1496     __ Daddu(sp, sp, Operand(3 * kPointerSize));  // In delay slot.
1497
1498     // Call the function proxy.
1499     __ bind(&call_proxy);
1500     __ push(a1);  // Add function proxy as last argument.
1501     __ Daddu(a0, a0, Operand(1));
1502     __ li(a2, Operand(0, RelocInfo::NONE32));
1503     __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY);
1504     __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1505             RelocInfo::CODE_TARGET);
1506     // Tear down the internal frame and remove function, receiver and args.
1507   }
1508
1509   __ Ret(USE_DELAY_SLOT);
1510   __ Daddu(sp, sp, Operand(3 * kPointerSize));  // In delay slot.
1511 }
1512
1513
1514 static void ArgumentAdaptorStackCheck(MacroAssembler* masm,
1515                                       Label* stack_overflow) {
1516   // ----------- S t a t e -------------
1517   //  -- a0 : actual number of arguments
1518   //  -- a1 : function (passed through to callee)
1519   //  -- a2 : expected number of arguments
1520   // -----------------------------------
1521   // Check the stack for overflow. We are not trying to catch
1522   // interruptions (e.g. debug break and preemption) here, so the "real stack
1523   // limit" is checked.
1524   __ LoadRoot(a5, Heap::kRealStackLimitRootIndex);
1525   // Make a5 the space we have left. The stack might already be overflowed
1526   // here which will cause a5 to become negative.
1527   __ dsubu(a5, sp, a5);
1528   // Check if the arguments will overflow the stack.
1529   __ dsll(at, a2, kPointerSizeLog2);
1530   // Signed comparison.
1531   __ Branch(stack_overflow, le, a5, Operand(at));
1532 }
1533
1534
1535 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1536   // __ sll(a0, a0, kSmiTagSize);
1537   __ dsll32(a0, a0, 0);
1538   __ li(a4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1539   __ MultiPush(a0.bit() | a1.bit() | a4.bit() | fp.bit() | ra.bit());
1540   __ Daddu(fp, sp,
1541       Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize));
1542 }
1543
1544
1545 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1546   // ----------- S t a t e -------------
1547   //  -- v0 : result being passed through
1548   // -----------------------------------
1549   // Get the number of arguments passed (as a smi), tear down the frame and
1550   // then tear down the parameters.
1551   __ ld(a1, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp +
1552                              kPointerSize)));
1553   __ mov(sp, fp);
1554   __ MultiPop(fp.bit() | ra.bit());
1555   __ SmiScale(a4, a1, kPointerSizeLog2);
1556   __ Daddu(sp, sp, a4);
1557   // Adjust for the receiver.
1558   __ Daddu(sp, sp, Operand(kPointerSize));
1559 }
1560
1561
1562 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1563   // State setup as expected by MacroAssembler::InvokePrologue.
1564   // ----------- S t a t e -------------
1565   //  -- a0: actual arguments count
1566   //  -- a1: function (passed through to callee)
1567   //  -- a2: expected arguments count
1568   // -----------------------------------
1569
1570   Label stack_overflow;
1571   ArgumentAdaptorStackCheck(masm, &stack_overflow);
1572   Label invoke, dont_adapt_arguments;
1573
1574   Label enough, too_few;
1575   __ ld(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
1576   __ Branch(&dont_adapt_arguments, eq,
1577       a2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
1578   // We use Uless as the number of argument should always be greater than 0.
1579   __ Branch(&too_few, Uless, a0, Operand(a2));
1580
1581   {  // Enough parameters: actual >= expected.
1582     // a0: actual number of arguments as a smi
1583     // a1: function
1584     // a2: expected number of arguments
1585     // a3: code entry to call
1586     __ bind(&enough);
1587     EnterArgumentsAdaptorFrame(masm);
1588
1589     // Calculate copy start address into a0 and copy end address into a2.
1590     __ SmiScale(a0, a0, kPointerSizeLog2);
1591     __ Daddu(a0, fp, a0);
1592     // Adjust for return address and receiver.
1593     __ Daddu(a0, a0, Operand(2 * kPointerSize));
1594     // Compute copy end address.
1595     __ dsll(a2, a2, kPointerSizeLog2);
1596     __ dsubu(a2, a0, a2);
1597
1598     // Copy the arguments (including the receiver) to the new stack frame.
1599     // a0: copy start address
1600     // a1: function
1601     // a2: copy end address
1602     // a3: code entry to call
1603
1604     Label copy;
1605     __ bind(&copy);
1606     __ ld(a4, MemOperand(a0));
1607     __ push(a4);
1608     __ Branch(USE_DELAY_SLOT, &copy, ne, a0, Operand(a2));
1609     __ daddiu(a0, a0, -kPointerSize);  // In delay slot.
1610
1611     __ jmp(&invoke);
1612   }
1613
1614   {  // Too few parameters: Actual < expected.
1615     __ bind(&too_few);
1616     EnterArgumentsAdaptorFrame(masm);
1617
1618     // Calculate copy start address into a0 and copy end address is fp.
1619     // a0: actual number of arguments as a smi
1620     // a1: function
1621     // a2: expected number of arguments
1622     // a3: code entry to call
1623     __ SmiScale(a0, a0, kPointerSizeLog2);
1624     __ Daddu(a0, fp, a0);
1625     // Adjust for return address and receiver.
1626     __ Daddu(a0, a0, Operand(2 * kPointerSize));
1627     // Compute copy end address. Also adjust for return address.
1628     __ Daddu(a7, fp, kPointerSize);
1629
1630     // Copy the arguments (including the receiver) to the new stack frame.
1631     // a0: copy start address
1632     // a1: function
1633     // a2: expected number of arguments
1634     // a3: code entry to call
1635     // a7: copy end address
1636     Label copy;
1637     __ bind(&copy);
1638     __ ld(a4, MemOperand(a0));  // Adjusted above for return addr and receiver.
1639     __ Dsubu(sp, sp, kPointerSize);
1640     __ Dsubu(a0, a0, kPointerSize);
1641     __ Branch(USE_DELAY_SLOT, &copy, ne, a0, Operand(a7));
1642     __ sd(a4, MemOperand(sp));  // In the delay slot.
1643
1644     // Fill the remaining expected arguments with undefined.
1645     // a1: function
1646     // a2: expected number of arguments
1647     // a3: code entry to call
1648     __ LoadRoot(a4, Heap::kUndefinedValueRootIndex);
1649     __ dsll(a6, a2, kPointerSizeLog2);
1650     __ Dsubu(a2, fp, Operand(a6));
1651     // Adjust for frame.
1652     __ Dsubu(a2, a2, Operand(StandardFrameConstants::kFixedFrameSizeFromFp +
1653                             2 * kPointerSize));
1654
1655     Label fill;
1656     __ bind(&fill);
1657     __ Dsubu(sp, sp, kPointerSize);
1658     __ Branch(USE_DELAY_SLOT, &fill, ne, sp, Operand(a2));
1659     __ sd(a4, MemOperand(sp));
1660   }
1661
1662   // Call the entry point.
1663   __ bind(&invoke);
1664
1665   __ Call(a3);
1666
1667   // Store offset of return address for deoptimizer.
1668   masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
1669
1670   // Exit frame and return.
1671   LeaveArgumentsAdaptorFrame(masm);
1672   __ Ret();
1673
1674
1675   // -------------------------------------------
1676   // Don't adapt arguments.
1677   // -------------------------------------------
1678   __ bind(&dont_adapt_arguments);
1679   __ Jump(a3);
1680
1681   __ bind(&stack_overflow);
1682   {
1683     FrameScope frame(masm, StackFrame::MANUAL);
1684     EnterArgumentsAdaptorFrame(masm);
1685     __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1686     __ break_(0xCC);
1687   }
1688 }
1689
1690
1691 #undef __
1692
1693 } }  // namespace v8::internal
1694
1695 #endif  // V8_TARGET_ARCH_MIPS64