Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / v8 / src / compiler / ia32 / code-generator-ia32.cc
1 // Copyright 2013 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 #include "src/compiler/code-generator.h"
6
7 #include "src/compiler/code-generator-impl.h"
8 #include "src/compiler/gap-resolver.h"
9 #include "src/compiler/node-matchers.h"
10 #include "src/compiler/node-properties-inl.h"
11 #include "src/ia32/assembler-ia32.h"
12 #include "src/ia32/macro-assembler-ia32.h"
13 #include "src/scopes.h"
14
15 namespace v8 {
16 namespace internal {
17 namespace compiler {
18
19 #define __ masm()->
20
21
22 // Adds IA-32 specific methods for decoding operands.
23 class IA32OperandConverter : public InstructionOperandConverter {
24  public:
25   IA32OperandConverter(CodeGenerator* gen, Instruction* instr)
26       : InstructionOperandConverter(gen, instr) {}
27
28   Operand InputOperand(int index) { return ToOperand(instr_->InputAt(index)); }
29
30   Immediate InputImmediate(int index) {
31     return ToImmediate(instr_->InputAt(index));
32   }
33
34   Operand OutputOperand() { return ToOperand(instr_->Output()); }
35
36   Operand TempOperand(int index) { return ToOperand(instr_->TempAt(index)); }
37
38   Operand ToOperand(InstructionOperand* op, int extra = 0) {
39     if (op->IsRegister()) {
40       DCHECK(extra == 0);
41       return Operand(ToRegister(op));
42     } else if (op->IsDoubleRegister()) {
43       DCHECK(extra == 0);
44       return Operand(ToDoubleRegister(op));
45     }
46     DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
47     // The linkage computes where all spill slots are located.
48     FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), extra);
49     return Operand(offset.from_stack_pointer() ? esp : ebp, offset.offset());
50   }
51
52   Operand HighOperand(InstructionOperand* op) {
53     DCHECK(op->IsDoubleStackSlot());
54     return ToOperand(op, kPointerSize);
55   }
56
57   Immediate ToImmediate(InstructionOperand* operand) {
58     Constant constant = ToConstant(operand);
59     switch (constant.type()) {
60       case Constant::kInt32:
61         return Immediate(constant.ToInt32());
62       case Constant::kFloat64:
63         return Immediate(
64             isolate()->factory()->NewNumber(constant.ToFloat64(), TENURED));
65       case Constant::kExternalReference:
66         return Immediate(constant.ToExternalReference());
67       case Constant::kHeapObject:
68         return Immediate(constant.ToHeapObject());
69       case Constant::kInt64:
70         break;
71     }
72     UNREACHABLE();
73     return Immediate(-1);
74   }
75
76   Operand MemoryOperand(int* first_input) {
77     const int offset = *first_input;
78     switch (AddressingModeField::decode(instr_->opcode())) {
79       case kMode_MR1I:
80         *first_input += 2;
81         return Operand(InputRegister(offset + 0), InputRegister(offset + 1),
82                        times_1,
83                        0);  // TODO(dcarney): K != 0
84       case kMode_MRI:
85         *first_input += 2;
86         return Operand::ForRegisterPlusImmediate(InputRegister(offset + 0),
87                                                  InputImmediate(offset + 1));
88       case kMode_MI:
89         *first_input += 1;
90         return Operand(InputImmediate(offset + 0));
91       default:
92         UNREACHABLE();
93         return Operand(no_reg);
94     }
95   }
96
97   Operand MemoryOperand() {
98     int first_input = 0;
99     return MemoryOperand(&first_input);
100   }
101 };
102
103
104 static bool HasImmediateInput(Instruction* instr, int index) {
105   return instr->InputAt(index)->IsImmediate();
106 }
107
108
109 // Assembles an instruction after register allocation, producing machine code.
110 void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
111   IA32OperandConverter i(this, instr);
112
113   switch (ArchOpcodeField::decode(instr->opcode())) {
114     case kArchJmp:
115       __ jmp(code()->GetLabel(i.InputBlock(0)));
116       break;
117     case kArchNop:
118       // don't emit code for nops.
119       break;
120     case kArchRet:
121       AssembleReturn();
122       break;
123     case kArchDeoptimize: {
124       int deoptimization_id = MiscField::decode(instr->opcode());
125       BuildTranslation(instr, deoptimization_id);
126
127       Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
128           isolate(), deoptimization_id, Deoptimizer::LAZY);
129       __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
130       break;
131     }
132     case kIA32Add:
133       if (HasImmediateInput(instr, 1)) {
134         __ add(i.InputOperand(0), i.InputImmediate(1));
135       } else {
136         __ add(i.InputRegister(0), i.InputOperand(1));
137       }
138       break;
139     case kIA32And:
140       if (HasImmediateInput(instr, 1)) {
141         __ and_(i.InputOperand(0), i.InputImmediate(1));
142       } else {
143         __ and_(i.InputRegister(0), i.InputOperand(1));
144       }
145       break;
146     case kIA32Cmp:
147       if (HasImmediateInput(instr, 1)) {
148         __ cmp(i.InputOperand(0), i.InputImmediate(1));
149       } else {
150         __ cmp(i.InputRegister(0), i.InputOperand(1));
151       }
152       break;
153     case kIA32Test:
154       if (HasImmediateInput(instr, 1)) {
155         __ test(i.InputOperand(0), i.InputImmediate(1));
156       } else {
157         __ test(i.InputRegister(0), i.InputOperand(1));
158       }
159       break;
160     case kIA32Imul:
161       if (HasImmediateInput(instr, 1)) {
162         __ imul(i.OutputRegister(), i.InputOperand(0), i.InputInt32(1));
163       } else {
164         __ imul(i.OutputRegister(), i.InputOperand(1));
165       }
166       break;
167     case kIA32Idiv:
168       __ cdq();
169       __ idiv(i.InputOperand(1));
170       break;
171     case kIA32Udiv:
172       __ xor_(edx, edx);
173       __ div(i.InputOperand(1));
174       break;
175     case kIA32Not:
176       __ not_(i.OutputOperand());
177       break;
178     case kIA32Neg:
179       __ neg(i.OutputOperand());
180       break;
181     case kIA32Or:
182       if (HasImmediateInput(instr, 1)) {
183         __ or_(i.InputOperand(0), i.InputImmediate(1));
184       } else {
185         __ or_(i.InputRegister(0), i.InputOperand(1));
186       }
187       break;
188     case kIA32Xor:
189       if (HasImmediateInput(instr, 1)) {
190         __ xor_(i.InputOperand(0), i.InputImmediate(1));
191       } else {
192         __ xor_(i.InputRegister(0), i.InputOperand(1));
193       }
194       break;
195     case kIA32Sub:
196       if (HasImmediateInput(instr, 1)) {
197         __ sub(i.InputOperand(0), i.InputImmediate(1));
198       } else {
199         __ sub(i.InputRegister(0), i.InputOperand(1));
200       }
201       break;
202     case kIA32Shl:
203       if (HasImmediateInput(instr, 1)) {
204         __ shl(i.OutputRegister(), i.InputInt5(1));
205       } else {
206         __ shl_cl(i.OutputRegister());
207       }
208       break;
209     case kIA32Shr:
210       if (HasImmediateInput(instr, 1)) {
211         __ shr(i.OutputRegister(), i.InputInt5(1));
212       } else {
213         __ shr_cl(i.OutputRegister());
214       }
215       break;
216     case kIA32Sar:
217       if (HasImmediateInput(instr, 1)) {
218         __ sar(i.OutputRegister(), i.InputInt5(1));
219       } else {
220         __ sar_cl(i.OutputRegister());
221       }
222       break;
223     case kIA32Push:
224       if (HasImmediateInput(instr, 0)) {
225         __ push(i.InputImmediate(0));
226       } else {
227         __ push(i.InputOperand(0));
228       }
229       break;
230     case kIA32CallCodeObject: {
231       if (HasImmediateInput(instr, 0)) {
232         Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
233         __ call(code, RelocInfo::CODE_TARGET);
234       } else {
235         Register reg = i.InputRegister(0);
236         int entry = Code::kHeaderSize - kHeapObjectTag;
237         __ call(Operand(reg, entry));
238       }
239       RecordSafepoint(instr->pointer_map(), Safepoint::kSimple, 0,
240                       Safepoint::kNoLazyDeopt);
241
242       bool lazy_deopt = (MiscField::decode(instr->opcode()) == 1);
243       if (lazy_deopt) {
244         RecordLazyDeoptimizationEntry(instr);
245       }
246       AddNopForSmiCodeInlining();
247       break;
248     }
249     case kIA32CallAddress:
250       if (HasImmediateInput(instr, 0)) {
251         // TODO(dcarney): wire up EXTERNAL_REFERENCE instead of RUNTIME_ENTRY.
252         __ call(reinterpret_cast<byte*>(i.InputInt32(0)),
253                 RelocInfo::RUNTIME_ENTRY);
254       } else {
255         __ call(i.InputRegister(0));
256       }
257       break;
258     case kPopStack: {
259       int words = MiscField::decode(instr->opcode());
260       __ add(esp, Immediate(kPointerSize * words));
261       break;
262     }
263     case kIA32CallJSFunction: {
264       Register func = i.InputRegister(0);
265
266       // TODO(jarin) The load of the context should be separated from the call.
267       __ mov(esi, FieldOperand(func, JSFunction::kContextOffset));
268       __ call(FieldOperand(func, JSFunction::kCodeEntryOffset));
269
270       RecordSafepoint(instr->pointer_map(), Safepoint::kSimple, 0,
271                       Safepoint::kNoLazyDeopt);
272       RecordLazyDeoptimizationEntry(instr);
273       break;
274     }
275     case kSSEFloat64Cmp:
276       __ ucomisd(i.InputDoubleRegister(0), i.InputOperand(1));
277       break;
278     case kSSEFloat64Add:
279       __ addsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
280       break;
281     case kSSEFloat64Sub:
282       __ subsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
283       break;
284     case kSSEFloat64Mul:
285       __ mulsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
286       break;
287     case kSSEFloat64Div:
288       __ divsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
289       break;
290     case kSSEFloat64Mod: {
291       // TODO(dcarney): alignment is wrong.
292       __ sub(esp, Immediate(kDoubleSize));
293       // Move values to st(0) and st(1).
294       __ movsd(Operand(esp, 0), i.InputDoubleRegister(1));
295       __ fld_d(Operand(esp, 0));
296       __ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
297       __ fld_d(Operand(esp, 0));
298       // Loop while fprem isn't done.
299       Label mod_loop;
300       __ bind(&mod_loop);
301       // This instructions traps on all kinds inputs, but we are assuming the
302       // floating point control word is set to ignore them all.
303       __ fprem();
304       // The following 2 instruction implicitly use eax.
305       __ fnstsw_ax();
306       __ sahf();
307       __ j(parity_even, &mod_loop);
308       // Move output to stack and clean up.
309       __ fstp(1);
310       __ fstp_d(Operand(esp, 0));
311       __ movsd(i.OutputDoubleRegister(), Operand(esp, 0));
312       __ add(esp, Immediate(kDoubleSize));
313       break;
314     }
315     case kSSEFloat64ToInt32:
316       __ cvttsd2si(i.OutputRegister(), i.InputOperand(0));
317       break;
318     case kSSEFloat64ToUint32: {
319       XMMRegister scratch = xmm0;
320       __ Move(scratch, -2147483648.0);
321       // TODO(turbofan): IA32 SSE subsd() should take an operand.
322       __ addsd(scratch, i.InputDoubleRegister(0));
323       __ cvttsd2si(i.OutputRegister(), scratch);
324       __ add(i.OutputRegister(), Immediate(0x80000000));
325       break;
326     }
327     case kSSEInt32ToFloat64:
328       __ cvtsi2sd(i.OutputDoubleRegister(), i.InputOperand(0));
329       break;
330     case kSSEUint32ToFloat64:
331       // TODO(turbofan): IA32 SSE LoadUint32() should take an operand.
332       __ LoadUint32(i.OutputDoubleRegister(), i.InputRegister(0));
333       break;
334     case kSSELoad:
335       __ movsd(i.OutputDoubleRegister(), i.MemoryOperand());
336       break;
337     case kSSEStore: {
338       int index = 0;
339       Operand operand = i.MemoryOperand(&index);
340       __ movsd(operand, i.InputDoubleRegister(index));
341       break;
342     }
343     case kIA32LoadWord8:
344       __ movzx_b(i.OutputRegister(), i.MemoryOperand());
345       break;
346     case kIA32StoreWord8: {
347       int index = 0;
348       Operand operand = i.MemoryOperand(&index);
349       __ mov_b(operand, i.InputRegister(index));
350       break;
351     }
352     case kIA32StoreWord8I: {
353       int index = 0;
354       Operand operand = i.MemoryOperand(&index);
355       __ mov_b(operand, i.InputInt8(index));
356       break;
357     }
358     case kIA32LoadWord16:
359       __ movzx_w(i.OutputRegister(), i.MemoryOperand());
360       break;
361     case kIA32StoreWord16: {
362       int index = 0;
363       Operand operand = i.MemoryOperand(&index);
364       __ mov_w(operand, i.InputRegister(index));
365       break;
366     }
367     case kIA32StoreWord16I: {
368       int index = 0;
369       Operand operand = i.MemoryOperand(&index);
370       __ mov_w(operand, i.InputInt16(index));
371       break;
372     }
373     case kIA32LoadWord32:
374       __ mov(i.OutputRegister(), i.MemoryOperand());
375       break;
376     case kIA32StoreWord32: {
377       int index = 0;
378       Operand operand = i.MemoryOperand(&index);
379       __ mov(operand, i.InputRegister(index));
380       break;
381     }
382     case kIA32StoreWord32I: {
383       int index = 0;
384       Operand operand = i.MemoryOperand(&index);
385       __ mov(operand, i.InputImmediate(index));
386       break;
387     }
388     case kIA32StoreWriteBarrier: {
389       Register object = i.InputRegister(0);
390       Register index = i.InputRegister(1);
391       Register value = i.InputRegister(2);
392       __ mov(Operand(object, index, times_1, 0), value);
393       __ lea(index, Operand(object, index, times_1, 0));
394       SaveFPRegsMode mode = code_->frame()->DidAllocateDoubleRegisters()
395                                 ? kSaveFPRegs
396                                 : kDontSaveFPRegs;
397       __ RecordWrite(object, index, value, mode);
398       break;
399     }
400   }
401 }
402
403
404 // Assembles branches after an instruction.
405 void CodeGenerator::AssembleArchBranch(Instruction* instr,
406                                        FlagsCondition condition) {
407   IA32OperandConverter i(this, instr);
408   Label done;
409
410   // Emit a branch. The true and false targets are always the last two inputs
411   // to the instruction.
412   BasicBlock* tblock = i.InputBlock(instr->InputCount() - 2);
413   BasicBlock* fblock = i.InputBlock(instr->InputCount() - 1);
414   bool fallthru = IsNextInAssemblyOrder(fblock);
415   Label* tlabel = code()->GetLabel(tblock);
416   Label* flabel = fallthru ? &done : code()->GetLabel(fblock);
417   Label::Distance flabel_distance = fallthru ? Label::kNear : Label::kFar;
418   switch (condition) {
419     case kUnorderedEqual:
420       __ j(parity_even, flabel, flabel_distance);
421     // Fall through.
422     case kEqual:
423       __ j(equal, tlabel);
424       break;
425     case kUnorderedNotEqual:
426       __ j(parity_even, tlabel);
427     // Fall through.
428     case kNotEqual:
429       __ j(not_equal, tlabel);
430       break;
431     case kSignedLessThan:
432       __ j(less, tlabel);
433       break;
434     case kSignedGreaterThanOrEqual:
435       __ j(greater_equal, tlabel);
436       break;
437     case kSignedLessThanOrEqual:
438       __ j(less_equal, tlabel);
439       break;
440     case kSignedGreaterThan:
441       __ j(greater, tlabel);
442       break;
443     case kUnorderedLessThan:
444       __ j(parity_even, flabel, flabel_distance);
445     // Fall through.
446     case kUnsignedLessThan:
447       __ j(below, tlabel);
448       break;
449     case kUnorderedGreaterThanOrEqual:
450       __ j(parity_even, tlabel);
451     // Fall through.
452     case kUnsignedGreaterThanOrEqual:
453       __ j(above_equal, tlabel);
454       break;
455     case kUnorderedLessThanOrEqual:
456       __ j(parity_even, flabel, flabel_distance);
457     // Fall through.
458     case kUnsignedLessThanOrEqual:
459       __ j(below_equal, tlabel);
460       break;
461     case kUnorderedGreaterThan:
462       __ j(parity_even, tlabel);
463     // Fall through.
464     case kUnsignedGreaterThan:
465       __ j(above, tlabel);
466       break;
467     case kOverflow:
468       __ j(overflow, tlabel);
469       break;
470     case kNotOverflow:
471       __ j(no_overflow, tlabel);
472       break;
473   }
474   if (!fallthru) __ jmp(flabel, flabel_distance);  // no fallthru to flabel.
475   __ bind(&done);
476 }
477
478
479 // Assembles boolean materializations after an instruction.
480 void CodeGenerator::AssembleArchBoolean(Instruction* instr,
481                                         FlagsCondition condition) {
482   IA32OperandConverter i(this, instr);
483   Label done;
484
485   // Materialize a full 32-bit 1 or 0 value. The result register is always the
486   // last output of the instruction.
487   Label check;
488   DCHECK_NE(0, instr->OutputCount());
489   Register reg = i.OutputRegister(instr->OutputCount() - 1);
490   Condition cc = no_condition;
491   switch (condition) {
492     case kUnorderedEqual:
493       __ j(parity_odd, &check, Label::kNear);
494       __ mov(reg, Immediate(0));
495       __ jmp(&done, Label::kNear);
496     // Fall through.
497     case kEqual:
498       cc = equal;
499       break;
500     case kUnorderedNotEqual:
501       __ j(parity_odd, &check, Label::kNear);
502       __ mov(reg, Immediate(1));
503       __ jmp(&done, Label::kNear);
504     // Fall through.
505     case kNotEqual:
506       cc = not_equal;
507       break;
508     case kSignedLessThan:
509       cc = less;
510       break;
511     case kSignedGreaterThanOrEqual:
512       cc = greater_equal;
513       break;
514     case kSignedLessThanOrEqual:
515       cc = less_equal;
516       break;
517     case kSignedGreaterThan:
518       cc = greater;
519       break;
520     case kUnorderedLessThan:
521       __ j(parity_odd, &check, Label::kNear);
522       __ mov(reg, Immediate(0));
523       __ jmp(&done, Label::kNear);
524     // Fall through.
525     case kUnsignedLessThan:
526       cc = below;
527       break;
528     case kUnorderedGreaterThanOrEqual:
529       __ j(parity_odd, &check, Label::kNear);
530       __ mov(reg, Immediate(1));
531       __ jmp(&done, Label::kNear);
532     // Fall through.
533     case kUnsignedGreaterThanOrEqual:
534       cc = above_equal;
535       break;
536     case kUnorderedLessThanOrEqual:
537       __ j(parity_odd, &check, Label::kNear);
538       __ mov(reg, Immediate(0));
539       __ jmp(&done, Label::kNear);
540     // Fall through.
541     case kUnsignedLessThanOrEqual:
542       cc = below_equal;
543       break;
544     case kUnorderedGreaterThan:
545       __ j(parity_odd, &check, Label::kNear);
546       __ mov(reg, Immediate(1));
547       __ jmp(&done, Label::kNear);
548     // Fall through.
549     case kUnsignedGreaterThan:
550       cc = above;
551       break;
552     case kOverflow:
553       cc = overflow;
554       break;
555     case kNotOverflow:
556       cc = no_overflow;
557       break;
558   }
559   __ bind(&check);
560   if (reg.is_byte_register()) {
561     // setcc for byte registers (al, bl, cl, dl).
562     __ setcc(cc, reg);
563     __ movzx_b(reg, reg);
564   } else {
565     // Emit a branch to set a register to either 1 or 0.
566     Label set;
567     __ j(cc, &set, Label::kNear);
568     __ mov(reg, Immediate(0));
569     __ jmp(&done, Label::kNear);
570     __ bind(&set);
571     __ mov(reg, Immediate(1));
572   }
573   __ bind(&done);
574 }
575
576
577 // The calling convention for JSFunctions on IA32 passes arguments on the
578 // stack and the JSFunction and context in EDI and ESI, respectively, thus
579 // the steps of the call look as follows:
580
581 // --{ before the call instruction }--------------------------------------------
582 //                                                         |  caller frame |
583 //                                                         ^ esp           ^ ebp
584
585 // --{ push arguments and setup ESI, EDI }--------------------------------------
586 //                                       | args + receiver |  caller frame |
587 //                                       ^ esp                             ^ ebp
588 //                 [edi = JSFunction, esi = context]
589
590 // --{ call [edi + kCodeEntryOffset] }------------------------------------------
591 //                                 | RET | args + receiver |  caller frame |
592 //                                 ^ esp                                   ^ ebp
593
594 // =={ prologue of called function }============================================
595 // --{ push ebp }---------------------------------------------------------------
596 //                            | FP | RET | args + receiver |  caller frame |
597 //                            ^ esp                                        ^ ebp
598
599 // --{ mov ebp, esp }-----------------------------------------------------------
600 //                            | FP | RET | args + receiver |  caller frame |
601 //                            ^ ebp,esp
602
603 // --{ push esi }---------------------------------------------------------------
604 //                      | CTX | FP | RET | args + receiver |  caller frame |
605 //                      ^esp  ^ ebp
606
607 // --{ push edi }---------------------------------------------------------------
608 //                | FNC | CTX | FP | RET | args + receiver |  caller frame |
609 //                ^esp        ^ ebp
610
611 // --{ subi esp, #N }-----------------------------------------------------------
612 // | callee frame | FNC | CTX | FP | RET | args + receiver |  caller frame |
613 // ^esp                       ^ ebp
614
615 // =={ body of called function }================================================
616
617 // =={ epilogue of called function }============================================
618 // --{ mov esp, ebp }-----------------------------------------------------------
619 //                            | FP | RET | args + receiver |  caller frame |
620 //                            ^ esp,ebp
621
622 // --{ pop ebp }-----------------------------------------------------------
623 // |                               | RET | args + receiver |  caller frame |
624 //                                 ^ esp                                   ^ ebp
625
626 // --{ ret #A+1 }-----------------------------------------------------------
627 // |                                                       |  caller frame |
628 //                                                         ^ esp           ^ ebp
629
630
631 // Runtime function calls are accomplished by doing a stub call to the
632 // CEntryStub (a real code object). On IA32 passes arguments on the
633 // stack, the number of arguments in EAX, the address of the runtime function
634 // in EBX, and the context in ESI.
635
636 // --{ before the call instruction }--------------------------------------------
637 //                                                         |  caller frame |
638 //                                                         ^ esp           ^ ebp
639
640 // --{ push arguments and setup EAX, EBX, and ESI }-----------------------------
641 //                                       | args + receiver |  caller frame |
642 //                                       ^ esp                             ^ ebp
643 //              [eax = #args, ebx = runtime function, esi = context]
644
645 // --{ call #CEntryStub }-------------------------------------------------------
646 //                                 | RET | args + receiver |  caller frame |
647 //                                 ^ esp                                   ^ ebp
648
649 // =={ body of runtime function }===============================================
650
651 // --{ runtime returns }--------------------------------------------------------
652 //                                                         |  caller frame |
653 //                                                         ^ esp           ^ ebp
654
655 // Other custom linkages (e.g. for calling directly into and out of C++) may
656 // need to save callee-saved registers on the stack, which is done in the
657 // function prologue of generated code.
658
659 // --{ before the call instruction }--------------------------------------------
660 //                                                         |  caller frame |
661 //                                                         ^ esp           ^ ebp
662
663 // --{ set up arguments in registers on stack }---------------------------------
664 //                                                  | args |  caller frame |
665 //                                                  ^ esp                  ^ ebp
666 //                  [r0 = arg0, r1 = arg1, ...]
667
668 // --{ call code }--------------------------------------------------------------
669 //                                            | RET | args |  caller frame |
670 //                                            ^ esp                        ^ ebp
671
672 // =={ prologue of called function }============================================
673 // --{ push ebp }---------------------------------------------------------------
674 //                                       | FP | RET | args |  caller frame |
675 //                                       ^ esp                             ^ ebp
676
677 // --{ mov ebp, esp }-----------------------------------------------------------
678 //                                       | FP | RET | args |  caller frame |
679 //                                       ^ ebp,esp
680
681 // --{ save registers }---------------------------------------------------------
682 //                                | regs | FP | RET | args |  caller frame |
683 //                                ^ esp  ^ ebp
684
685 // --{ subi esp, #N }-----------------------------------------------------------
686 //                 | callee frame | regs | FP | RET | args |  caller frame |
687 //                 ^esp                  ^ ebp
688
689 // =={ body of called function }================================================
690
691 // =={ epilogue of called function }============================================
692 // --{ restore registers }------------------------------------------------------
693 //                                | regs | FP | RET | args |  caller frame |
694 //                                ^ esp  ^ ebp
695
696 // --{ mov esp, ebp }-----------------------------------------------------------
697 //                                       | FP | RET | args |  caller frame |
698 //                                       ^ esp,ebp
699
700 // --{ pop ebp }----------------------------------------------------------------
701 //                                            | RET | args |  caller frame |
702 //                                            ^ esp                        ^ ebp
703
704
705 void CodeGenerator::AssemblePrologue() {
706   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
707   Frame* frame = code_->frame();
708   int stack_slots = frame->GetSpillSlotCount();
709   if (descriptor->kind() == CallDescriptor::kCallAddress) {
710     // Assemble a prologue similar the to cdecl calling convention.
711     __ push(ebp);
712     __ mov(ebp, esp);
713     const RegList saves = descriptor->CalleeSavedRegisters();
714     if (saves != 0) {  // Save callee-saved registers.
715       int register_save_area_size = 0;
716       for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
717         if (!((1 << i) & saves)) continue;
718         __ push(Register::from_code(i));
719         register_save_area_size += kPointerSize;
720       }
721       frame->SetRegisterSaveAreaSize(register_save_area_size);
722     }
723   } else if (descriptor->IsJSFunctionCall()) {
724     CompilationInfo* info = linkage()->info();
725     __ Prologue(info->IsCodePreAgingActive());
726     frame->SetRegisterSaveAreaSize(
727         StandardFrameConstants::kFixedFrameSizeFromFp);
728
729     // Sloppy mode functions and builtins need to replace the receiver with the
730     // global proxy when called as functions (without an explicit receiver
731     // object).
732     // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC?
733     if (info->strict_mode() == SLOPPY && !info->is_native()) {
734       Label ok;
735       // +2 for return address and saved frame pointer.
736       int receiver_slot = info->scope()->num_parameters() + 2;
737       __ mov(ecx, Operand(ebp, receiver_slot * kPointerSize));
738       __ cmp(ecx, isolate()->factory()->undefined_value());
739       __ j(not_equal, &ok, Label::kNear);
740       __ mov(ecx, GlobalObjectOperand());
741       __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalProxyOffset));
742       __ mov(Operand(ebp, receiver_slot * kPointerSize), ecx);
743       __ bind(&ok);
744     }
745
746   } else {
747     __ StubPrologue();
748     frame->SetRegisterSaveAreaSize(
749         StandardFrameConstants::kFixedFrameSizeFromFp);
750   }
751   if (stack_slots > 0) {
752     __ sub(esp, Immediate(stack_slots * kPointerSize));
753   }
754 }
755
756
757 void CodeGenerator::AssembleReturn() {
758   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
759   if (descriptor->kind() == CallDescriptor::kCallAddress) {
760     const RegList saves = descriptor->CalleeSavedRegisters();
761     if (frame()->GetRegisterSaveAreaSize() > 0) {
762       // Remove this frame's spill slots first.
763       int stack_slots = frame()->GetSpillSlotCount();
764       if (stack_slots > 0) {
765         __ add(esp, Immediate(stack_slots * kPointerSize));
766       }
767       // Restore registers.
768       if (saves != 0) {
769         for (int i = 0; i < Register::kNumRegisters; i++) {
770           if (!((1 << i) & saves)) continue;
771           __ pop(Register::from_code(i));
772         }
773       }
774       __ pop(ebp);  // Pop caller's frame pointer.
775       __ ret(0);
776     } else {
777       // No saved registers.
778       __ mov(esp, ebp);  // Move stack pointer back to frame pointer.
779       __ pop(ebp);       // Pop caller's frame pointer.
780       __ ret(0);
781     }
782   } else {
783     __ mov(esp, ebp);  // Move stack pointer back to frame pointer.
784     __ pop(ebp);       // Pop caller's frame pointer.
785     int pop_count =
786         descriptor->IsJSFunctionCall() ? descriptor->ParameterCount() : 0;
787     __ ret(pop_count * kPointerSize);
788   }
789 }
790
791
792 void CodeGenerator::AssembleMove(InstructionOperand* source,
793                                  InstructionOperand* destination) {
794   IA32OperandConverter g(this, NULL);
795   // Dispatch on the source and destination operand kinds.  Not all
796   // combinations are possible.
797   if (source->IsRegister()) {
798     DCHECK(destination->IsRegister() || destination->IsStackSlot());
799     Register src = g.ToRegister(source);
800     Operand dst = g.ToOperand(destination);
801     __ mov(dst, src);
802   } else if (source->IsStackSlot()) {
803     DCHECK(destination->IsRegister() || destination->IsStackSlot());
804     Operand src = g.ToOperand(source);
805     if (destination->IsRegister()) {
806       Register dst = g.ToRegister(destination);
807       __ mov(dst, src);
808     } else {
809       Operand dst = g.ToOperand(destination);
810       __ push(src);
811       __ pop(dst);
812     }
813   } else if (source->IsConstant()) {
814     Constant src_constant = g.ToConstant(source);
815     if (src_constant.type() == Constant::kHeapObject) {
816       Handle<HeapObject> src = src_constant.ToHeapObject();
817       if (destination->IsRegister()) {
818         Register dst = g.ToRegister(destination);
819         __ LoadHeapObject(dst, src);
820       } else {
821         DCHECK(destination->IsStackSlot());
822         Operand dst = g.ToOperand(destination);
823         AllowDeferredHandleDereference embedding_raw_address;
824         if (isolate()->heap()->InNewSpace(*src)) {
825           __ PushHeapObject(src);
826           __ pop(dst);
827         } else {
828           __ mov(dst, src);
829         }
830       }
831     } else if (destination->IsRegister()) {
832       Register dst = g.ToRegister(destination);
833       __ mov(dst, g.ToImmediate(source));
834     } else if (destination->IsStackSlot()) {
835       Operand dst = g.ToOperand(destination);
836       __ mov(dst, g.ToImmediate(source));
837     } else {
838       double v = g.ToDouble(source);
839       uint64_t int_val = BitCast<uint64_t, double>(v);
840       int32_t lower = static_cast<int32_t>(int_val);
841       int32_t upper = static_cast<int32_t>(int_val >> kBitsPerInt);
842       if (destination->IsDoubleRegister()) {
843         XMMRegister dst = g.ToDoubleRegister(destination);
844         __ Move(dst, v);
845       } else {
846         DCHECK(destination->IsDoubleStackSlot());
847         Operand dst0 = g.ToOperand(destination);
848         Operand dst1 = g.HighOperand(destination);
849         __ mov(dst0, Immediate(lower));
850         __ mov(dst1, Immediate(upper));
851       }
852     }
853   } else if (source->IsDoubleRegister()) {
854     XMMRegister src = g.ToDoubleRegister(source);
855     if (destination->IsDoubleRegister()) {
856       XMMRegister dst = g.ToDoubleRegister(destination);
857       __ movaps(dst, src);
858     } else {
859       DCHECK(destination->IsDoubleStackSlot());
860       Operand dst = g.ToOperand(destination);
861       __ movsd(dst, src);
862     }
863   } else if (source->IsDoubleStackSlot()) {
864     DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
865     Operand src = g.ToOperand(source);
866     if (destination->IsDoubleRegister()) {
867       XMMRegister dst = g.ToDoubleRegister(destination);
868       __ movsd(dst, src);
869     } else {
870       // We rely on having xmm0 available as a fixed scratch register.
871       Operand dst = g.ToOperand(destination);
872       __ movsd(xmm0, src);
873       __ movsd(dst, xmm0);
874     }
875   } else {
876     UNREACHABLE();
877   }
878 }
879
880
881 void CodeGenerator::AssembleSwap(InstructionOperand* source,
882                                  InstructionOperand* destination) {
883   IA32OperandConverter g(this, NULL);
884   // Dispatch on the source and destination operand kinds.  Not all
885   // combinations are possible.
886   if (source->IsRegister() && destination->IsRegister()) {
887     // Register-register.
888     Register src = g.ToRegister(source);
889     Register dst = g.ToRegister(destination);
890     __ xchg(dst, src);
891   } else if (source->IsRegister() && destination->IsStackSlot()) {
892     // Register-memory.
893     __ xchg(g.ToRegister(source), g.ToOperand(destination));
894   } else if (source->IsStackSlot() && destination->IsStackSlot()) {
895     // Memory-memory.
896     Operand src = g.ToOperand(source);
897     Operand dst = g.ToOperand(destination);
898     __ push(dst);
899     __ push(src);
900     __ pop(dst);
901     __ pop(src);
902   } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) {
903     // XMM register-register swap. We rely on having xmm0
904     // available as a fixed scratch register.
905     XMMRegister src = g.ToDoubleRegister(source);
906     XMMRegister dst = g.ToDoubleRegister(destination);
907     __ movaps(xmm0, src);
908     __ movaps(src, dst);
909     __ movaps(dst, xmm0);
910   } else if (source->IsDoubleRegister() && source->IsDoubleStackSlot()) {
911     // XMM register-memory swap.  We rely on having xmm0
912     // available as a fixed scratch register.
913     XMMRegister reg = g.ToDoubleRegister(source);
914     Operand other = g.ToOperand(destination);
915     __ movsd(xmm0, other);
916     __ movsd(other, reg);
917     __ movaps(reg, xmm0);
918   } else if (source->IsDoubleStackSlot() && destination->IsDoubleStackSlot()) {
919     // Double-width memory-to-memory.
920     Operand src0 = g.ToOperand(source);
921     Operand src1 = g.HighOperand(source);
922     Operand dst0 = g.ToOperand(destination);
923     Operand dst1 = g.HighOperand(destination);
924     __ movsd(xmm0, dst0);  // Save destination in xmm0.
925     __ push(src0);         // Then use stack to copy source to destination.
926     __ pop(dst0);
927     __ push(src1);
928     __ pop(dst1);
929     __ movsd(src0, xmm0);
930   } else {
931     // No other combinations are possible.
932     UNREACHABLE();
933   }
934 }
935
936
937 void CodeGenerator::AddNopForSmiCodeInlining() { __ nop(); }
938
939 #undef __
940
941 #ifdef DEBUG
942
943 // Checks whether the code between start_pc and end_pc is a no-op.
944 bool CodeGenerator::IsNopForSmiCodeInlining(Handle<Code> code, int start_pc,
945                                             int end_pc) {
946   if (start_pc + 1 != end_pc) {
947     return false;
948   }
949   return *(code->instruction_start() + start_pc) ==
950          v8::internal::Assembler::kNopByte;
951 }
952
953 #endif  // DEBUG
954 }
955 }
956 }  // namespace v8::internal::compiler