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
15namespace v8 {
16namespace internal {
17namespace compiler {
18
19#define __ masm()->
20
21
22// Adds IA-32 specific methods for decoding operands.
23class 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
104static 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.
110void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
111  IA32OperandConverter i(this, instr);
112
113  switch (ArchOpcodeField::decode(instr->opcode())) {
114    case kArchCallCodeObject: {
115      EnsureSpaceForLazyDeopt();
116      if (HasImmediateInput(instr, 0)) {
117        Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
118        __ call(code, RelocInfo::CODE_TARGET);
119      } else {
120        Register reg = i.InputRegister(0);
121        __ call(Operand(reg, Code::kHeaderSize - kHeapObjectTag));
122      }
123      AddSafepointAndDeopt(instr);
124      break;
125    }
126    case kArchCallJSFunction: {
127      EnsureSpaceForLazyDeopt();
128      Register func = i.InputRegister(0);
129      if (FLAG_debug_code) {
130        // Check the function's context matches the context argument.
131        __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset));
132        __ Assert(equal, kWrongFunctionContext);
133      }
134      __ call(FieldOperand(func, JSFunction::kCodeEntryOffset));
135      AddSafepointAndDeopt(instr);
136      break;
137    }
138    case kArchJmp:
139      __ jmp(code()->GetLabel(i.InputBlock(0)));
140      break;
141    case kArchNop:
142      // don't emit code for nops.
143      break;
144    case kArchRet:
145      AssembleReturn();
146      break;
147    case kArchTruncateDoubleToI:
148      __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
149      break;
150    case kIA32Add:
151      if (HasImmediateInput(instr, 1)) {
152        __ add(i.InputOperand(0), i.InputImmediate(1));
153      } else {
154        __ add(i.InputRegister(0), i.InputOperand(1));
155      }
156      break;
157    case kIA32And:
158      if (HasImmediateInput(instr, 1)) {
159        __ and_(i.InputOperand(0), i.InputImmediate(1));
160      } else {
161        __ and_(i.InputRegister(0), i.InputOperand(1));
162      }
163      break;
164    case kIA32Cmp:
165      if (HasImmediateInput(instr, 1)) {
166        __ cmp(i.InputOperand(0), i.InputImmediate(1));
167      } else {
168        __ cmp(i.InputRegister(0), i.InputOperand(1));
169      }
170      break;
171    case kIA32Test:
172      if (HasImmediateInput(instr, 1)) {
173        __ test(i.InputOperand(0), i.InputImmediate(1));
174      } else {
175        __ test(i.InputRegister(0), i.InputOperand(1));
176      }
177      break;
178    case kIA32Imul:
179      if (HasImmediateInput(instr, 1)) {
180        __ imul(i.OutputRegister(), i.InputOperand(0), i.InputInt32(1));
181      } else {
182        __ imul(i.OutputRegister(), i.InputOperand(1));
183      }
184      break;
185    case kIA32Idiv:
186      __ cdq();
187      __ idiv(i.InputOperand(1));
188      break;
189    case kIA32Udiv:
190      __ xor_(edx, edx);
191      __ div(i.InputOperand(1));
192      break;
193    case kIA32Not:
194      __ not_(i.OutputOperand());
195      break;
196    case kIA32Neg:
197      __ neg(i.OutputOperand());
198      break;
199    case kIA32Or:
200      if (HasImmediateInput(instr, 1)) {
201        __ or_(i.InputOperand(0), i.InputImmediate(1));
202      } else {
203        __ or_(i.InputRegister(0), i.InputOperand(1));
204      }
205      break;
206    case kIA32Xor:
207      if (HasImmediateInput(instr, 1)) {
208        __ xor_(i.InputOperand(0), i.InputImmediate(1));
209      } else {
210        __ xor_(i.InputRegister(0), i.InputOperand(1));
211      }
212      break;
213    case kIA32Sub:
214      if (HasImmediateInput(instr, 1)) {
215        __ sub(i.InputOperand(0), i.InputImmediate(1));
216      } else {
217        __ sub(i.InputRegister(0), i.InputOperand(1));
218      }
219      break;
220    case kIA32Shl:
221      if (HasImmediateInput(instr, 1)) {
222        __ shl(i.OutputRegister(), i.InputInt5(1));
223      } else {
224        __ shl_cl(i.OutputRegister());
225      }
226      break;
227    case kIA32Shr:
228      if (HasImmediateInput(instr, 1)) {
229        __ shr(i.OutputRegister(), i.InputInt5(1));
230      } else {
231        __ shr_cl(i.OutputRegister());
232      }
233      break;
234    case kIA32Sar:
235      if (HasImmediateInput(instr, 1)) {
236        __ sar(i.OutputRegister(), i.InputInt5(1));
237      } else {
238        __ sar_cl(i.OutputRegister());
239      }
240      break;
241    case kIA32Ror:
242      if (HasImmediateInput(instr, 1)) {
243        __ ror(i.OutputRegister(), i.InputInt5(1));
244      } else {
245        __ ror_cl(i.OutputRegister());
246      }
247      break;
248    case kSSEFloat64Cmp:
249      __ ucomisd(i.InputDoubleRegister(0), i.InputOperand(1));
250      break;
251    case kSSEFloat64Add:
252      __ addsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
253      break;
254    case kSSEFloat64Sub:
255      __ subsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
256      break;
257    case kSSEFloat64Mul:
258      __ mulsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
259      break;
260    case kSSEFloat64Div:
261      __ divsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
262      break;
263    case kSSEFloat64Mod: {
264      // TODO(dcarney): alignment is wrong.
265      __ sub(esp, Immediate(kDoubleSize));
266      // Move values to st(0) and st(1).
267      __ movsd(Operand(esp, 0), i.InputDoubleRegister(1));
268      __ fld_d(Operand(esp, 0));
269      __ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
270      __ fld_d(Operand(esp, 0));
271      // Loop while fprem isn't done.
272      Label mod_loop;
273      __ bind(&mod_loop);
274      // This instructions traps on all kinds inputs, but we are assuming the
275      // floating point control word is set to ignore them all.
276      __ fprem();
277      // The following 2 instruction implicitly use eax.
278      __ fnstsw_ax();
279      __ sahf();
280      __ j(parity_even, &mod_loop);
281      // Move output to stack and clean up.
282      __ fstp(1);
283      __ fstp_d(Operand(esp, 0));
284      __ movsd(i.OutputDoubleRegister(), Operand(esp, 0));
285      __ add(esp, Immediate(kDoubleSize));
286      break;
287    }
288    case kSSEFloat64Sqrt:
289      __ sqrtsd(i.OutputDoubleRegister(), i.InputOperand(0));
290      break;
291    case kSSEFloat64ToInt32:
292      __ cvttsd2si(i.OutputRegister(), i.InputOperand(0));
293      break;
294    case kSSEFloat64ToUint32: {
295      XMMRegister scratch = xmm0;
296      __ Move(scratch, -2147483648.0);
297      __ addsd(scratch, i.InputOperand(0));
298      __ cvttsd2si(i.OutputRegister(), scratch);
299      __ add(i.OutputRegister(), Immediate(0x80000000));
300      break;
301    }
302    case kSSEInt32ToFloat64:
303      __ cvtsi2sd(i.OutputDoubleRegister(), i.InputOperand(0));
304      break;
305    case kSSEUint32ToFloat64:
306      // TODO(turbofan): IA32 SSE LoadUint32() should take an operand.
307      __ LoadUint32(i.OutputDoubleRegister(), i.InputRegister(0));
308      break;
309    case kIA32Movsxbl:
310      __ movsx_b(i.OutputRegister(), i.MemoryOperand());
311      break;
312    case kIA32Movzxbl:
313      __ movzx_b(i.OutputRegister(), i.MemoryOperand());
314      break;
315    case kIA32Movb: {
316      int index = 0;
317      Operand operand = i.MemoryOperand(&index);
318      if (HasImmediateInput(instr, index)) {
319        __ mov_b(operand, i.InputInt8(index));
320      } else {
321        __ mov_b(operand, i.InputRegister(index));
322      }
323      break;
324    }
325    case kIA32Movsxwl:
326      __ movsx_w(i.OutputRegister(), i.MemoryOperand());
327      break;
328    case kIA32Movzxwl:
329      __ movzx_w(i.OutputRegister(), i.MemoryOperand());
330      break;
331    case kIA32Movw: {
332      int index = 0;
333      Operand operand = i.MemoryOperand(&index);
334      if (HasImmediateInput(instr, index)) {
335        __ mov_w(operand, i.InputInt16(index));
336      } else {
337        __ mov_w(operand, i.InputRegister(index));
338      }
339      break;
340    }
341    case kIA32Movl:
342      if (instr->HasOutput()) {
343        __ mov(i.OutputRegister(), i.MemoryOperand());
344      } else {
345        int index = 0;
346        Operand operand = i.MemoryOperand(&index);
347        if (HasImmediateInput(instr, index)) {
348          __ mov(operand, i.InputImmediate(index));
349        } else {
350          __ mov(operand, i.InputRegister(index));
351        }
352      }
353      break;
354    case kIA32Movsd:
355      if (instr->HasOutput()) {
356        __ movsd(i.OutputDoubleRegister(), i.MemoryOperand());
357      } else {
358        int index = 0;
359        Operand operand = i.MemoryOperand(&index);
360        __ movsd(operand, i.InputDoubleRegister(index));
361      }
362      break;
363    case kIA32Movss:
364      if (instr->HasOutput()) {
365        __ movss(i.OutputDoubleRegister(), i.MemoryOperand());
366        __ cvtss2sd(i.OutputDoubleRegister(), i.OutputDoubleRegister());
367      } else {
368        int index = 0;
369        Operand operand = i.MemoryOperand(&index);
370        __ cvtsd2ss(xmm0, i.InputDoubleRegister(index));
371        __ movss(operand, xmm0);
372      }
373      break;
374    case kIA32Push:
375      if (HasImmediateInput(instr, 0)) {
376        __ push(i.InputImmediate(0));
377      } else {
378        __ push(i.InputOperand(0));
379      }
380      break;
381    case kIA32StoreWriteBarrier: {
382      Register object = i.InputRegister(0);
383      Register index = i.InputRegister(1);
384      Register value = i.InputRegister(2);
385      __ mov(Operand(object, index, times_1, 0), value);
386      __ lea(index, Operand(object, index, times_1, 0));
387      SaveFPRegsMode mode = code_->frame()->DidAllocateDoubleRegisters()
388                                ? kSaveFPRegs
389                                : kDontSaveFPRegs;
390      __ RecordWrite(object, index, value, mode);
391      break;
392    }
393  }
394}
395
396
397// Assembles branches after an instruction.
398void CodeGenerator::AssembleArchBranch(Instruction* instr,
399                                       FlagsCondition condition) {
400  IA32OperandConverter i(this, instr);
401  Label done;
402
403  // Emit a branch. The true and false targets are always the last two inputs
404  // to the instruction.
405  BasicBlock* tblock = i.InputBlock(instr->InputCount() - 2);
406  BasicBlock* fblock = i.InputBlock(instr->InputCount() - 1);
407  bool fallthru = IsNextInAssemblyOrder(fblock);
408  Label* tlabel = code()->GetLabel(tblock);
409  Label* flabel = fallthru ? &done : code()->GetLabel(fblock);
410  Label::Distance flabel_distance = fallthru ? Label::kNear : Label::kFar;
411  switch (condition) {
412    case kUnorderedEqual:
413      __ j(parity_even, flabel, flabel_distance);
414    // Fall through.
415    case kEqual:
416      __ j(equal, tlabel);
417      break;
418    case kUnorderedNotEqual:
419      __ j(parity_even, tlabel);
420    // Fall through.
421    case kNotEqual:
422      __ j(not_equal, tlabel);
423      break;
424    case kSignedLessThan:
425      __ j(less, tlabel);
426      break;
427    case kSignedGreaterThanOrEqual:
428      __ j(greater_equal, tlabel);
429      break;
430    case kSignedLessThanOrEqual:
431      __ j(less_equal, tlabel);
432      break;
433    case kSignedGreaterThan:
434      __ j(greater, tlabel);
435      break;
436    case kUnorderedLessThan:
437      __ j(parity_even, flabel, flabel_distance);
438    // Fall through.
439    case kUnsignedLessThan:
440      __ j(below, tlabel);
441      break;
442    case kUnorderedGreaterThanOrEqual:
443      __ j(parity_even, tlabel);
444    // Fall through.
445    case kUnsignedGreaterThanOrEqual:
446      __ j(above_equal, tlabel);
447      break;
448    case kUnorderedLessThanOrEqual:
449      __ j(parity_even, flabel, flabel_distance);
450    // Fall through.
451    case kUnsignedLessThanOrEqual:
452      __ j(below_equal, tlabel);
453      break;
454    case kUnorderedGreaterThan:
455      __ j(parity_even, tlabel);
456    // Fall through.
457    case kUnsignedGreaterThan:
458      __ j(above, tlabel);
459      break;
460    case kOverflow:
461      __ j(overflow, tlabel);
462      break;
463    case kNotOverflow:
464      __ j(no_overflow, tlabel);
465      break;
466  }
467  if (!fallthru) __ jmp(flabel, flabel_distance);  // no fallthru to flabel.
468  __ bind(&done);
469}
470
471
472// Assembles boolean materializations after an instruction.
473void CodeGenerator::AssembleArchBoolean(Instruction* instr,
474                                        FlagsCondition condition) {
475  IA32OperandConverter i(this, instr);
476  Label done;
477
478  // Materialize a full 32-bit 1 or 0 value. The result register is always the
479  // last output of the instruction.
480  Label check;
481  DCHECK_NE(0, instr->OutputCount());
482  Register reg = i.OutputRegister(instr->OutputCount() - 1);
483  Condition cc = no_condition;
484  switch (condition) {
485    case kUnorderedEqual:
486      __ j(parity_odd, &check, Label::kNear);
487      __ mov(reg, Immediate(0));
488      __ jmp(&done, Label::kNear);
489    // Fall through.
490    case kEqual:
491      cc = equal;
492      break;
493    case kUnorderedNotEqual:
494      __ j(parity_odd, &check, Label::kNear);
495      __ mov(reg, Immediate(1));
496      __ jmp(&done, Label::kNear);
497    // Fall through.
498    case kNotEqual:
499      cc = not_equal;
500      break;
501    case kSignedLessThan:
502      cc = less;
503      break;
504    case kSignedGreaterThanOrEqual:
505      cc = greater_equal;
506      break;
507    case kSignedLessThanOrEqual:
508      cc = less_equal;
509      break;
510    case kSignedGreaterThan:
511      cc = greater;
512      break;
513    case kUnorderedLessThan:
514      __ j(parity_odd, &check, Label::kNear);
515      __ mov(reg, Immediate(0));
516      __ jmp(&done, Label::kNear);
517    // Fall through.
518    case kUnsignedLessThan:
519      cc = below;
520      break;
521    case kUnorderedGreaterThanOrEqual:
522      __ j(parity_odd, &check, Label::kNear);
523      __ mov(reg, Immediate(1));
524      __ jmp(&done, Label::kNear);
525    // Fall through.
526    case kUnsignedGreaterThanOrEqual:
527      cc = above_equal;
528      break;
529    case kUnorderedLessThanOrEqual:
530      __ j(parity_odd, &check, Label::kNear);
531      __ mov(reg, Immediate(0));
532      __ jmp(&done, Label::kNear);
533    // Fall through.
534    case kUnsignedLessThanOrEqual:
535      cc = below_equal;
536      break;
537    case kUnorderedGreaterThan:
538      __ j(parity_odd, &check, Label::kNear);
539      __ mov(reg, Immediate(1));
540      __ jmp(&done, Label::kNear);
541    // Fall through.
542    case kUnsignedGreaterThan:
543      cc = above;
544      break;
545    case kOverflow:
546      cc = overflow;
547      break;
548    case kNotOverflow:
549      cc = no_overflow;
550      break;
551  }
552  __ bind(&check);
553  if (reg.is_byte_register()) {
554    // setcc for byte registers (al, bl, cl, dl).
555    __ setcc(cc, reg);
556    __ movzx_b(reg, reg);
557  } else {
558    // Emit a branch to set a register to either 1 or 0.
559    Label set;
560    __ j(cc, &set, Label::kNear);
561    __ mov(reg, Immediate(0));
562    __ jmp(&done, Label::kNear);
563    __ bind(&set);
564    __ mov(reg, Immediate(1));
565  }
566  __ bind(&done);
567}
568
569
570void CodeGenerator::AssembleDeoptimizerCall(int deoptimization_id) {
571  Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
572      isolate(), deoptimization_id, Deoptimizer::LAZY);
573  __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
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
705void 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
757void 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 = descriptor->IsJSFunctionCall()
786                        ? static_cast<int>(descriptor->JSParameterCount())
787                        : 0;
788    __ ret(pop_count * kPointerSize);
789  }
790}
791
792
793void CodeGenerator::AssembleMove(InstructionOperand* source,
794                                 InstructionOperand* destination) {
795  IA32OperandConverter g(this, NULL);
796  // Dispatch on the source and destination operand kinds.  Not all
797  // combinations are possible.
798  if (source->IsRegister()) {
799    DCHECK(destination->IsRegister() || destination->IsStackSlot());
800    Register src = g.ToRegister(source);
801    Operand dst = g.ToOperand(destination);
802    __ mov(dst, src);
803  } else if (source->IsStackSlot()) {
804    DCHECK(destination->IsRegister() || destination->IsStackSlot());
805    Operand src = g.ToOperand(source);
806    if (destination->IsRegister()) {
807      Register dst = g.ToRegister(destination);
808      __ mov(dst, src);
809    } else {
810      Operand dst = g.ToOperand(destination);
811      __ push(src);
812      __ pop(dst);
813    }
814  } else if (source->IsConstant()) {
815    Constant src_constant = g.ToConstant(source);
816    if (src_constant.type() == Constant::kHeapObject) {
817      Handle<HeapObject> src = src_constant.ToHeapObject();
818      if (destination->IsRegister()) {
819        Register dst = g.ToRegister(destination);
820        __ LoadHeapObject(dst, src);
821      } else {
822        DCHECK(destination->IsStackSlot());
823        Operand dst = g.ToOperand(destination);
824        AllowDeferredHandleDereference embedding_raw_address;
825        if (isolate()->heap()->InNewSpace(*src)) {
826          __ PushHeapObject(src);
827          __ pop(dst);
828        } else {
829          __ mov(dst, src);
830        }
831      }
832    } else if (destination->IsRegister()) {
833      Register dst = g.ToRegister(destination);
834      __ mov(dst, g.ToImmediate(source));
835    } else if (destination->IsStackSlot()) {
836      Operand dst = g.ToOperand(destination);
837      __ mov(dst, g.ToImmediate(source));
838    } else {
839      double v = g.ToDouble(source);
840      uint64_t int_val = bit_cast<uint64_t, double>(v);
841      int32_t lower = static_cast<int32_t>(int_val);
842      int32_t upper = static_cast<int32_t>(int_val >> kBitsPerInt);
843      if (destination->IsDoubleRegister()) {
844        XMMRegister dst = g.ToDoubleRegister(destination);
845        __ Move(dst, v);
846      } else {
847        DCHECK(destination->IsDoubleStackSlot());
848        Operand dst0 = g.ToOperand(destination);
849        Operand dst1 = g.HighOperand(destination);
850        __ mov(dst0, Immediate(lower));
851        __ mov(dst1, Immediate(upper));
852      }
853    }
854  } else if (source->IsDoubleRegister()) {
855    XMMRegister src = g.ToDoubleRegister(source);
856    if (destination->IsDoubleRegister()) {
857      XMMRegister dst = g.ToDoubleRegister(destination);
858      __ movaps(dst, src);
859    } else {
860      DCHECK(destination->IsDoubleStackSlot());
861      Operand dst = g.ToOperand(destination);
862      __ movsd(dst, src);
863    }
864  } else if (source->IsDoubleStackSlot()) {
865    DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
866    Operand src = g.ToOperand(source);
867    if (destination->IsDoubleRegister()) {
868      XMMRegister dst = g.ToDoubleRegister(destination);
869      __ movsd(dst, src);
870    } else {
871      // We rely on having xmm0 available as a fixed scratch register.
872      Operand dst = g.ToOperand(destination);
873      __ movsd(xmm0, src);
874      __ movsd(dst, xmm0);
875    }
876  } else {
877    UNREACHABLE();
878  }
879}
880
881
882void CodeGenerator::AssembleSwap(InstructionOperand* source,
883                                 InstructionOperand* destination) {
884  IA32OperandConverter g(this, NULL);
885  // Dispatch on the source and destination operand kinds.  Not all
886  // combinations are possible.
887  if (source->IsRegister() && destination->IsRegister()) {
888    // Register-register.
889    Register src = g.ToRegister(source);
890    Register dst = g.ToRegister(destination);
891    __ xchg(dst, src);
892  } else if (source->IsRegister() && destination->IsStackSlot()) {
893    // Register-memory.
894    __ xchg(g.ToRegister(source), g.ToOperand(destination));
895  } else if (source->IsStackSlot() && destination->IsStackSlot()) {
896    // Memory-memory.
897    Operand src = g.ToOperand(source);
898    Operand dst = g.ToOperand(destination);
899    __ push(dst);
900    __ push(src);
901    __ pop(dst);
902    __ pop(src);
903  } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) {
904    // XMM register-register swap. We rely on having xmm0
905    // available as a fixed scratch register.
906    XMMRegister src = g.ToDoubleRegister(source);
907    XMMRegister dst = g.ToDoubleRegister(destination);
908    __ movaps(xmm0, src);
909    __ movaps(src, dst);
910    __ movaps(dst, xmm0);
911  } else if (source->IsDoubleRegister() && source->IsDoubleStackSlot()) {
912    // XMM register-memory swap.  We rely on having xmm0
913    // available as a fixed scratch register.
914    XMMRegister reg = g.ToDoubleRegister(source);
915    Operand other = g.ToOperand(destination);
916    __ movsd(xmm0, other);
917    __ movsd(other, reg);
918    __ movaps(reg, xmm0);
919  } else if (source->IsDoubleStackSlot() && destination->IsDoubleStackSlot()) {
920    // Double-width memory-to-memory.
921    Operand src0 = g.ToOperand(source);
922    Operand src1 = g.HighOperand(source);
923    Operand dst0 = g.ToOperand(destination);
924    Operand dst1 = g.HighOperand(destination);
925    __ movsd(xmm0, dst0);  // Save destination in xmm0.
926    __ push(src0);         // Then use stack to copy source to destination.
927    __ pop(dst0);
928    __ push(src1);
929    __ pop(dst1);
930    __ movsd(src0, xmm0);
931  } else {
932    // No other combinations are possible.
933    UNREACHABLE();
934  }
935}
936
937
938void CodeGenerator::AddNopForSmiCodeInlining() { __ nop(); }
939
940
941void CodeGenerator::EnsureSpaceForLazyDeopt() {
942  int space_needed = Deoptimizer::patch_size();
943  if (!linkage()->info()->IsStub()) {
944    // Ensure that we have enough space after the previous lazy-bailout
945    // instruction for patching the code here.
946    int current_pc = masm()->pc_offset();
947    if (current_pc < last_lazy_deopt_pc_ + space_needed) {
948      int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
949      __ Nop(padding_size);
950    }
951  }
952  MarkLazyDeoptSite();
953}
954
955#undef __
956
957}  // namespace compiler
958}  // namespace internal
959}  // namespace v8
960