1 // [AsmJit]
2 // Complete JIT Assembler for C++ Language.
3 //
4 // [License]
5 // Zlib - See COPYING file in this package.
6 
7 #define ASMJIT_EXPORTS
8 
9 // [Dependencies - AsmJit]
10 #include "../core/intutil.h"
11 #include "../core/stringutil.h"
12 
13 #include "../x86/x86compiler.h"
14 #include "../x86/x86compilercontext.h"
15 #include "../x86/x86compilerfunc.h"
16 #include "../x86/x86compileritem.h"
17 #include "../x86/x86cpuinfo.h"
18 #include "../x86/x86util.h"
19 
20 // [Api-Begin]
21 #include "../core/apibegin.h"
22 
23 namespace AsmJit {
24 
25 // ============================================================================
26 // [AsmJit::X86Assembler - Logging]
27 // ============================================================================
28 
29 // Defined in AsmJit/X86/X86Assembler.cpp.
30 char* X86Assembler_dumpRegister(char* buf, uint32_t type, uint32_t index);
31 char* X86Assembler_dumpOperand(char* buf, const Operand* op, uint32_t memRegType, uint32_t loggerFlags);
32 
33 // ============================================================================
34 // [AsmJit::X86CompilerFuncDecl - Construction / Destructioin]
35 // ============================================================================
36 
X86CompilerFuncDecl(X86Compiler * x86Compiler)37 X86CompilerFuncDecl::X86CompilerFuncDecl(X86Compiler* x86Compiler) :
38   CompilerFuncDecl(x86Compiler),
39   _gpModifiedAndPreserved(0),
40   _mmModifiedAndPreserved(0),
41   _xmmModifiedAndPreserved(0),
42   _movDqInstCode(kInstNone),
43   _pePushPopStackSize(0),
44   _peMovStackSize(0),
45   _peAdjustStackSize(0),
46   _memStackSize(0),
47   _memStackSize16(0)
48 {
49   _decl = &_x86Decl;
50 
51   // Just clear to safe defaults.
52   _funcHints |= IntUtil::maskFromIndex(kX86FuncHintPushPop);
53 
54   // Stack is always aligned to 16-bytes when using 64-bit OS.
55   if (CompilerUtil::isStack16ByteAligned())
56     _funcHints |= IntUtil::maskFromIndex(kX86FuncHintAssume16ByteAlignment);
57 
58   _entryLabel = x86Compiler->newLabel();
59   _exitLabel = x86Compiler->newLabel();
60 
61   _entryTarget = x86Compiler->_getTarget(_entryLabel.getId());
62   _exitTarget = x86Compiler->_getTarget(_exitLabel.getId());
63 
64   _end = Compiler_newItem<X86CompilerFuncEnd>(x86Compiler, this);
65 }
66 
~X86CompilerFuncDecl()67 X86CompilerFuncDecl::~X86CompilerFuncDecl()
68 {
69 }
70 
71 // ============================================================================
72 // [AsmJit::X86CompilerFuncDecl - Interface]
73 // ============================================================================
74 
prepare(CompilerContext & cc)75 void X86CompilerFuncDecl::prepare(CompilerContext& cc)
76 {
77   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
78   _offset = x86Context._currentOffset++;
79 
80   _prepareVariables(this);
81 }
82 
translate(CompilerContext & cc)83 CompilerItem* X86CompilerFuncDecl::translate(CompilerContext& cc)
84 {
85   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
86 
87   _allocVariables(x86Context);
88   return translated();
89 }
90 
91 // ============================================================================
92 // [AsmJit::X86CompilerFuncDecl - Misc]
93 // ============================================================================
94 
getMaxSize() const95 int X86CompilerFuncDecl::getMaxSize() const
96 {
97   // NOP.
98   return 0;
99 }
100 
101 // ============================================================================
102 // [AsmJit::X86CompilerFuncDecl - Prototype]
103 // ============================================================================
104 
setPrototype(uint32_t convention,uint32_t returnType,const uint32_t * arguments,uint32_t argumentsCount)105 void X86CompilerFuncDecl::setPrototype(uint32_t convention, uint32_t returnType, const uint32_t* arguments, uint32_t argumentsCount)
106 {
107   _x86Decl.setPrototype(convention, returnType, arguments, argumentsCount);
108 }
109 
110 // ============================================================================
111 // [AsmJit::X86CompilerFuncDecl - Helpers]
112 // ============================================================================
113 
_createVariables()114 void X86CompilerFuncDecl::_createVariables()
115 {
116   X86Compiler* x86Compiler = getCompiler();
117 
118   uint32_t i, count = _x86Decl.getArgumentsCount();
119   if (count == 0) return;
120 
121   _vars = reinterpret_cast<CompilerVar**>(x86Compiler->getZoneMemory().alloc(count * sizeof(void*)));
122   if (_vars == NULL)
123   {
124     x86Compiler->setError(kErrorNoHeapMemory);
125     return;
126   }
127 
128   char argNameStorage[64];
129   char* argName = NULL;
130 
131   bool debug = x86Compiler->getLogger() != NULL;
132   if (debug) argName = argNameStorage;
133 
134   for (i = 0; i < count; i++)
135   {
136     FuncArg& arg = _x86Decl.getArgument(i);
137 
138     if (debug)
139       snprintf(argName, ASMJIT_ARRAY_SIZE(argNameStorage), "arg_%u", i);
140 
141     uint32_t size = X86Util::getVarSizeFromVarType(arg.getVarType());
142     X86CompilerVar* cv = x86Compiler->_newVar(argName, arg.getVarType(), size);
143 
144     if (arg.getRegIndex() != kRegIndexInvalid)
145     {
146       cv->_isRegArgument = true;
147       cv->regIndex = arg.getRegIndex();
148     }
149 
150     if (arg.getStackOffset() != kFuncStackInvalid)
151     {
152       cv->_isMemArgument = true;
153       cv->homeMemoryOffset = arg.getStackOffset();
154     }
155 
156     _vars[i] = cv;
157   }
158 }
159 
_prepareVariables(CompilerItem * first)160 void X86CompilerFuncDecl::_prepareVariables(CompilerItem* first)
161 {
162   uint32_t count = _x86Decl.getArgumentsCount();
163   if (count == 0) return;
164 
165   for (uint32_t i = 0; i < count; i++)
166   {
167     X86CompilerVar* cv = getVar(i);
168 
169     // This is where variable scope starts.
170     cv->firstItem = first;
171     // If this will not be changed then it will be deallocated immediately.
172     cv->lastItem = first;
173   }
174 }
175 
_allocVariables(CompilerContext & cc)176 void X86CompilerFuncDecl::_allocVariables(CompilerContext& cc)
177 {
178   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
179   uint32_t count = getDecl()->getArgumentsCount();
180 
181   if (count == 0)
182     return;
183 
184   for (uint32_t i = 0; i < count; i++)
185   {
186     X86CompilerVar* cv = getVar(i);
187 
188     if (cv->firstItem != NULL || cv->isArgument())
189     {
190       // Variable is used.
191       if (cv->regIndex != kRegIndexInvalid)
192       {
193         cv->state = kVarStateReg;
194         // If variable is in register -> mark it as changed so it will not be
195         // lost by first spill.
196         cv->changed = true;
197         x86Context._allocatedVariable(cv);
198       }
199       else if (cv->isMemArgument())
200       {
201         cv->state = kVarStateMem;
202       }
203     }
204     else
205     {
206       // Variable is not used.
207       cv->regIndex = kRegIndexInvalid;
208     }
209   }
210 }
211 
_preparePrologEpilog(CompilerContext & cc)212 void X86CompilerFuncDecl::_preparePrologEpilog(CompilerContext& cc)
213 {
214   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
215   const X86CpuInfo* cpuInfo = X86CpuInfo::getGlobal();
216 
217   clearFuncFlag(
218     kX86FuncFlagPushPop    |
219     kX86FuncFlagEmitEmms   |
220     kX86FuncFlagEmitSFence |
221     kX86FuncFlagEmitLFence |
222     kX86FuncFlagAssume16ByteAlignment |
223     kX86FuncFlagPerform16ByteAlignment);
224 
225   uint32_t accessibleMemoryBelowStack = 0;
226   if (getDecl()->getConvention() == kX86FuncConvX64U)
227     accessibleMemoryBelowStack = 128;
228 
229   if (getHint(kX86FuncHintAssume16ByteAlignment ))
230     setFuncFlag(kX86FuncFlagAssume16ByteAlignment);
231 
232   if (getHint(kX86FuncHintPerform16ByteAlignment))
233     setFuncFlag(kX86FuncFlagPerform16ByteAlignment);
234 
235   if (getHint(kFuncHintNaked) != 0)
236     setFuncFlag(kFuncFlagIsNaked);
237 
238   if (isCaller() && (x86Context._memBytesTotal > 0 || isAssumed16ByteAlignment()))
239     setFuncFlag(kX86FuncFlagIsEspAdjusted);
240 
241   if (x86Context._memBytesTotal > accessibleMemoryBelowStack)
242     setFuncFlag(kX86FuncFlagIsEspAdjusted);
243 
244   if (getHint(kX86FuncHintPushPop) != 0)
245     setFuncFlag(kX86FuncFlagPushPop);
246 
247   if (getHint(kX86FuncHintEmms) != 0)
248     setFuncFlag(kX86FuncFlagEmitEmms);
249 
250   if (getHint(kX86FuncHintSFence) != 0)
251     setFuncFlag(kX86FuncFlagEmitSFence);
252 
253   if (getHint(kX86FuncHintLFence) != 0)
254     setFuncFlag(kX86FuncFlagEmitLFence);
255 
256   // Updated to respect comment from issue #47, align also when using MMX code.
257   if (!isAssumed16ByteAlignment() && !isNaked() && (x86Context._mem16BlocksCount + (x86Context._mem8BlocksCount > 0)))
258   {
259     // Have to align stack to 16-bytes.
260     setFuncFlag(kX86FuncFlagIsEspAdjusted | kX86FuncFlagPerform16ByteAlignment);
261   }
262 
263   _gpModifiedAndPreserved  = x86Context._modifiedGpRegisters  & _x86Decl.getGpPreservedMask() & (~IntUtil::maskFromIndex(kX86RegIndexEsp));
264   _mmModifiedAndPreserved  = x86Context._modifiedMmRegisters  & _x86Decl.getMmPreservedMask();
265   _xmmModifiedAndPreserved = x86Context._modifiedXmmRegisters & _x86Decl.getXmmPreservedMask();
266   _movDqInstCode = (isAssumed16ByteAlignment() | isPerformed16ByteAlignment()) ? kX86InstMovDQA : kX86InstMovDQU;
267 
268   // Prolog & Epilog stack size.
269   {
270     int32_t memGpSize = IntUtil::bitCount(_gpModifiedAndPreserved) * sizeof(intptr_t);
271     int32_t memMmSize = IntUtil::bitCount(_mmModifiedAndPreserved) * 8;
272     int32_t memXmmSize = IntUtil::bitCount(_xmmModifiedAndPreserved) * 16;
273 
274     if (hasFuncFlag(kX86FuncFlagPushPop))
275     {
276       _pePushPopStackSize = memGpSize;
277       _peMovStackSize = memXmmSize + IntUtil::align<int32_t>(memMmSize, 16);
278     }
279     else
280     {
281       _pePushPopStackSize = 0;
282       _peMovStackSize = memXmmSize + IntUtil::align<int32_t>(memMmSize + memGpSize, 16);
283     }
284   }
285 
286   if (isPerformed16ByteAlignment())
287   {
288     _peAdjustStackSize += IntUtil::delta<int32_t>(_pePushPopStackSize, 16);
289   }
290   else
291   {
292     int32_t v = 16 - sizeof(uintptr_t);
293 
294     if (!isNaked())
295       v -= sizeof(uintptr_t);
296 
297     v -= _pePushPopStackSize & 15;
298 
299     if (v < 0)
300       v += 16;
301 
302     _peAdjustStackSize = v;
303 
304     //_peAdjustStackSize += IntUtil::delta<int32_t>(_pePushPopStackSize + v, 16);
305   }
306 
307   // Memory stack size.
308   _memStackSize = x86Context._memBytesTotal;
309   _memStackSize16 = IntUtil::align(_memStackSize, 16);
310 
311   if (isNaked())
312   {
313     x86Context._argumentsBaseReg = kX86RegIndexEsp;
314     x86Context._argumentsBaseOffset = hasFuncFlag(kX86FuncFlagIsEspAdjusted)
315       ? (_funcCallStackSize + _memStackSize16 + _peMovStackSize + _pePushPopStackSize + _peAdjustStackSize)
316       : (_pePushPopStackSize);
317   }
318   else
319   {
320     x86Context._argumentsBaseReg = kX86RegIndexEbp;
321     x86Context._argumentsBaseOffset = sizeof(sysint_t);
322   }
323 
324   x86Context._variablesBaseReg = kX86RegIndexEsp;
325   x86Context._variablesBaseOffset = _funcCallStackSize;
326 
327   if (!hasFuncFlag(kX86FuncFlagIsEspAdjusted))
328     x86Context._variablesBaseOffset = -_memStackSize16 - _peMovStackSize - _peAdjustStackSize;
329 }
330 
_dumpFunction(CompilerContext & cc)331 void X86CompilerFuncDecl::_dumpFunction(CompilerContext& cc)
332 {
333   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
334   X86Compiler* x86Compiler = getCompiler();
335 
336   Logger* logger = x86Compiler->getLogger();
337   ASMJIT_ASSERT(logger != NULL);
338 
339   uint32_t i;
340   char _buf[1024];
341   char* p;
342 
343   // Log function prototype.
344   {
345     uint32_t argumentsCount = _x86Decl.getArgumentsCount();
346     bool first = true;
347 
348     logger->logString("; Function Prototype:\n");
349     logger->logString(";\n");
350 
351     for (i = 0; i < argumentsCount; i++)
352     {
353       const FuncArg& a = _x86Decl.getArgument(i);
354       X86CompilerVar* cv = getVar(i);
355 
356       if (first)
357       {
358         logger->logString("; IDX| Type     | Sz | Home           |\n");
359         logger->logString("; ---+----------+----+----------------+\n");
360       }
361 
362       char* memHome = memHome = _buf;
363 
364       if (a.hasRegIndex())
365       {
366         Reg regOp(a.getRegIndex() | kX86RegTypeGpz, 0);
367         X86Assembler_dumpOperand(memHome, &regOp, kX86RegTypeGpz, 0)[0] = '\0';
368       }
369       else
370       {
371         Mem memOp;
372         memOp._mem.base = kX86RegIndexEsp;
373         memOp._mem.displacement = a.getStackOffset();
374         X86Assembler_dumpOperand(memHome, &memOp, kX86RegTypeGpz, 0)[0] = '\0';
375       }
376 
377       logger->logFormat("; %-3u| %-9s| %-3u| %-15s|\n",
378         // Argument index.
379         i,
380         // Argument type.
381         cv->getType() < kX86VarTypeCount ? x86VarInfo[cv->getType()].getName() : "invalid",
382         // Argument size.
383         cv->getSize(),
384         // Argument memory home.
385         memHome
386       );
387 
388       first = false;
389     }
390     logger->logString(";\n");
391   }
392 
393   // Log variables.
394   {
395     uint32_t variablesCount = (uint32_t)x86Compiler->_vars.getLength();
396     bool first = true;
397 
398     logger->logString("; Variables:\n");
399     logger->logString(";\n");
400 
401     for (i = 0; i < variablesCount; i++)
402     {
403       X86CompilerVar* cv = static_cast<X86CompilerVar*>(x86Compiler->_vars[i]);
404 
405       // If this variable is not related to this function then skip it.
406       if (cv->funcScope != this)
407         continue;
408 
409       // Get some information about variable type.
410       const X86VarInfo& vinfo = x86VarInfo[cv->getType()];
411 
412       if (first)
413       {
414         logger->logString("; ID | Type     | Sz | Home           | Register Access   | Memory Access     |\n");
415         logger->logString("; ---+----------+----+----------------+-------------------+-------------------+\n");
416       }
417 
418       char* memHome = (char*)"[None]";
419       if (cv->homeMemoryData != NULL)
420       {
421         VarMemBlock* memBlock = reinterpret_cast<VarMemBlock*>(cv->homeMemoryData);
422         memHome = _buf;
423 
424         Mem memOp;
425         if (cv->isMemArgument())
426         {
427           const FuncArg& a = _x86Decl.getArgument(i);
428 
429           memOp._mem.base = x86Context._argumentsBaseReg;
430           memOp._mem.displacement += x86Context._argumentsBaseOffset;
431           memOp._mem.displacement += a.getStackOffset();
432         }
433         else
434         {
435           memOp._mem.base = x86Context._variablesBaseReg;
436           memOp._mem.displacement += x86Context._variablesBaseOffset;
437           memOp._mem.displacement += memBlock->offset;
438         }
439         X86Assembler_dumpOperand(memHome, &memOp, kX86RegTypeGpz, 0)[0] = '\0';
440       }
441 
442       logger->logFormat("; %-3u| %-9s| %-3u| %-15s| r=%-4uw=%-4ux=%-4u| r=%-4uw=%-4ux=%-4u|\n",
443         // Variable id.
444         (uint)(i & kOperandIdValueMask),
445         // Variable type.
446         cv->getType() < kX86VarTypeCount ? vinfo.getName() : "invalid",
447         // Variable size.
448         cv->getSize(),
449         // Variable memory home.
450         memHome,
451         // Register access count.
452         (unsigned int)cv->regReadCount,
453         (unsigned int)cv->regWriteCount,
454         (unsigned int)cv->regRwCount,
455         // Memory access count.
456         (unsigned int)cv->memReadCount,
457         (unsigned int)cv->memWriteCount,
458         (unsigned int)cv->memRwCount
459       );
460       first = false;
461     }
462     logger->logString(";\n");
463   }
464 
465   // Log modified registers.
466   {
467     p = _buf;
468 
469     uint32_t r;
470     uint32_t modifiedRegisters = 0;
471 
472     for (r = 0; r < 3; r++)
473     {
474       bool first = true;
475       uint32_t regs;
476       uint32_t type;
477 
478       switch (r)
479       {
480         case 0:
481           regs = x86Context._modifiedGpRegisters;
482           type = kX86RegTypeGpz;
483           p = StringUtil::copy(p, "; GP : ");
484           break;
485         case 1:
486           regs = x86Context._modifiedMmRegisters;
487           type = kX86RegTypeMm;
488           p = StringUtil::copy(p, "; MM : ");
489           break;
490         case 2:
491           regs = x86Context._modifiedXmmRegisters;
492           type = kX86RegTypeXmm;
493           p = StringUtil::copy(p, "; XMM: ");
494           break;
495         default:
496           ASMJIT_ASSERT(0);
497       }
498 
499       for (i = 0; i < kX86RegNumBase; i++)
500       {
501         if ((regs & IntUtil::maskFromIndex(i)) != 0)
502         {
503           if (!first) { *p++ = ','; *p++ = ' '; }
504           p = X86Assembler_dumpRegister(p, type, i);
505           first = false;
506           modifiedRegisters++;
507         }
508       }
509       *p++ = '\n';
510     }
511     *p = '\0';
512 
513     logger->logFormat("; Modified registers (%u):\n", (unsigned int)modifiedRegisters);
514     logger->logString(_buf);
515   }
516 
517   logger->logString("\n");
518 }
519 
_emitProlog(CompilerContext & cc)520 void X86CompilerFuncDecl::_emitProlog(CompilerContext& cc)
521 {
522   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
523   X86Compiler* x86Compiler = getCompiler();
524 
525   // --------------------------------------------------------------------------
526   // [Init]
527   // --------------------------------------------------------------------------
528 
529   uint32_t i, mask;
530   uint32_t preservedGP  = _gpModifiedAndPreserved;
531   uint32_t preservedMM  = _mmModifiedAndPreserved;
532   uint32_t preservedXMM = _xmmModifiedAndPreserved;
533 
534   int32_t stackOffset = _getRequiredStackOffset();
535   int32_t stackPos;
536 
537   // --------------------------------------------------------------------------
538   // [Prolog]
539   // --------------------------------------------------------------------------
540 
541   if (x86Compiler->getLogger())
542     x86Compiler->comment("Prolog");
543 
544   // Emit standard prolog entry code (but don't do it if function is set to be
545   // naked).
546   //
547   // Also see the _prologEpilogStackAdjust variable. If function is naked (so
548   // prolog and epilog will not contain "push ebp" and "mov ebp, esp", we need
549   // to adjust stack by 8 bytes in 64-bit mode (this will give us that stack
550   // will remain aligned to 16 bytes).
551   if (!isNaked())
552   {
553     x86Compiler->emit(kX86InstPush, zbp);
554     x86Compiler->emit(kX86InstMov, zbp, zsp);
555   }
556 
557   // Align manually stack-pointer to 16-bytes.
558   if (isPerformed16ByteAlignment())
559   {
560     ASMJIT_ASSERT(!isNaked());
561     x86Compiler->emit(kX86InstAnd, zsp, imm(-16));
562   }
563 
564   // --------------------------------------------------------------------------
565   // [Save Gp - Push/Pop]
566   // --------------------------------------------------------------------------
567 
568   if (preservedGP != 0 && hasFuncFlag(kX86FuncFlagPushPop))
569   {
570     for (i = 0, mask = 1; i < kX86RegNumGp; i++, mask <<= 1)
571     {
572       if (preservedGP & mask)
573         x86Compiler->emit(kX86InstPush, gpz(i));
574     }
575   }
576 
577   // --------------------------------------------------------------------------
578   // [Adjust Scack]
579   // --------------------------------------------------------------------------
580 
581   if (isEspAdjusted())
582   {
583     stackPos = _memStackSize16 + _funcCallStackSize;
584     if (stackOffset != 0)
585       x86Compiler->emit(kX86InstSub, zsp, imm(stackOffset));
586   }
587   else
588   {
589     stackPos = -(_peMovStackSize + _peAdjustStackSize);
590     //if (_pePushPop) stackPos += IntUtil::bitCount(preservedGP) * sizeof(sysint_t);
591   }
592 
593   // --------------------------------------------------------------------------
594   // [Save Xmm - MovDqa/MovDqu]
595   // --------------------------------------------------------------------------
596 
597   if (preservedXMM != 0)
598   {
599     for (i = 0, mask = 1; i < kX86RegNumXmm; i++, mask <<= 1)
600     {
601       if (preservedXMM & mask)
602       {
603         x86Compiler->emit(_movDqInstCode, dqword_ptr(zsp, stackPos), xmm(i));
604         stackPos += 16;
605       }
606     }
607   }
608 
609   // --------------------------------------------------------------------------
610   // [Save Mm - MovQ]
611   // --------------------------------------------------------------------------
612 
613   if (preservedMM != 0)
614   {
615     for (i = 0, mask = 1; i < 8; i++, mask <<= 1)
616     {
617       if (preservedMM & mask)
618       {
619         x86Compiler->emit(kX86InstMovQ, qword_ptr(zsp, stackPos), mm(i));
620         stackPos += 8;
621       }
622     }
623   }
624 
625   // --------------------------------------------------------------------------
626   // [Save Gp - Mov]
627   // --------------------------------------------------------------------------
628 
629   if (preservedGP != 0 && !hasFuncFlag(kX86FuncFlagPushPop))
630   {
631     for (i = 0, mask = 1; i < kX86RegNumGp; i++, mask <<= 1)
632     {
633       if (preservedGP & mask)
634       {
635         x86Compiler->emit(kX86InstMov, sysint_ptr(zsp, stackPos), gpz(i));
636         stackPos += sizeof(sysint_t);
637       }
638     }
639   }
640 
641   // --------------------------------------------------------------------------
642   // [...]
643   // --------------------------------------------------------------------------
644 
645   if (x86Compiler->getLogger())
646     x86Compiler->comment("Body");
647 }
648 
_emitEpilog(CompilerContext & cc)649 void X86CompilerFuncDecl::_emitEpilog(CompilerContext& cc)
650 {
651   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
652   X86Compiler* x86Compiler = getCompiler();
653 
654   const X86CpuInfo* cpuInfo = X86CpuInfo::getGlobal();
655 
656   // --------------------------------------------------------------------------
657   // [Init]
658   // --------------------------------------------------------------------------
659 
660   uint32_t i, mask;
661   uint32_t preservedGP  = _gpModifiedAndPreserved;
662   uint32_t preservedMM  = _mmModifiedAndPreserved;
663   uint32_t preservedXMM = _xmmModifiedAndPreserved;
664 
665   int32_t stackOffset = _getRequiredStackOffset();
666   int32_t stackPos;
667 
668   if (isEspAdjusted())
669     stackPos = _memStackSize16 + _funcCallStackSize;
670   else
671     stackPos = -(_peMovStackSize + _peAdjustStackSize);
672 
673   // --------------------------------------------------------------------------
674   // [Epilog]
675   // --------------------------------------------------------------------------
676 
677   if (x86Compiler->getLogger())
678     x86Compiler->comment("Epilog");
679 
680   // --------------------------------------------------------------------------
681   // [Restore Xmm - MovDqa/ModDqu]
682   // --------------------------------------------------------------------------
683 
684   if (preservedXMM != 0)
685   {
686     for (i = 0, mask = 1; i < kX86RegNumXmm; i++, mask <<= 1)
687     {
688       if (preservedXMM & mask)
689       {
690         x86Compiler->emit(_movDqInstCode, xmm(i), dqword_ptr(zsp, stackPos));
691         stackPos += 16;
692       }
693     }
694   }
695 
696   // --------------------------------------------------------------------------
697   // [Restore Mm - MovQ]
698   // --------------------------------------------------------------------------
699 
700   if (preservedMM != 0)
701   {
702     for (i = 0, mask = 1; i < 8; i++, mask <<= 1)
703     {
704       if (preservedMM & mask)
705       {
706         x86Compiler->emit(kX86InstMovQ, mm(i), qword_ptr(zsp, stackPos));
707         stackPos += 8;
708       }
709     }
710   }
711 
712   // --------------------------------------------------------------------------
713   // [Restore Gp - Mov]
714   // --------------------------------------------------------------------------
715 
716   if (preservedGP != 0 && !hasFuncFlag(kX86FuncFlagPushPop))
717   {
718     for (i = 0, mask = 1; i < kX86RegNumGp; i++, mask <<= 1)
719     {
720       if (preservedGP & mask)
721       {
722         x86Compiler->emit(kX86InstMov, gpz(i), sysint_ptr(zsp, stackPos));
723         stackPos += sizeof(sysint_t);
724       }
725     }
726   }
727 
728   // --------------------------------------------------------------------------
729   // [Adjust Stack]
730   // --------------------------------------------------------------------------
731 
732   if (isEspAdjusted() && stackOffset != 0)
733     x86Compiler->emit(kX86InstAdd, zsp, imm(stackOffset));
734 
735   // --------------------------------------------------------------------------
736   // [Restore Gp - Push/Pop]
737   // --------------------------------------------------------------------------
738 
739   if (preservedGP != 0 && hasFuncFlag(kX86FuncFlagPushPop))
740   {
741     for (i = kX86RegNumGp - 1, mask = 1 << i; (int32_t)i >= 0; i--, mask >>= 1)
742     {
743       if (preservedGP & mask)
744         x86Compiler->emit(kX86InstPop, gpz(i));
745     }
746   }
747 
748   // --------------------------------------------------------------------------
749   // [Emms]
750   // --------------------------------------------------------------------------
751 
752   if (hasFuncFlag(kX86FuncFlagEmitEmms))
753     x86Compiler->emit(kX86InstEmms);
754 
755   // --------------------------------------------------------------------------
756   // [MFence/SFence/LFence]
757   // --------------------------------------------------------------------------
758 
759   if (hasFuncFlag(kX86FuncFlagEmitSFence) & hasFuncFlag(kX86FuncFlagEmitLFence))
760     x86Compiler->emit(kX86InstMFence);
761   else if (hasFuncFlag(kX86FuncFlagEmitSFence))
762     x86Compiler->emit(kX86InstSFence);
763   else if (hasFuncFlag(kX86FuncFlagEmitLFence))
764     x86Compiler->emit(kX86InstLFence);
765 
766   // --------------------------------------------------------------------------
767   // [Epilog]
768   // --------------------------------------------------------------------------
769 
770   // Emit standard epilog leave code (if needed).
771   if (!isNaked())
772   {
773     // AMD seems to prefer LEAVE instead of MOV/POP sequence.
774     if (cpuInfo->getVendorId() == kCpuAmd)
775     {
776       x86Compiler->emit(kX86InstLeave);
777     }
778     else
779     {
780       x86Compiler->emit(kX86InstMov, zsp, zbp);
781       x86Compiler->emit(kX86InstPop, zbp);
782     }
783   }
784 
785   // Emit return.
786   if (_x86Decl.getCalleePopsStack())
787     x86Compiler->emit(kX86InstRet, imm((int16_t)_x86Decl.getArgumentsStackSize()));
788   else
789     x86Compiler->emit(kX86InstRet);
790 }
791 
792 // ============================================================================
793 // [AsmJit::X86CompilerFuncDecl - Function-Call]
794 // ============================================================================
795 
reserveStackForFunctionCall(int32_t size)796 void X86CompilerFuncDecl::reserveStackForFunctionCall(int32_t size)
797 {
798   size = IntUtil::align<int32_t>(size, 16);
799   if (size > _funcCallStackSize)
800     _funcCallStackSize = size;
801   setFuncFlag(kFuncFlagIsCaller);
802 }
803 
804 // ============================================================================
805 // [AsmJit::X86CompilerFuncEnd - Construction / Destruction]
806 // ============================================================================
807 
X86CompilerFuncEnd(X86Compiler * x86Compiler,X86CompilerFuncDecl * func)808 X86CompilerFuncEnd::X86CompilerFuncEnd(X86Compiler* x86Compiler, X86CompilerFuncDecl* func) :
809   CompilerFuncEnd(x86Compiler, func)
810 {
811 }
812 
~X86CompilerFuncEnd()813 X86CompilerFuncEnd::~X86CompilerFuncEnd()
814 {
815 }
816 
817 // ============================================================================
818 // [AsmJit::X86CompilerFuncEnd - Interface]
819 // ============================================================================
820 
prepare(CompilerContext & cc)821 void X86CompilerFuncEnd::prepare(CompilerContext& cc)
822 {
823   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
824   _offset = x86Context._currentOffset++;
825 }
826 
translate(CompilerContext & cc)827 CompilerItem* X86CompilerFuncEnd::translate(CompilerContext& cc)
828 {
829   _isTranslated = true;
830   return NULL;
831 }
832 
833 // ============================================================================
834 // [AsmJit::X86CompilerFuncRet - Construction / Destruction]
835 // ============================================================================
836 
X86CompilerFuncRet(X86Compiler * x86Compiler,X86CompilerFuncDecl * func,const Operand * first,const Operand * second)837 X86CompilerFuncRet::X86CompilerFuncRet(X86Compiler* x86Compiler, X86CompilerFuncDecl* func, const Operand* first, const Operand* second) :
838   CompilerFuncRet(x86Compiler, func, first, second)
839 {
840 /*
841   // TODO:?
842 
843   // Check whether the return value is compatible.
844   uint32_t retValType = function->_x86Decl.getReturnType();
845   bool valid = false;
846 
847   switch (retValType)
848   {
849     case kX86VarTypeGpd:
850     case kX86VarTypeGpq:
851       if ((_ret[0].isVar() && (reinterpret_cast<const Var&>(_ret[0]).isGpVar())) ||
852           (_ret[0].isImm()))
853       {
854         valid = true;
855       }
856       break;
857 
858     case kX86VarTypeX87:
859     case kX86VarTypeX87SS:
860     case kX86VarTypeX87SD:
861       if ((_ret[0].isVar() && (reinterpret_cast<const Var&>(_ret[0]).isX87Var() ||
862                                reinterpret_cast<const Var&>(_ret[0]).isXmmVar() )) )
863       {
864         valid = true;
865       }
866       break;
867 
868     case kX86VarTypeMm:
869       break;
870 
871     case kVarTypeInvalid:
872       if (_ret[0].isNone() &&
873           _ret[1].isNone())
874       {
875         valid = true;
876       }
877       break;
878 
879     default:
880       break;
881   }
882 
883   // Incompatible return value.
884   if (!valid)
885   {
886     c->setError(kErrorIncompatibleReturnType);
887   }
888 */
889 }
890 
~X86CompilerFuncRet()891 X86CompilerFuncRet::~X86CompilerFuncRet()
892 {
893 }
894 
895 // ============================================================================
896 // [AsmJit::X86CompilerFuncRet - Interface]
897 // ============================================================================
898 
prepare(CompilerContext & cc)899 void X86CompilerFuncRet::prepare(CompilerContext& cc)
900 {
901   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
902   X86Compiler* x86Compiler = x86Context.getCompiler();
903 
904   uint32_t retValType = getFunc()->_x86Decl.getReturnType();
905   _offset = x86Context._currentOffset;
906 
907   if (retValType != kVarTypeInvalid)
908   {
909     uint32_t i;
910     for (i = 0; i < 2; i++)
911     {
912       Operand& o = _ret[i];
913 
914       if (o.isVar())
915       {
916         ASMJIT_ASSERT(o.getId() != kInvalidValue);
917         X86CompilerVar* cv = x86Compiler->_getVar(o.getId());
918         ASMJIT_ASSERT(cv != NULL);
919 
920         // First item (begin of variable scope).
921         if (cv->firstItem == NULL) cv->firstItem = this;
922 
923         // Last item (end of variable scope).
924         cv->lastItem = this;
925 
926         if (cv->workOffset == _offset) continue;
927         if (!x86Context._isActive(cv)) x86Context._addActive(cv);
928 
929         cv->workOffset = _offset;
930         cv->regReadCount++;
931 
932         if (X86Util::isVarTypeInt(cv->getType()) && X86Util::isVarTypeInt(retValType))
933         {
934           x86Context._newRegisterHomeIndex(cv, (i == 0) ? kX86RegIndexEax : kX86RegIndexEdx);
935         }
936       }
937     }
938   }
939 
940   x86Context._currentOffset++;
941 }
942 
translate(CompilerContext & cc)943 CompilerItem* X86CompilerFuncRet::translate(CompilerContext& cc)
944 {
945   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
946   X86Compiler* x86Compiler = x86Context.getCompiler();
947 
948   // Check whether the return value is compatible.
949   uint32_t retValType = getFunc()->getDecl()->getReturnType();
950   uint32_t i;
951 
952   switch (retValType)
953   {
954     case kX86VarTypeGpd:
955     case kX86VarTypeGpq:
956       for (i = 0; i < 2; i++)
957       {
958         uint32_t dstIndex = (i == 0) ? kX86RegIndexEax : kX86RegIndexEdx;
959         uint32_t srcIndex;
960 
961         if (_ret[i].isVar())
962         {
963           if (reinterpret_cast<const Var&>(_ret[i]).isGpVar())
964           {
965             X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId());
966             ASMJIT_ASSERT(cv != NULL);
967 
968             srcIndex = cv->regIndex;
969             if (srcIndex == kRegIndexInvalid)
970               x86Compiler->emit(kX86InstMov, gpz(dstIndex), x86Context._getVarMem(cv));
971             else if (dstIndex != srcIndex)
972               x86Compiler->emit(kX86InstMov, gpz(dstIndex), gpz(srcIndex));
973           }
974         }
975         else if (_ret[i].isImm())
976         {
977           x86Compiler->emit(kX86InstMov, gpz(dstIndex), _ret[i]);
978         }
979       }
980       break;
981 
982     case kX86VarTypeX87:
983     case kX86VarTypeX87SS:
984     case kX86VarTypeX87SD:
985       // There is case that we need to return two values (Unix-ABI specific):
986       // - FLD #2
987       //-  FLD #1
988       i = 2;
989       do {
990         i--;
991         uint32_t dsti = i;
992         uint32_t srci;
993 
994         if (_ret[i].isVar())
995         {
996           if (reinterpret_cast<const Var&>(_ret[i]).isX87Var())
997           {
998             // TODO: X87 Support.
999           }
1000           else if (reinterpret_cast<const Var&>(_ret[i]).isXmmVar())
1001           {
1002             X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId());
1003             ASMJIT_ASSERT(cv != NULL);
1004 
1005             srci = cv->regIndex;
1006             if (srci != kRegIndexInvalid)
1007               x86Context.saveXmmVar(cv);
1008 
1009             switch (cv->getType())
1010             {
1011               case kX86VarTypeXmmSS:
1012               case kX86VarTypeXmmPS:
1013                 x86Compiler->emit(kX86InstFLd, _BaseVarMem(reinterpret_cast<Var&>(_ret[i]), 4));
1014                 break;
1015               case kX86VarTypeXmmSD:
1016               case kX86VarTypeXmmPD:
1017                 x86Compiler->emit(kX86InstFLd, _BaseVarMem(reinterpret_cast<Var&>(_ret[i]), 8));
1018                 break;
1019             }
1020           }
1021         }
1022       } while (i != 0);
1023       break;
1024 
1025     case kX86VarTypeMm:
1026       for (i = 0; i < 2; i++)
1027       {
1028         uint32_t dsti = i;
1029         uint32_t srci;
1030 
1031         if (_ret[i].isVar())
1032         {
1033           if (reinterpret_cast<const Var&>(_ret[i]).isGpVar())
1034           {
1035             X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId());
1036             ASMJIT_ASSERT(cv != NULL);
1037 
1038             srci = cv->regIndex;
1039             uint32_t inst = _ret[i].isRegType(kX86RegTypeGpq) ? kX86InstMovQ : kX86InstMovD;
1040 
1041             if (srci == kRegIndexInvalid)
1042               x86Compiler->emit(inst, mm(dsti), x86Context._getVarMem(cv));
1043             else
1044 #if defined(ASMJIT_X86)
1045               x86Compiler->emit(inst, mm(dsti), gpd(srci));
1046 #else
1047               x86Compiler->emit(inst, mm(dsti), _ret[i].isRegType(kX86RegTypeGpq) ? gpq(srci) : gpd(srci));
1048 #endif
1049           }
1050           else if (reinterpret_cast<const Var&>(_ret[i]).isMmVar())
1051           {
1052             X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId());
1053             ASMJIT_ASSERT(cv != NULL);
1054 
1055             srci = cv->regIndex;
1056             uint32_t inst = kX86InstMovQ;
1057 
1058             if (srci == kRegIndexInvalid)
1059               x86Compiler->emit(inst, mm(dsti), x86Context._getVarMem(cv));
1060             else if (dsti != srci)
1061               x86Compiler->emit(inst, mm(dsti), mm(srci));
1062           }
1063           else if (reinterpret_cast<const Var&>(_ret[i]).isXmmVar())
1064           {
1065             X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId());
1066             ASMJIT_ASSERT(cv != NULL);
1067 
1068             srci = cv->regIndex;
1069             uint32_t inst = kX86InstMovQ;
1070             if (reinterpret_cast<const Var&>(_ret[i]).getVarType() == kX86VarTypeXmmSS) inst = kX86InstMovD;
1071 
1072             if (srci == kRegIndexInvalid)
1073               x86Compiler->emit(inst, mm(dsti), x86Context._getVarMem(cv));
1074             else
1075               x86Compiler->emit(inst, mm(dsti), xmm(srci));
1076           }
1077         }
1078       }
1079       break;
1080 
1081     case kX86VarTypeXmm:
1082     case kX86VarTypeXmmPS:
1083     case kX86VarTypeXmmPD:
1084       for (i = 0; i < 2; i++)
1085       {
1086         uint32_t dsti = i;
1087         uint32_t srci;
1088 
1089         if (_ret[i].isVar())
1090         {
1091           if (reinterpret_cast<const Var&>(_ret[i]).isGpVar())
1092           {
1093             X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId());
1094             ASMJIT_ASSERT(cv != NULL);
1095 
1096             srci = cv->regIndex;
1097             uint32_t inst = _ret[i].isRegType(kX86RegTypeGpq) ? kX86InstMovQ : kX86InstMovD;
1098 
1099             if (srci == kRegIndexInvalid)
1100               x86Compiler->emit(inst, xmm(dsti), x86Context._getVarMem(cv));
1101             else
1102 #if defined(ASMJIT_X86)
1103               x86Compiler->emit(inst, xmm(dsti), gpd(srci));
1104 #else
1105               x86Compiler->emit(inst, xmm(dsti), _ret[i].isRegType(kX86RegTypeGpq) ? gpq(srci) : gpd(srci));
1106 #endif
1107           }
1108           else if (reinterpret_cast<const Var&>(_ret[i]).isX87Var())
1109           {
1110             // TODO: X87 Support.
1111           }
1112           else if (reinterpret_cast<const Var&>(_ret[i]).isMmVar())
1113           {
1114             X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId());
1115             ASMJIT_ASSERT(cv != NULL);
1116 
1117             srci = cv->regIndex;
1118             if (srci == kRegIndexInvalid)
1119               x86Compiler->emit(kX86InstMovQ, xmm(dsti), x86Context._getVarMem(cv));
1120             else
1121               x86Compiler->emit(kX86InstMovQ, xmm(dsti), mm(srci));
1122           }
1123           else if (reinterpret_cast<const Var&>(_ret[i]).isXmmVar())
1124           {
1125             X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId());
1126             ASMJIT_ASSERT(cv != NULL);
1127 
1128             srci = cv->regIndex;
1129             if (srci == kRegIndexInvalid)
1130               x86Compiler->emit(kX86InstMovDQA, xmm(dsti), x86Context._getVarMem(cv));
1131             else if (dsti != srci)
1132               x86Compiler->emit(kX86InstMovDQA, xmm(dsti), xmm(srci));
1133           }
1134         }
1135       }
1136       break;
1137 
1138     case kX86VarTypeXmmSS:
1139       for (i = 0; i < 2; i++)
1140       {
1141         uint32_t dsti = i;
1142         uint32_t srci;
1143 
1144         if (_ret[i].isVar())
1145         {
1146           if (reinterpret_cast<const Var&>(_ret[i]).isX87Var())
1147           {
1148             // TODO: X87 Support.
1149           }
1150           else if (reinterpret_cast<const Var&>(_ret[i]).isXmmVar())
1151           {
1152             X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId());
1153             ASMJIT_ASSERT(cv != NULL);
1154 
1155             srci = cv->regIndex;
1156             switch (cv->getType())
1157             {
1158               case kX86VarTypeXmm:
1159                 if (srci == kRegIndexInvalid)
1160                   x86Compiler->emit(kX86InstMovDQA, xmm(dsti), x86Context._getVarMem(cv));
1161                 else if (dsti != srci)
1162                   x86Compiler->emit(kX86InstMovDQA, xmm(dsti), xmm(srci));
1163                 break;
1164               case kX86VarTypeXmmSS:
1165               case kX86VarTypeXmmPS:
1166                 if (srci == kRegIndexInvalid)
1167                   x86Compiler->emit(kX86InstMovSS, xmm(dsti), x86Context._getVarMem(cv));
1168                 else
1169                   x86Compiler->emit(kX86InstMovSS, xmm(dsti), xmm(srci));
1170                 break;
1171               case kX86VarTypeXmmSD:
1172               case kX86VarTypeXmmPD:
1173                 if (srci == kRegIndexInvalid)
1174                   x86Compiler->emit(kX86InstCvtSD2SS, xmm(dsti), x86Context._getVarMem(cv));
1175                 else if (dsti != srci)
1176                   x86Compiler->emit(kX86InstCvtSD2SS, xmm(dsti), xmm(srci));
1177                 break;
1178             }
1179           }
1180         }
1181       }
1182       break;
1183 
1184     case kX86VarTypeXmmSD:
1185       for (i = 0; i < 2; i++)
1186       {
1187         uint32_t dsti = i;
1188         uint32_t srci;
1189 
1190         if (_ret[i].isVar())
1191         {
1192           if (reinterpret_cast<const Var&>(_ret[i]).isX87Var())
1193           {
1194             // TODO: X87 Support.
1195           }
1196           else if (reinterpret_cast<const Var&>(_ret[i]).isXmmVar())
1197           {
1198             X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId());
1199             ASMJIT_ASSERT(cv != NULL);
1200 
1201             srci = cv->regIndex;
1202             switch (cv->getType())
1203             {
1204               case kX86VarTypeXmm:
1205                 if (srci == kRegIndexInvalid)
1206                   x86Compiler->emit(kX86InstMovDQA, xmm(dsti), x86Context._getVarMem(cv));
1207                 else if (dsti != srci)
1208                   x86Compiler->emit(kX86InstMovDQA, xmm(dsti), xmm(srci));
1209                 break;
1210               case kX86VarTypeXmmSS:
1211               case kX86VarTypeXmmPS:
1212                 if (srci == kRegIndexInvalid)
1213                   x86Compiler->emit(kX86InstCvtSS2SD, xmm(dsti), x86Context._getVarMem(cv));
1214                 else
1215                   x86Compiler->emit(kX86InstCvtSS2SD, xmm(dsti), xmm(srci));
1216                 break;
1217               case kX86VarTypeXmmSD:
1218               case kX86VarTypeXmmPD:
1219                 if (srci == kRegIndexInvalid)
1220                   x86Compiler->emit(kX86InstMovSD, xmm(dsti), x86Context._getVarMem(cv));
1221                 else
1222                   x86Compiler->emit(kX86InstMovSD, xmm(dsti), xmm(srci));
1223                 break;
1224             }
1225           }
1226         }
1227       }
1228       break;
1229 
1230     case kInvalidValue:
1231     default:
1232       break;
1233   }
1234 
1235   if (mustEmitJump())
1236   {
1237     x86Context._isUnreachable = 1;
1238   }
1239 
1240   for (i = 0; i < 2; i++)
1241   {
1242     if (_ret[i].isVar())
1243     {
1244       X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId());
1245       x86Context._unuseVarOnEndOfScope(this, cv);
1246     }
1247   }
1248 
1249   return translated();
1250 }
1251 
emit(Assembler & a)1252 void X86CompilerFuncRet::emit(Assembler& a)
1253 {
1254   X86Assembler& x86Asm = static_cast<X86Assembler&>(a);
1255 
1256   if (mustEmitJump())
1257     x86Asm.jmp(getFunc()->getExitLabel());
1258 }
1259 
1260 // ============================================================================
1261 // [AsmJit::X86CompilerFuncRet - Misc]
1262 // ============================================================================
1263 
getMaxSize() const1264 int X86CompilerFuncRet::getMaxSize() const
1265 {
1266   return mustEmitJump() ? 15 : 0;
1267 }
1268 
1269 // ============================================================================
1270 // [AsmJit::X86CompilerFuncCall - Construction / Destruction]
1271 // ============================================================================
1272 
X86CompilerFuncCall(X86Compiler * x86Compiler,X86CompilerFuncDecl * caller,const Operand * target)1273 X86CompilerFuncCall::X86CompilerFuncCall(X86Compiler* x86Compiler, X86CompilerFuncDecl* caller, const Operand* target) :
1274   CompilerFuncCall(x86Compiler, caller, target),
1275   _gpParams(0),
1276   _mmParams(0),
1277   _xmmParams(0),
1278   _variablesCount(0),
1279   _variables(NULL)
1280 {
1281 }
1282 
~X86CompilerFuncCall()1283 X86CompilerFuncCall::~X86CompilerFuncCall()
1284 {
1285   memset(_argumentToVarRecord, 0, sizeof(VarCallRecord*) * kFuncArgsMax);
1286 }
1287 
1288 // ============================================================================
1289 // [AsmJit::X86CompilerFuncCall - Interface]
1290 // ============================================================================
1291 
prepare(CompilerContext & cc)1292 void X86CompilerFuncCall::prepare(CompilerContext& cc)
1293 {
1294   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
1295   X86Compiler* x86Compiler = getCompiler();
1296 
1297   // Prepare is similar to X86CompilerInst::prepare(). We collect unique variables
1298   // and update statistics, but we don't use standard alloc/free register calls.
1299   //
1300   // The calling function is also unique in variable allocator point of view,
1301   // because we need to alloc some variables that may be destroyed be the
1302   // callee (okay, may not, but this is not guaranteed).
1303   _offset = x86Context._currentOffset;
1304 
1305   // Tell EFunction that another function will be called inside. It needs this
1306   // information to reserve stack for the call and to mark esp adjustable.
1307   getCaller()->reserveStackForFunctionCall(static_cast<int32_t>(_x86Decl.getArgumentsStackSize()));
1308 
1309   uint32_t i;
1310   uint32_t argumentsCount = _x86Decl.getArgumentsCount();
1311   uint32_t operandsCount = argumentsCount;
1312   uint32_t variablesCount = 0;
1313 
1314   // Create registers used as arguments mask.
1315   for (i = 0; i < argumentsCount; i++)
1316   {
1317     const FuncArg& fArg = _x86Decl.getArguments()[i];
1318 
1319     if (fArg.hasRegIndex())
1320     {
1321       switch (fArg.getVarType())
1322       {
1323         case kX86VarTypeGpd:
1324         case kX86VarTypeGpq:
1325           _gpParams |= IntUtil::maskFromIndex(fArg.getRegIndex());
1326           break;
1327         case kX86VarTypeMm:
1328           _mmParams |= IntUtil::maskFromIndex(fArg.getRegIndex());
1329           break;
1330         case kX86VarTypeXmm:
1331         case kX86VarTypeXmmSS:
1332         case kX86VarTypeXmmPS:
1333         case kX86VarTypeXmmSD:
1334         case kX86VarTypeXmmPD:
1335           _xmmParams |= IntUtil::maskFromIndex(fArg.getRegIndex());
1336           break;
1337         default:
1338           ASMJIT_ASSERT(0);
1339       }
1340     }
1341     else
1342     {
1343       x86Context.getFunc()->setFuncFlag(kX86FuncFlagIsEspAdjusted);
1344     }
1345   }
1346 
1347   // Call address.
1348   operandsCount++;
1349 
1350   // The first and the second return value.
1351   if (!_ret[0].isNone())
1352     operandsCount++;
1353   if (!_ret[1].isNone())
1354     operandsCount++;
1355 
1356 #define __GET_VARIABLE(__vardata__) \
1357   { \
1358     X86CompilerVar* _candidate = __vardata__; \
1359     \
1360     for (var = cur; ;) \
1361     { \
1362       if (var == _variables) \
1363       { \
1364         var = cur++; \
1365         var->vdata = _candidate; \
1366         break; \
1367       } \
1368       \
1369       var--; \
1370       \
1371       if (var->vdata == _candidate) \
1372       { \
1373         break; \
1374       } \
1375     } \
1376     \
1377     ASMJIT_ASSERT(var != NULL); \
1378   }
1379 
1380   for (i = 0; i < operandsCount; i++)
1381   {
1382     Operand& o = (i < argumentsCount)
1383       ? (_args[i])
1384       : (i == argumentsCount ? _target : _ret[i - argumentsCount - 1]);
1385 
1386     if (o.isVar())
1387     {
1388       ASMJIT_ASSERT(o.getId() != kInvalidValue);
1389       X86CompilerVar* cv = x86Compiler->_getVar(o.getId());
1390       ASMJIT_ASSERT(cv != NULL);
1391 
1392       if (cv->workOffset == _offset) continue;
1393       if (!x86Context._isActive(cv)) x86Context._addActive(cv);
1394 
1395       cv->workOffset = _offset;
1396       variablesCount++;
1397     }
1398     else if (o.isMem())
1399     {
1400       if ((o.getId() & kOperandIdTypeMask) == kOperandIdTypeVar)
1401       {
1402         X86CompilerVar* cv = x86Compiler->_getVar(o.getId());
1403         ASMJIT_ASSERT(cv != NULL);
1404 
1405         x86Context._markMemoryUsed(cv);
1406         if (!x86Context._isActive(cv)) x86Context._addActive(cv);
1407 
1408         continue;
1409       }
1410       else if ((o._mem.base & kOperandIdTypeMask) == kOperandIdTypeVar)
1411       {
1412         X86CompilerVar* cv = x86Compiler->_getVar(o._mem.base);
1413         ASMJIT_ASSERT(cv != NULL);
1414 
1415         if (cv->workOffset == _offset) continue;
1416         if (!x86Context._isActive(cv)) x86Context._addActive(cv);
1417 
1418         cv->workOffset = _offset;
1419         variablesCount++;
1420       }
1421 
1422       if ((o._mem.index & kOperandIdTypeMask) == kOperandIdTypeVar)
1423       {
1424         X86CompilerVar* cv = x86Compiler->_getVar(o._mem.index);
1425         ASMJIT_ASSERT(cv != NULL);
1426 
1427         if (cv->workOffset == _offset) continue;
1428         if (!x86Context._isActive(cv)) x86Context._addActive(cv);
1429 
1430         cv->workOffset = _offset;
1431         variablesCount++;
1432       }
1433     }
1434   }
1435 
1436   // Traverse all active variables and set their funcCall pointer to this
1437   // call. This information can be used to choose between the preserved-first
1438   // and preserved-last register allocation.
1439   if (x86Context._active)
1440   {
1441     X86CompilerVar* first = static_cast<X86CompilerVar*>(x86Context._active);
1442     X86CompilerVar* active = first;
1443     do {
1444       if (active->funcCall == NULL)
1445         active->funcCall = this;
1446       active = active->nextActive;
1447     } while (active != first);
1448   }
1449 
1450   if (!variablesCount)
1451   {
1452     x86Context._currentOffset++;
1453     return;
1454   }
1455 
1456   _variables = reinterpret_cast<VarCallRecord*>(x86Compiler->getZoneMemory().alloc(sizeof(VarCallRecord) * variablesCount));
1457   if (!_variables)
1458   {
1459     x86Compiler->setError(kErrorNoHeapMemory);
1460     x86Context._currentOffset++;
1461     return;
1462   }
1463 
1464   _variablesCount = variablesCount;
1465   memset(_variables, 0, sizeof(VarCallRecord) * variablesCount);
1466 
1467   VarCallRecord* cur = _variables;
1468   VarCallRecord* var = NULL;
1469 
1470   for (i = 0; i < operandsCount; i++)
1471   {
1472     Operand& o = (i < argumentsCount)
1473       ? (_args[i])
1474       : (i == argumentsCount ? _target : _ret[i - argumentsCount - 1]);
1475 
1476     if (o.isVar())
1477     {
1478       X86CompilerVar* cv = x86Compiler->_getVar(o.getId());
1479       ASMJIT_ASSERT(cv != NULL);
1480 
1481       __GET_VARIABLE(cv)
1482       _argumentToVarRecord[i] = var;
1483 
1484       if (i < argumentsCount)
1485       {
1486         const FuncArg& fArg = _x86Decl.getArgument(i);
1487 
1488         if (fArg.hasRegIndex())
1489         {
1490           x86Context._newRegisterHomeIndex(cv, fArg.getRegIndex());
1491 
1492           switch (fArg.getVarType())
1493           {
1494             case kX86VarTypeGpd:
1495             case kX86VarTypeGpq:
1496               var->flags |= VarCallRecord::kFlagInGp;
1497               var->inCount++;
1498               break;
1499 
1500             case kX86VarTypeMm:
1501               var->flags |= VarCallRecord::kFlagInMm;
1502               var->inCount++;
1503               break;
1504 
1505             case kX86VarTypeXmm:
1506             case kX86VarTypeXmmSS:
1507             case kX86VarTypeXmmPS:
1508             case kX86VarTypeXmmSD:
1509             case kX86VarTypeXmmPD:
1510               var->flags |= VarCallRecord::kFlagInXmm;
1511               var->inCount++;
1512               break;
1513 
1514             default:
1515               ASMJIT_ASSERT(0);
1516           }
1517         }
1518         else
1519         {
1520           var->inCount++;
1521         }
1522 
1523         cv->regReadCount++;
1524       }
1525       else if (i == argumentsCount)
1526       {
1527         uint32_t mask = (~_x86Decl.getGpPreservedMask()) &
1528                         (~_x86Decl.getGpArgumentsMask()) &
1529                         (IntUtil::maskUpToIndex(kX86RegNumGp));
1530 
1531         x86Context._newRegisterHomeIndex(cv, IntUtil::findFirstBit(mask));
1532         x86Context._newRegisterHomeMask(cv, mask);
1533 
1534         var->flags |= VarCallRecord::kFlagCallReg;
1535         cv->regReadCount++;
1536       }
1537       else
1538       {
1539         switch (cv->getType())
1540         {
1541           case kX86VarTypeGpd:
1542           case kX86VarTypeGpq:
1543             if (i == argumentsCount+1)
1544               var->flags |= VarCallRecord::kFlagOutEax;
1545             else
1546               var->flags |= VarCallRecord::kFlagOutEdx;
1547             break;
1548 
1549           case kX86VarTypeX87:
1550           case kX86VarTypeX87SS:
1551           case kX86VarTypeX87SD:
1552 #if defined(ASMJIT_X86)
1553             if (i == argumentsCount+1)
1554               var->flags |= VarCallRecord::kFlagOutSt0;
1555             else
1556               var->flags |= VarCallRecord::kFlagOutSt1;
1557 #else
1558             if (i == argumentsCount+1)
1559               var->flags |= VarCallRecord::kFlagOutXmm0;
1560             else
1561               var->flags |= VarCallRecord::kFlagOutXmm1;
1562 #endif
1563             break;
1564 
1565           case kX86VarTypeMm:
1566             var->flags |= VarCallRecord::kFlagOutMm0;
1567             break;
1568 
1569           case kX86VarTypeXmm:
1570           case kX86VarTypeXmmPS:
1571           case kX86VarTypeXmmPD:
1572             if (i == argumentsCount+1)
1573               var->flags |= VarCallRecord::kFlagOutXmm0;
1574             else
1575               var->flags |= VarCallRecord::kFlagOutXmm1;
1576             break;
1577 
1578           case kX86VarTypeXmmSS:
1579           case kX86VarTypeXmmSD:
1580 #if defined(ASMJIT_X86)
1581             if (i == argumentsCount+1)
1582               var->flags |= VarCallRecord::kFlagOutSt0;
1583             else
1584               var->flags |= VarCallRecord::kFlagOutSt1;
1585 #else
1586             if (i == argumentsCount+1)
1587               var->flags |= VarCallRecord::kFlagOutXmm0;
1588             else
1589               var->flags |= VarCallRecord::kFlagOutXmm1;
1590 #endif
1591             break;
1592 
1593           default:
1594             ASMJIT_ASSERT(0);
1595         }
1596 
1597         cv->regWriteCount++;
1598       }
1599     }
1600     else if (o.isMem())
1601     {
1602       ASMJIT_ASSERT(i == argumentsCount);
1603 
1604       if ((o.getId() & kOperandIdTypeMask) == kOperandIdTypeVar)
1605       {
1606         X86CompilerVar* cv = x86Compiler->_getVar(o.getId());
1607         ASMJIT_ASSERT(cv != NULL);
1608 
1609         cv->memReadCount++;
1610       }
1611       else if ((o._mem.base & kOperandIdTypeMask) == kOperandIdTypeVar)
1612       {
1613         X86CompilerVar* cv = x86Compiler->_getVar(reinterpret_cast<Mem&>(o).getBase());
1614         ASMJIT_ASSERT(cv != NULL);
1615 
1616         cv->regReadCount++;
1617 
1618         __GET_VARIABLE(cv)
1619         var->flags |= VarCallRecord::kFlagCallReg | VarCallRecord::kFlagCallMem;
1620       }
1621 
1622       if ((o._mem.index & kOperandIdTypeMask) == kOperandIdTypeVar)
1623       {
1624         X86CompilerVar* cv = x86Compiler->_getVar(reinterpret_cast<Mem&>(o).getIndex());
1625         ASMJIT_ASSERT(cv != NULL);
1626 
1627         cv->regReadCount++;
1628 
1629         __GET_VARIABLE(cv)
1630         var->flags |= VarCallRecord::kFlagCallReg | VarCallRecord::kFlagCallMem;
1631       }
1632     }
1633   }
1634 
1635   // Traverse all variables and update firstItem / lastItem. This
1636   // function is called from iterator that scans items using forward
1637   // direction so we can use this knowledge to optimize the process.
1638   //
1639   // Same code is in X86CompilerInst::prepare().
1640   for (i = 0; i < _variablesCount; i++)
1641   {
1642     X86CompilerVar* v = _variables[i].vdata;
1643 
1644     // First item (begin of variable scope).
1645     if (v->firstItem == NULL) v->firstItem = this;
1646 
1647     // Last item (end of variable scope).
1648     v->lastItem = this;
1649   }
1650 
1651   x86Context._currentOffset++;
1652 
1653 #undef __GET_VARIABLE
1654 }
1655 
translate(CompilerContext & cc)1656 CompilerItem* X86CompilerFuncCall::translate(CompilerContext& cc)
1657 {
1658   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
1659   X86Compiler* x86Compiler = x86Context.getCompiler();
1660 
1661   uint32_t i;
1662   uint32_t preserved, mask;
1663 
1664   uint32_t temporaryGpReg;
1665   uint32_t temporaryXmmReg;
1666 
1667   uint32_t offset = x86Context._currentOffset;
1668 
1669   // Constants.
1670   const FuncArg* targs = _x86Decl.getArguments();
1671 
1672   uint32_t argumentsCount = _x86Decl.getArgumentsCount();
1673   uint32_t variablesCount = _variablesCount;
1674 
1675   // Processed arguments kFuncArgsMax.
1676   uint8_t processed[kFuncArgsMax] = { 0 };
1677 
1678   x86Compiler->comment("Call");
1679 
1680   // These variables are used by the instruction so we set current offset
1681   // to their work offsets -> The getSpillCandidate() method never returns
1682   // the variable used by this instruction.
1683   for (i = 0; i < variablesCount; i++)
1684   {
1685     _variables[i].vdata->workOffset = offset;
1686 
1687     // Init back-reference to VarCallRecord.
1688     _variables[i].vdata->tPtr = &_variables[i];
1689   }
1690 
1691   // --------------------------------------------------------------------------
1692   // STEP 1:
1693   //
1694   // Spill variables which are not used by the function call and have to
1695   // be destroyed. These registers may be used by callee.
1696   // --------------------------------------------------------------------------
1697 
1698   preserved = _x86Decl.getGpPreservedMask();
1699   for (i = 0, mask = 1; i < kX86RegNumGp; i++, mask <<= 1)
1700   {
1701     X86CompilerVar* cv = x86Context._x86State.gp[i];
1702     if (cv && cv->workOffset != offset && (preserved & mask) == 0)
1703       x86Context.spillGpVar(cv);
1704   }
1705 
1706   preserved = _x86Decl.getMmPreservedMask();
1707   for (i = 0, mask = 1; i < kX86RegNumMm; i++, mask <<= 1)
1708   {
1709     X86CompilerVar* cv = x86Context._x86State.mm[i];
1710     if (cv && cv->workOffset != offset && (preserved & mask) == 0)
1711       x86Context.spillMmVar(cv);
1712   }
1713 
1714   preserved = _x86Decl.getXmmPreservedMask();
1715   for (i = 0, mask = 1; i < kX86RegNumXmm; i++, mask <<= 1)
1716   {
1717     X86CompilerVar* cv = x86Context._x86State.xmm[i];
1718     if (cv && cv->workOffset != offset && (preserved & mask) == 0)
1719       x86Context.spillXmmVar(cv);
1720   }
1721 
1722   // --------------------------------------------------------------------------
1723   // STEP 2:
1724   //
1725   // Move all arguments to the stack which all already in registers.
1726   // --------------------------------------------------------------------------
1727 
1728   for (i = 0; i < argumentsCount; i++)
1729   {
1730     if (processed[i])
1731       continue;
1732 
1733     const FuncArg& argType = targs[i];
1734     if (argType.hasRegIndex())
1735       continue;
1736 
1737     Operand& operand = _args[i];
1738 
1739     if (operand.isVar())
1740     {
1741       VarCallRecord* rec = _argumentToVarRecord[i];
1742       X86CompilerVar* cv = x86Compiler->_getVar(operand.getId());
1743 
1744       if (cv->regIndex != kRegIndexInvalid)
1745       {
1746         _moveAllocatedVariableToStack(cc,
1747           cv, argType);
1748 
1749         rec->inDone++;
1750         processed[i] = true;
1751       }
1752     }
1753   }
1754 
1755   // --------------------------------------------------------------------------
1756   // STEP 3:
1757   //
1758   // Spill all non-preserved variables we moved to stack in STEP #2.
1759   // --------------------------------------------------------------------------
1760 
1761   for (i = 0; i < argumentsCount; i++)
1762   {
1763     VarCallRecord* rec = _argumentToVarRecord[i];
1764     if (!rec || processed[i])
1765       continue;
1766 
1767     if (rec->inDone >= rec->inCount)
1768     {
1769       X86CompilerVar* cv = rec->vdata;
1770       if (cv->regIndex == kRegIndexInvalid)
1771         continue;
1772 
1773       if (rec->outCount)
1774       {
1775         // Variable will be rewritten by function return value, it's not needed
1776         // to spill it. It will be allocated again by X86CompilerFuncCall.
1777         x86Context.unuseVar(rec->vdata, kVarStateUnused);
1778       }
1779       else
1780       {
1781         switch (cv->getType())
1782         {
1783           case kX86VarTypeGpd:
1784           case kX86VarTypeGpq:
1785             if ((_x86Decl.getGpPreservedMask() & IntUtil::maskFromIndex(cv->regIndex)) == 0)
1786               x86Context.spillGpVar(cv);
1787             break;
1788           case kX86VarTypeMm:
1789             if ((_x86Decl.getMmPreservedMask() & IntUtil::maskFromIndex(cv->regIndex)) == 0)
1790               x86Context.spillMmVar(cv);
1791             break;
1792           case kX86VarTypeXmm:
1793           case kX86VarTypeXmmSS:
1794           case kX86VarTypeXmmSD:
1795           case kX86VarTypeXmmPS:
1796           case kX86VarTypeXmmPD:
1797             if ((_x86Decl.getXmmPreservedMask() & IntUtil::maskFromIndex(cv->regIndex)) == 0)
1798               x86Context.spillXmmVar(cv);
1799             break;
1800         }
1801       }
1802     }
1803   }
1804 
1805   // --------------------------------------------------------------------------
1806   // STEP 4:
1807   //
1808   // Get temporary register that we can use to pass input function arguments.
1809   // Now it's safe to do, because the non-needed variables should be spilled.
1810   // --------------------------------------------------------------------------
1811 
1812   temporaryGpReg = _findTemporaryGpRegister(cc);
1813   temporaryXmmReg = _findTemporaryXmmRegister(cc);
1814 
1815   // If failed to get temporary register then we need just to pick one.
1816   if (temporaryGpReg == kRegIndexInvalid)
1817   {
1818     // TODO.
1819   }
1820   if (temporaryXmmReg == kRegIndexInvalid)
1821   {
1822     // TODO.
1823   }
1824 
1825   // --------------------------------------------------------------------------
1826   // STEP 5:
1827   //
1828   // Move all remaining arguments to the stack (we can use temporary register).
1829   // or allocate it to the primary register. Also move immediates.
1830   // --------------------------------------------------------------------------
1831 
1832   for (i = 0; i < argumentsCount; i++)
1833   {
1834     if (processed[i])
1835       continue;
1836 
1837     const FuncArg& argType = targs[i];
1838 
1839     if (argType.hasRegIndex())
1840       continue;
1841 
1842     Operand& operand = _args[i];
1843 
1844     if (operand.isVar())
1845     {
1846       VarCallRecord* rec = _argumentToVarRecord[i];
1847       X86CompilerVar* cv = x86Compiler->_getVar(operand.getId());
1848 
1849       _moveSpilledVariableToStack(cc,
1850         cv, argType,
1851         temporaryGpReg, temporaryXmmReg);
1852 
1853       rec->inDone++;
1854       processed[i] = true;
1855     }
1856     else if (operand.isImm())
1857     {
1858       // TODO.
1859     }
1860   }
1861 
1862   // --------------------------------------------------------------------------
1863   // STEP 6:
1864   //
1865   // Allocate arguments to registers.
1866   // --------------------------------------------------------------------------
1867 
1868   bool didWork;
1869 
1870   do {
1871     didWork = false;
1872 
1873     for (i = 0; i < argumentsCount; i++)
1874     {
1875       if (processed[i])
1876         continue;
1877 
1878       VarCallRecord* rsrc = _argumentToVarRecord[i];
1879 
1880       Operand& osrc = _args[i];
1881       ASMJIT_ASSERT(osrc.isVar());
1882       X86CompilerVar* vsrc = x86Compiler->_getVar(osrc.getId());
1883 
1884       const FuncArg& srcArgType = targs[i];
1885       X86CompilerVar* vdst = _getOverlappingVariable(cc, srcArgType);
1886 
1887       if (vsrc == vdst)
1888       {
1889         rsrc->inDone++;
1890         processed[i] = true;
1891 
1892         didWork = true;
1893         continue;
1894       }
1895       else if (vdst != NULL)
1896       {
1897         VarCallRecord* rdst = reinterpret_cast<VarCallRecord*>(vdst->tPtr);
1898 
1899         if (rdst == NULL)
1900         {
1901           x86Context.spillVar(vdst);
1902           vdst = NULL;
1903         }
1904         else if (rdst->inDone >= rdst->inCount && (rdst->flags & VarCallRecord::kFlagCallReg) == 0)
1905         {
1906           // Safe to spill.
1907           if (rdst->outCount || vdst->lastItem == this)
1908             x86Context.unuseVar(vdst, kVarStateUnused);
1909           else
1910             x86Context.spillVar(vdst);
1911           vdst = NULL;
1912         }
1913         else
1914         {
1915           uint32_t x = _x86Decl.findArgumentByRegCode(X86Util::getRegCodeFromVarType(vsrc->getType(), vsrc->regIndex));
1916           bool doSpill = true;
1917 
1918           if ((vdst->getClass() & kX86VarClassGp) != 0)
1919           {
1920             // Try to emit mov to register which is possible for call() operand.
1921             if (x == kInvalidValue && (rdst->flags & VarCallRecord::kFlagCallReg) != 0)
1922             {
1923               uint32_t rIndex;
1924               uint32_t rBit;
1925 
1926               // The mask which contains registers which are not-preserved
1927               // (these that might be clobbered by the callee) and which are
1928               // not used to pass function arguments. Each register contained
1929               // in this mask is ideal to be used by call() instruction.
1930               uint32_t possibleMask = (~_x86Decl.getGpPreservedMask()) &
1931                                       (~_x86Decl.getGpArgumentsMask()) &
1932                                       (IntUtil::maskUpToIndex(kX86RegNumGp));
1933 
1934               if (possibleMask != 0)
1935               {
1936                 for (rIndex = 0, rBit = 1; rIndex < kX86RegNumGp; rIndex++, rBit <<= 1)
1937                 {
1938                   if ((possibleMask & rBit) != 0)
1939                   {
1940                     if (x86Context._x86State.gp[rIndex] == NULL)
1941                     {
1942                       // This is the best possible solution, the register is
1943                       // free. We do not need to continue with this loop, the
1944                       // rIndex will be used by the call().
1945                       break;
1946                     }
1947                     else
1948                     {
1949                       // Wait until the register is freed or try to find another.
1950                       doSpill = false;
1951                       didWork = true;
1952                     }
1953                   }
1954                 }
1955               }
1956               else
1957               {
1958                 // Try to find a register which is free and which is not used
1959                 // to pass a function argument.
1960                 possibleMask = _x86Decl.getGpPreservedMask();
1961 
1962                 for (rIndex = 0, rBit = 1; rIndex < kX86RegNumGp; rIndex++, rBit <<= 1)
1963                 {
1964                   if ((possibleMask & rBit) != 0)
1965                   {
1966                     // Found one.
1967                     if (x86Context._x86State.gp[rIndex] == NULL) break;
1968                   }
1969                 }
1970               }
1971 
1972               if (rIndex < kX86RegNumGp)
1973               {
1974                 if (temporaryGpReg == vsrc->regIndex) temporaryGpReg = rIndex;
1975                 x86Compiler->emit(kX86InstMov, gpz(rIndex), gpz(vsrc->regIndex));
1976 
1977                 x86Context._x86State.gp[vsrc->regIndex] = NULL;
1978                 x86Context._x86State.gp[rIndex] = vsrc;
1979 
1980                 vsrc->regIndex = rIndex;
1981                 x86Context._allocatedGpRegister(rIndex);
1982 
1983                 doSpill = false;
1984                 didWork = true;
1985               }
1986             }
1987             // Emit xchg instead of spill/alloc if possible.
1988             else if (x != kInvalidValue)
1989             {
1990               const FuncArg& dstArgType = targs[x];
1991               if (X86Util::getVarClassFromVarType(dstArgType.getVarType()) == X86Util::getVarClassFromVarType(srcArgType.getVarType()))
1992               {
1993                 uint32_t dstIndex = vdst->regIndex;
1994                 uint32_t srcIndex = vsrc->regIndex;
1995 
1996                 if (srcIndex == dstArgType.getRegIndex())
1997                 {
1998 #if defined(ASMJIT_X64)
1999                   if (vdst->getType() != kX86VarTypeGpd || vsrc->getType() != kX86VarTypeGpd)
2000                     x86Compiler->emit(kX86InstXchg, gpq(dstIndex), gpq(srcIndex));
2001                   else
2002 #endif
2003                     x86Compiler->emit(kX86InstXchg, gpd(dstIndex), gpd(srcIndex));
2004 
2005                   x86Context._x86State.gp[srcIndex] = vdst;
2006                   x86Context._x86State.gp[dstIndex] = vsrc;
2007 
2008                   vdst->regIndex = srcIndex;
2009                   vsrc->regIndex = dstIndex;
2010 
2011                   rdst->inDone++;
2012                   rsrc->inDone++;
2013 
2014                   processed[i] = true;
2015                   processed[x] = true;
2016 
2017                   doSpill = false;
2018                 }
2019               }
2020             }
2021           }
2022 
2023           if (doSpill)
2024           {
2025             x86Context.spillVar(vdst);
2026             vdst = NULL;
2027           }
2028         }
2029       }
2030 
2031       if (vdst == NULL)
2032       {
2033         VarCallRecord* rec = reinterpret_cast<VarCallRecord*>(vsrc->tPtr);
2034 
2035         _moveSrcVariableToRegister(cc, vsrc, srcArgType);
2036 
2037         switch (srcArgType.getVarType())
2038         {
2039           case kX86VarTypeGpd:
2040           case kX86VarTypeGpq:
2041             x86Context._markGpRegisterModified(srcArgType.getRegIndex());
2042             break;
2043           case kX86VarTypeMm:
2044             x86Context._markMmRegisterModified(srcArgType.getRegIndex());
2045             break;
2046           case kX86VarTypeXmm:
2047           case kX86VarTypeXmmSS:
2048           case kX86VarTypeXmmSD:
2049           case kX86VarTypeXmmPS:
2050           case kX86VarTypeXmmPD:
2051             x86Context._markMmRegisterModified(srcArgType.getRegIndex());
2052             break;
2053         }
2054 
2055         rec->inDone++;
2056         processed[i] = true;
2057       }
2058     }
2059   } while (didWork);
2060 
2061   // --------------------------------------------------------------------------
2062   // STEP 7:
2063   //
2064   // Allocate operand used by CALL instruction.
2065   // --------------------------------------------------------------------------
2066 
2067   for (i = 0; i < variablesCount; i++)
2068   {
2069     VarCallRecord& r = _variables[i];
2070     if ((r.flags & VarCallRecord::kFlagCallReg) &&
2071         (r.vdata->regIndex == kRegIndexInvalid))
2072     {
2073       // If the register is not allocated and the call form is 'call reg' then
2074       // it's possible to keep it in memory.
2075       if ((r.flags & VarCallRecord::kFlagCallMem) == 0)
2076       {
2077         _target = r.vdata->asGpVar().m();
2078         break;
2079       }
2080 
2081       if (temporaryGpReg == kRegIndexInvalid)
2082         temporaryGpReg = _findTemporaryGpRegister(cc);
2083 
2084       x86Context.allocGpVar(r.vdata,
2085         IntUtil::maskFromIndex(temporaryGpReg),
2086         kVarAllocRegister | kVarAllocRead);
2087     }
2088   }
2089 
2090   x86Context.translateOperands(&_target, 1);
2091 
2092   // --------------------------------------------------------------------------
2093   // STEP 8:
2094   //
2095   // Spill all preserved variables.
2096   // --------------------------------------------------------------------------
2097 
2098   preserved = _x86Decl.getGpPreservedMask();
2099   for (i = 0, mask = 1; i < kX86RegNumGp; i++, mask <<= 1)
2100   {
2101     X86CompilerVar* vdata = x86Context._x86State.gp[i];
2102     if (vdata && (preserved & mask) == 0)
2103     {
2104       VarCallRecord* rec = reinterpret_cast<VarCallRecord*>(vdata->tPtr);
2105       if (rec && (rec->outCount || rec->flags & VarCallRecord::kFlagUnuseAfterUse || vdata->lastItem == this))
2106         x86Context.unuseVar(vdata, kVarStateUnused);
2107       else
2108         x86Context.spillGpVar(vdata);
2109     }
2110   }
2111 
2112   preserved = _x86Decl.getMmPreservedMask();
2113   for (i = 0, mask = 1; i < kX86RegNumMm; i++, mask <<= 1)
2114   {
2115     X86CompilerVar* vdata = x86Context._x86State.mm[i];
2116     if (vdata && (preserved & mask) == 0)
2117     {
2118       VarCallRecord* rec = reinterpret_cast<VarCallRecord*>(vdata->tPtr);
2119       if (rec && (rec->outCount || vdata->lastItem == this))
2120         x86Context.unuseVar(vdata, kVarStateUnused);
2121       else
2122         x86Context.spillMmVar(vdata);
2123     }
2124   }
2125 
2126   preserved = _x86Decl.getXmmPreservedMask();
2127   for (i = 0, mask = 1; i < kX86RegNumXmm; i++, mask <<= 1)
2128   {
2129     X86CompilerVar* vdata = x86Context._x86State.xmm[i];
2130     if (vdata && (preserved & mask) == 0)
2131     {
2132       VarCallRecord* rec = reinterpret_cast<VarCallRecord*>(vdata->tPtr);
2133       if (rec && (rec->outCount || vdata->lastItem == this))
2134         x86Context.unuseVar(vdata, kVarStateUnused);
2135       else
2136         x86Context.spillXmmVar(vdata);
2137     }
2138   }
2139 
2140   // --------------------------------------------------------------------------
2141   // STEP 9:
2142   //
2143   // Emit CALL instruction.
2144   // --------------------------------------------------------------------------
2145 
2146   x86Compiler->emit(kX86InstCall, _target);
2147 
2148   // Restore the stack offset.
2149   if (_x86Decl.getCalleePopsStack())
2150   {
2151     int32_t s = static_cast<int32_t>(_x86Decl.getArgumentsStackSize());
2152 
2153     if (s != 0)
2154       x86Compiler->emit(kX86InstSub, zsp, imm(s));
2155   }
2156 
2157   // --------------------------------------------------------------------------
2158   // STEP 10:
2159   //
2160   // Prepare others for return value(s) and cleanup.
2161   // --------------------------------------------------------------------------
2162 
2163   // Clear temp data, see AsmJit::X86CompilerVar::temp why it's needed.
2164   for (i = 0; i < variablesCount; i++)
2165   {
2166     VarCallRecord* rec = &_variables[i];
2167     X86CompilerVar* vdata = rec->vdata;
2168 
2169     if (rec->flags & (VarCallRecord::kFlagOutEax | VarCallRecord::kFlagOutEdx))
2170     {
2171       if (vdata->getClass() & kX86VarClassGp)
2172       {
2173         x86Context.allocGpVar(vdata,
2174           IntUtil::maskFromIndex((rec->flags & VarCallRecord::kFlagOutEax) != 0
2175             ? kX86RegIndexEax
2176             : kX86RegIndexEdx),
2177           kVarAllocRegister | kVarAllocWrite);
2178         vdata->changed = true;
2179       }
2180     }
2181 
2182     if (rec->flags & (VarCallRecord::kFlagOutMm0))
2183     {
2184       if (vdata->getClass() & kX86VarClassMm)
2185       {
2186         x86Context.allocMmVar(vdata, IntUtil::maskFromIndex(kX86RegIndexMm0),
2187           kVarAllocRegister | kVarAllocWrite);
2188         vdata->changed = true;
2189       }
2190     }
2191 
2192     if (rec->flags & (VarCallRecord::kFlagOutXmm0 | VarCallRecord::kFlagOutXmm1))
2193     {
2194       if (vdata->getClass() & kX86VarClassXmm)
2195       {
2196         x86Context.allocXmmVar(vdata,
2197           IntUtil::maskFromIndex((rec->flags & VarCallRecord::kFlagOutXmm0) != 0
2198             ? kX86RegIndexXmm0
2199             : kX86RegIndexXmm1),
2200           kVarAllocRegister | kVarAllocWrite);
2201         vdata->changed = true;
2202       }
2203     }
2204 
2205     if (rec->flags & (VarCallRecord::kFlagOutSt0 | VarCallRecord::kFlagOutSt1))
2206     {
2207       if (vdata->getClass() & kX86VarClassXmm)
2208       {
2209         Mem mem(x86Context._getVarMem(vdata));
2210         x86Context.unuseVar(vdata, kVarStateMem);
2211 
2212         switch (vdata->getType())
2213         {
2214           case kX86VarTypeXmmSS:
2215           case kX86VarTypeXmmPS:
2216           {
2217             mem.setSize(4);
2218             x86Compiler->emit(kX86InstFStP, mem);
2219             break;
2220           }
2221           case kX86VarTypeXmmSD:
2222           case kX86VarTypeXmmPD:
2223           {
2224             mem.setSize(8);
2225             x86Compiler->emit(kX86InstFStP, mem);
2226             break;
2227           }
2228           default:
2229           {
2230             x86Compiler->comment("*** WARNING: Can't convert float return value to untyped XMM\n");
2231             break;
2232           }
2233         }
2234       }
2235     }
2236 
2237     // Cleanup.
2238     vdata->tPtr = NULL;
2239   }
2240 
2241   for (i = 0; i < variablesCount; i++)
2242   {
2243     x86Context._unuseVarOnEndOfScope(this, &_variables[i]);
2244   }
2245 
2246   return translated();
2247 }
2248 
2249 // ============================================================================
2250 // [AsmJit::X86CompilerFuncCall - Misc]
2251 // ============================================================================
2252 
getMaxSize() const2253 int X86CompilerFuncCall::getMaxSize() const
2254 {
2255   // TODO: Instruction max size.
2256   return 15;
2257 }
2258 
_tryUnuseVar(CompilerVar * _v)2259 bool X86CompilerFuncCall::_tryUnuseVar(CompilerVar* _v)
2260 {
2261   X86CompilerVar* cv = static_cast<X86CompilerVar*>(_v);
2262 
2263   for (uint32_t i = 0; i < _variablesCount; i++)
2264   {
2265     if (_variables[i].vdata == cv)
2266     {
2267       _variables[i].flags |= VarCallRecord::kFlagUnuseAfterUse;
2268       return true;
2269     }
2270   }
2271 
2272   return false;
2273 }
2274 
2275 // ============================================================================
2276 // [AsmJit::X86CompilerFuncCall - Helpers]
2277 // ============================================================================
2278 
_findTemporaryGpRegister(CompilerContext & cc)2279 uint32_t X86CompilerFuncCall::_findTemporaryGpRegister(CompilerContext& cc)
2280 {
2281   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
2282 
2283   uint32_t i;
2284   uint32_t mask;
2285 
2286   uint32_t passedGP = _x86Decl.getGpArgumentsMask();
2287   uint32_t candidate = kRegIndexInvalid;
2288 
2289   // Find all registers used to pass function arguments. We shouldn't use these
2290   // if possible.
2291   for (i = 0, mask = 1; i < kX86RegNumGp; i++, mask <<= 1)
2292   {
2293     if (x86Context._x86State.gp[i] == NULL)
2294     {
2295       // If this register is used to pass arguments to function, we will mark
2296       // it and use it only if there is no other one.
2297       if ((passedGP & mask) != 0)
2298         candidate = i;
2299       else
2300         return i;
2301     }
2302   }
2303 
2304   return candidate;
2305 }
2306 
_findTemporaryXmmRegister(CompilerContext & cc)2307 uint32_t X86CompilerFuncCall::_findTemporaryXmmRegister(CompilerContext& cc)
2308 {
2309   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
2310 
2311   uint32_t i;
2312   uint32_t mask;
2313 
2314   uint32_t passedXMM = _x86Decl.getXmmArgumentsMask();
2315   uint32_t candidate = kRegIndexInvalid;
2316 
2317   // Find all registers used to pass function arguments. We shouldn't use these
2318   // if possible.
2319   for (i = 0, mask = 1; i < kX86RegNumXmm; i++, mask <<= 1)
2320   {
2321     if (x86Context._x86State.xmm[i] == NULL)
2322     {
2323       // If this register is used to pass arguments to function, we will mark
2324       // it and use it only if there is no other one.
2325       if ((passedXMM & mask) != 0)
2326         candidate = i;
2327       else
2328         return i;
2329     }
2330   }
2331 
2332   return candidate;
2333 }
2334 
_getOverlappingVariable(CompilerContext & cc,const FuncArg & argType) const2335 X86CompilerVar* X86CompilerFuncCall::_getOverlappingVariable(CompilerContext& cc, const FuncArg& argType) const
2336 {
2337   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
2338   ASMJIT_ASSERT(argType.getVarType() != kVarTypeInvalid);
2339 
2340   switch (argType.getVarType())
2341   {
2342     case kX86VarTypeGpd:
2343     case kX86VarTypeGpq:
2344       return x86Context._x86State.gp[argType.getRegIndex()];
2345     case kX86VarTypeMm:
2346       return x86Context._x86State.mm[argType.getRegIndex()];
2347     case kX86VarTypeXmm:
2348     case kX86VarTypeXmmSS:
2349     case kX86VarTypeXmmSD:
2350     case kX86VarTypeXmmPS:
2351     case kX86VarTypeXmmPD:
2352       return x86Context._x86State.xmm[argType.getRegIndex()];
2353   }
2354 
2355   return NULL;
2356 }
2357 
_moveAllocatedVariableToStack(CompilerContext & cc,X86CompilerVar * vdata,const FuncArg & argType)2358 void X86CompilerFuncCall::_moveAllocatedVariableToStack(CompilerContext& cc, X86CompilerVar* vdata, const FuncArg& argType)
2359 {
2360   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
2361   X86Compiler* x86Compiler = x86Context.getCompiler();
2362 
2363   ASMJIT_ASSERT(!argType.hasRegIndex());
2364   ASMJIT_ASSERT(vdata->regIndex != kRegIndexInvalid);
2365 
2366   uint32_t src = vdata->regIndex;
2367   Mem dst = ptr(zsp, -(int)sizeof(uintptr_t) + argType.getStackOffset());
2368 
2369   switch (vdata->getType())
2370   {
2371     case kX86VarTypeGpd:
2372       switch (argType.getVarType())
2373       {
2374         case kX86VarTypeGpd:
2375           x86Compiler->emit(kX86InstMov, dst, gpd(src));
2376           return;
2377 #if defined(ASMJIT_X64)
2378         case kX86VarTypeGpq:
2379         case kX86VarTypeMm:
2380           x86Compiler->emit(kX86InstMov, dst, gpq(src));
2381           return;
2382 #endif // ASMJIT_X64
2383       }
2384       break;
2385 
2386 #if defined(ASMJIT_X64)
2387     case kX86VarTypeGpq:
2388       switch (argType.getVarType())
2389       {
2390         case kX86VarTypeGpd:
2391           x86Compiler->emit(kX86InstMov, dst, gpd(src));
2392           return;
2393         case kX86VarTypeGpq:
2394           x86Compiler->emit(kX86InstMov, dst, gpq(src));
2395           return;
2396         case kX86VarTypeMm:
2397           x86Compiler->emit(kX86InstMovQ, dst, gpq(src));
2398           return;
2399       }
2400       break;
2401 #endif // ASMJIT_X64
2402 
2403     case kX86VarTypeMm:
2404       switch (argType.getVarType())
2405       {
2406         case kX86VarTypeGpd:
2407         case kX86VarTypeX87SS:
2408         case kX86VarTypeXmmSS:
2409           x86Compiler->emit(kX86InstMovD, dst, mm(src));
2410           return;
2411         case kX86VarTypeGpq:
2412         case kX86VarTypeMm:
2413         case kX86VarTypeX87SD:
2414         case kX86VarTypeXmmSD:
2415           x86Compiler->emit(kX86InstMovQ, dst, mm(src));
2416           return;
2417       }
2418       break;
2419 
2420     // We allow incompatible types here, because the called can convert them
2421     // to correct format before function is called.
2422 
2423     case kX86VarTypeXmm:
2424     case kX86VarTypeXmmPS:
2425     case kX86VarTypeXmmPD:
2426       switch (argType.getVarType())
2427       {
2428         case kX86VarTypeXmm:
2429           x86Compiler->emit(kX86InstMovDQU, dst, xmm(src));
2430           return;
2431         case kX86VarTypeXmmSS:
2432         case kX86VarTypeXmmPS:
2433           x86Compiler->emit(kX86InstMovUPS, dst, xmm(src));
2434           return;
2435         case kX86VarTypeXmmSD:
2436         case kX86VarTypeXmmPD:
2437           x86Compiler->emit(kX86InstMovUPD, dst, xmm(src));
2438           return;
2439       }
2440       break;
2441 
2442     case kX86VarTypeXmmSS:
2443       switch (argType.getVarType())
2444       {
2445         case kX86VarTypeX87SS:
2446         case kX86VarTypeXmm:
2447         case kX86VarTypeXmmSS:
2448         case kX86VarTypeXmmPS:
2449         case kX86VarTypeXmmSD:
2450         case kX86VarTypeXmmPD:
2451           x86Compiler->emit(kX86InstMovSS, dst, xmm(src));
2452           return;
2453       }
2454       break;
2455 
2456     case kX86VarTypeXmmSD:
2457       switch (argType.getVarType())
2458       {
2459         case kX86VarTypeX87SD:
2460         case kX86VarTypeXmm:
2461         case kX86VarTypeXmmSS:
2462         case kX86VarTypeXmmPS:
2463         case kX86VarTypeXmmSD:
2464         case kX86VarTypeXmmPD:
2465           x86Compiler->emit(kX86InstMovSD, dst, xmm(src));
2466           return;
2467       }
2468       break;
2469   }
2470 
2471   x86Compiler->setError(kErrorIncompatibleArgumentType);
2472 }
2473 
_moveSpilledVariableToStack(CompilerContext & cc,X86CompilerVar * cv,const FuncArg & argType,uint32_t temporaryGpReg,uint32_t temporaryXmmReg)2474 void X86CompilerFuncCall::_moveSpilledVariableToStack(CompilerContext& cc,
2475   X86CompilerVar* cv, const FuncArg& argType,
2476   uint32_t temporaryGpReg,
2477   uint32_t temporaryXmmReg)
2478 {
2479   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
2480   X86Compiler* x86Compiler = x86Context.getCompiler();
2481 
2482   ASMJIT_ASSERT(!argType.hasRegIndex());
2483   ASMJIT_ASSERT(cv->regIndex == kRegIndexInvalid);
2484 
2485   Mem src = x86Context._getVarMem(cv);
2486   Mem dst = ptr(zsp, -(int)sizeof(sysint_t) + argType.getStackOffset());
2487 
2488   switch (cv->getType())
2489   {
2490     case kX86VarTypeGpd:
2491       switch (argType.getVarType())
2492       {
2493         case kX86VarTypeGpd:
2494           x86Compiler->emit(kX86InstMov, gpd(temporaryGpReg), src);
2495           x86Compiler->emit(kX86InstMov, dst, gpd(temporaryGpReg));
2496           return;
2497 #if defined(ASMJIT_X64)
2498         case kX86VarTypeGpq:
2499         case kX86VarTypeMm:
2500           x86Compiler->emit(kX86InstMov, gpd(temporaryGpReg), src);
2501           x86Compiler->emit(kX86InstMov, dst, gpq(temporaryGpReg));
2502           return;
2503 #endif // ASMJIT_X64
2504       }
2505       break;
2506 
2507 #if defined(ASMJIT_X64)
2508     case kX86VarTypeGpq:
2509       switch (argType.getVarType())
2510       {
2511         case kX86VarTypeGpd:
2512           x86Compiler->emit(kX86InstMov, gpd(temporaryGpReg), src);
2513           x86Compiler->emit(kX86InstMov, dst, gpd(temporaryGpReg));
2514           return;
2515         case kX86VarTypeGpq:
2516         case kX86VarTypeMm:
2517           x86Compiler->emit(kX86InstMov, gpq(temporaryGpReg), src);
2518           x86Compiler->emit(kX86InstMov, dst, gpq(temporaryGpReg));
2519           return;
2520       }
2521       break;
2522 #endif // ASMJIT_X64
2523 
2524     case kX86VarTypeMm:
2525       switch (argType.getVarType())
2526       {
2527         case kX86VarTypeGpd:
2528         case kX86VarTypeX87SS:
2529         case kX86VarTypeXmmSS:
2530           x86Compiler->emit(kX86InstMov, gpd(temporaryGpReg), src);
2531           x86Compiler->emit(kX86InstMov, dst, gpd(temporaryGpReg));
2532           return;
2533         case kX86VarTypeGpq:
2534         case kX86VarTypeMm:
2535         case kX86VarTypeX87SD:
2536         case kX86VarTypeXmmSD:
2537           // TODO
2538           return;
2539       }
2540       break;
2541 
2542     // We allow incompatible types here, because the caller can convert them
2543     // to correct format before function is called.
2544 
2545     case kX86VarTypeXmm:
2546     case kX86VarTypeXmmPS:
2547     case kX86VarTypeXmmPD:
2548       switch (argType.getVarType())
2549       {
2550         case kX86VarTypeXmm:
2551           x86Compiler->emit(kX86InstMovDQU, xmm(temporaryXmmReg), src);
2552           x86Compiler->emit(kX86InstMovDQU, dst, xmm(temporaryXmmReg));
2553           return;
2554         case kX86VarTypeXmmSS:
2555         case kX86VarTypeXmmPS:
2556           x86Compiler->emit(kX86InstMovUPS, xmm(temporaryXmmReg), src);
2557           x86Compiler->emit(kX86InstMovUPS, dst, xmm(temporaryXmmReg));
2558           return;
2559         case kX86VarTypeXmmSD:
2560         case kX86VarTypeXmmPD:
2561           x86Compiler->emit(kX86InstMovUPD, xmm(temporaryXmmReg), src);
2562           x86Compiler->emit(kX86InstMovUPD, dst, xmm(temporaryXmmReg));
2563           return;
2564       }
2565       break;
2566 
2567     case kX86VarTypeXmmSS:
2568       switch (argType.getVarType())
2569       {
2570         case kX86VarTypeX87SS:
2571         case kX86VarTypeXmm:
2572         case kX86VarTypeXmmSS:
2573         case kX86VarTypeXmmPS:
2574         case kX86VarTypeXmmSD:
2575         case kX86VarTypeXmmPD:
2576           x86Compiler->emit(kX86InstMovSS, xmm(temporaryXmmReg), src);
2577           x86Compiler->emit(kX86InstMovSS, dst, xmm(temporaryXmmReg));
2578           return;
2579       }
2580       break;
2581 
2582     case kX86VarTypeXmmSD:
2583       switch (argType.getVarType())
2584       {
2585         case kX86VarTypeX87SD:
2586         case kX86VarTypeXmm:
2587         case kX86VarTypeXmmSS:
2588         case kX86VarTypeXmmPS:
2589         case kX86VarTypeXmmSD:
2590         case kX86VarTypeXmmPD:
2591           x86Compiler->emit(kX86InstMovSD, xmm(temporaryXmmReg), src);
2592           x86Compiler->emit(kX86InstMovSD, dst, xmm(temporaryXmmReg));
2593           return;
2594       }
2595       break;
2596   }
2597 
2598   x86Compiler->setError(kErrorIncompatibleArgumentType);
2599 }
2600 
_moveSrcVariableToRegister(CompilerContext & cc,X86CompilerVar * cv,const FuncArg & argType)2601 void X86CompilerFuncCall::_moveSrcVariableToRegister(CompilerContext& cc,
2602   X86CompilerVar* cv, const FuncArg& argType)
2603 {
2604   X86CompilerContext& x86Context = static_cast<X86CompilerContext&>(cc);
2605   X86Compiler* x86Compiler = x86Context.getCompiler();
2606 
2607   uint32_t dst = argType.getRegIndex();
2608   uint32_t src = cv->regIndex;
2609 
2610   if (src != kRegIndexInvalid)
2611   {
2612     switch (argType.getVarType())
2613     {
2614       case kX86VarTypeGpd:
2615         switch (cv->getType())
2616         {
2617           case kX86VarTypeGpd:
2618 #if defined(ASMJIT_X64)
2619           case kX86VarTypeGpq:
2620 #endif // ASMJIT_X64
2621             x86Compiler->emit(kX86InstMov, gpd(dst), gpd(src));
2622             return;
2623           case kX86VarTypeMm:
2624             x86Compiler->emit(kX86InstMovD, gpd(dst), mm(src));
2625             return;
2626         }
2627         break;
2628 
2629 #if defined(ASMJIT_X64)
2630       case kX86VarTypeGpq:
2631         switch (cv->getType())
2632         {
2633           case kX86VarTypeGpd:
2634             x86Compiler->emit(kX86InstMov, gpd(dst), gpd(src));
2635             return;
2636           case kX86VarTypeGpq:
2637             x86Compiler->emit(kX86InstMov, gpq(dst), gpq(src));
2638             return;
2639           case kX86VarTypeMm:
2640             x86Compiler->emit(kX86InstMovQ, gpq(dst), mm(src));
2641             return;
2642         }
2643         break;
2644 #endif // ASMJIT_X64
2645 
2646       case kX86VarTypeMm:
2647         switch (cv->getType())
2648         {
2649           case kX86VarTypeGpd:
2650             x86Compiler->emit(kX86InstMovD, gpd(dst), gpd(src));
2651             return;
2652 #if defined(ASMJIT_X64)
2653           case kX86VarTypeGpq:
2654             x86Compiler->emit(kX86InstMovQ, gpq(dst), gpq(src));
2655             return;
2656 #endif // ASMJIT_X64
2657           case kX86VarTypeMm:
2658             x86Compiler->emit(kX86InstMovQ, mm(dst), mm(src));
2659             return;
2660         }
2661         break;
2662 
2663       case kX86VarTypeXmm:
2664       case kX86VarTypeXmmPS:
2665       case kX86VarTypeXmmPD:
2666         switch (cv->getType())
2667         {
2668           case kX86VarTypeGpd:
2669             x86Compiler->emit(kX86InstMovD, xmm(dst), gpd(src));
2670             return;
2671 #if defined(ASMJIT_X64)
2672           case kX86VarTypeGpq:
2673             x86Compiler->emit(kX86InstMovQ, xmm(dst), gpq(src));
2674             return;
2675 #endif // ASMJIT_X64
2676           case kX86VarTypeMm:
2677             x86Compiler->emit(kX86InstMovQ, xmm(dst), mm(src));
2678             return;
2679           case kX86VarTypeXmm:
2680           case kX86VarTypeXmmSS:
2681           case kX86VarTypeXmmPS:
2682           case kX86VarTypeXmmSD:
2683           case kX86VarTypeXmmPD:
2684             x86Compiler->emit(kX86InstMovDQA, xmm(dst), xmm(src));
2685             return;
2686         }
2687         break;
2688 
2689       case kX86VarTypeXmmSS:
2690         switch (cv->getType())
2691         {
2692           case kX86VarTypeMm:
2693             x86Compiler->emit(kX86InstMovQ, xmm(dst), mm(src));
2694             return;
2695 
2696           case kX86VarTypeXmm:
2697             x86Compiler->emit(kX86InstMovDQA, xmm(dst), xmm(src));
2698             return;
2699           case kX86VarTypeXmmSS:
2700           case kX86VarTypeXmmPS:
2701             x86Compiler->emit(kX86InstMovSS, xmm(dst), xmm(src));
2702             return;
2703           case kX86VarTypeXmmSD:
2704           case kX86VarTypeXmmPD:
2705             x86Compiler->emit(kX86InstCvtSD2SS, xmm(dst), xmm(src));
2706             return;
2707         }
2708         break;
2709 
2710       case kX86VarTypeXmmSD:
2711         switch (cv->getType())
2712         {
2713           case kX86VarTypeMm:
2714             x86Compiler->emit(kX86InstMovQ, xmm(dst), mm(src));
2715             return;
2716 
2717           case kX86VarTypeXmm:
2718             x86Compiler->emit(kX86InstMovDQA, xmm(dst), xmm(src));
2719             return;
2720           case kX86VarTypeXmmSS:
2721           case kX86VarTypeXmmPS:
2722             x86Compiler->emit(kX86InstCvtSS2SD, xmm(dst), xmm(src));
2723             return;
2724           case kX86VarTypeXmmSD:
2725           case kX86VarTypeXmmPD:
2726             x86Compiler->emit(kX86InstMovSD, xmm(dst), xmm(src));
2727             return;
2728         }
2729         break;
2730     }
2731   }
2732   else
2733   {
2734     Mem mem = x86Context._getVarMem(cv);
2735 
2736     switch (argType.getVarType())
2737     {
2738       case kX86VarTypeGpd:
2739         switch (cv->getType())
2740         {
2741           case kX86VarTypeGpd:
2742 #if defined(ASMJIT_X64)
2743           case kX86VarTypeGpq:
2744 #endif // ASMJIT_X64
2745             x86Compiler->emit(kX86InstMov, gpd(dst), mem);
2746             return;
2747           case kX86VarTypeMm:
2748             x86Compiler->emit(kX86InstMovD, gpd(dst), mem);
2749             return;
2750         }
2751         break;
2752 
2753 #if defined(ASMJIT_X64)
2754       case kX86VarTypeGpq:
2755         switch (cv->getType())
2756         {
2757           case kX86VarTypeGpd:
2758             x86Compiler->emit(kX86InstMov, gpd(dst), mem);
2759             return;
2760           case kX86VarTypeGpq:
2761             x86Compiler->emit(kX86InstMov, gpq(dst), mem);
2762             return;
2763           case kX86VarTypeMm:
2764             x86Compiler->emit(kX86InstMovQ, gpq(dst), mem);
2765             return;
2766         }
2767         break;
2768 #endif // ASMJIT_X64
2769 
2770       case kX86VarTypeMm:
2771         switch (cv->getType())
2772         {
2773           case kX86VarTypeGpd:
2774             x86Compiler->emit(kX86InstMovD, gpd(dst), mem);
2775             return;
2776 #if defined(ASMJIT_X64)
2777           case kX86VarTypeGpq:
2778             x86Compiler->emit(kX86InstMovQ, gpq(dst), mem);
2779             return;
2780 #endif // ASMJIT_X64
2781           case kX86VarTypeMm:
2782             x86Compiler->emit(kX86InstMovQ, mm(dst), mem);
2783             return;
2784         }
2785         break;
2786 
2787       case kX86VarTypeXmm:
2788       case kX86VarTypeXmmPS:
2789       case kX86VarTypeXmmPD:
2790         switch (cv->getType())
2791         {
2792           case kX86VarTypeGpd:
2793             x86Compiler->emit(kX86InstMovD, xmm(dst), mem);
2794             return;
2795 #if defined(ASMJIT_X64)
2796           case kX86VarTypeGpq:
2797             x86Compiler->emit(kX86InstMovQ, xmm(dst), mem);
2798             return;
2799 #endif // ASMJIT_X64
2800           case kX86VarTypeMm:
2801             x86Compiler->emit(kX86InstMovQ, xmm(dst), mem);
2802             return;
2803           case kX86VarTypeXmm:
2804           case kX86VarTypeXmmSS:
2805           case kX86VarTypeXmmPS:
2806           case kX86VarTypeXmmSD:
2807           case kX86VarTypeXmmPD:
2808             x86Compiler->emit(kX86InstMovDQA, xmm(dst), mem);
2809             return;
2810         }
2811         break;
2812 
2813       case kX86VarTypeXmmSS:
2814         switch (cv->getType())
2815         {
2816           case kX86VarTypeMm:
2817             x86Compiler->emit(kX86InstMovQ, xmm(dst), mem);
2818             return;
2819 
2820           case kX86VarTypeXmm:
2821             x86Compiler->emit(kX86InstMovDQA, xmm(dst), mem);
2822             return;
2823           case kX86VarTypeXmmSS:
2824           case kX86VarTypeXmmPS:
2825             x86Compiler->emit(kX86InstMovSS, xmm(dst), mem);
2826             return;
2827           case kX86VarTypeXmmSD:
2828           case kX86VarTypeXmmPD:
2829             x86Compiler->emit(kX86InstCvtSD2SS, xmm(dst), mem);
2830             return;
2831         }
2832         break;
2833 
2834       case kX86VarTypeXmmSD:
2835         switch (cv->getType())
2836         {
2837           case kX86VarTypeMm:
2838             x86Compiler->emit(kX86InstMovQ, xmm(dst), mem);
2839             return;
2840 
2841           case kX86VarTypeXmm:
2842             x86Compiler->emit(kX86InstMovDQA, xmm(dst), mem);
2843             return;
2844           case kX86VarTypeXmmSS:
2845           case kX86VarTypeXmmPS:
2846             x86Compiler->emit(kX86InstCvtSS2SD, xmm(dst), mem);
2847             return;
2848           case kX86VarTypeXmmSD:
2849           case kX86VarTypeXmmPD:
2850             x86Compiler->emit(kX86InstMovSD, xmm(dst), mem);
2851             return;
2852         }
2853         break;
2854     }
2855   }
2856 
2857   x86Compiler->setError(kErrorIncompatibleArgumentType);
2858 }
2859 
2860 // Prototype & Arguments Management.
setPrototype(uint32_t callingConvention,uint32_t returnType,const uint32_t * arguments,uint32_t argumentsCount)2861 void X86CompilerFuncCall::setPrototype(uint32_t callingConvention, uint32_t returnType, const uint32_t* arguments, uint32_t argumentsCount)
2862 {
2863   _x86Decl.setPrototype(callingConvention, returnType, arguments, argumentsCount);
2864   _args = reinterpret_cast<Operand*>(
2865     getCompiler()->getZoneMemory().alloc(sizeof(Operand) * argumentsCount));
2866   memset(_args, 0, sizeof(Operand) * argumentsCount);
2867 }
2868 
setArgument(uint32_t i,const Var & var)2869 bool X86CompilerFuncCall::setArgument(uint32_t i, const Var& var)
2870 {
2871   ASMJIT_ASSERT(i < _x86Decl.getArgumentsCount());
2872 
2873   if (i >= _x86Decl.getArgumentsCount())
2874     return false;
2875 
2876   _args[i] = var;
2877   return true;
2878 }
2879 
setArgument(uint32_t i,const Imm & imm)2880 bool X86CompilerFuncCall::setArgument(uint32_t i, const Imm& imm)
2881 {
2882   ASMJIT_ASSERT(i < _x86Decl.getArgumentsCount());
2883 
2884   if (i >= _x86Decl.getArgumentsCount())
2885     return false;
2886 
2887   _args[i] = imm;
2888   return true;
2889 }
2890 
setReturn(const Operand & first,const Operand & second)2891 bool X86CompilerFuncCall::setReturn(const Operand& first, const Operand& second)
2892 {
2893   _ret[0] = first;
2894   _ret[1] = second;
2895 
2896   return true;
2897 }
2898 
2899 } // AsmJit namespace
2900 
2901 // [Api-End]
2902 #include "../core/apiend.h"
2903