1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "assembler_x86_64.h"
18 
19 #include "base/casts.h"
20 #include "entrypoints/quick/quick_entrypoints.h"
21 #include "memory_region.h"
22 #include "thread.h"
23 
24 namespace art {
25 namespace x86_64 {
26 
operator <<(std::ostream & os,const CpuRegister & reg)27 std::ostream& operator<<(std::ostream& os, const CpuRegister& reg) {
28   return os << reg.AsRegister();
29 }
30 
operator <<(std::ostream & os,const XmmRegister & reg)31 std::ostream& operator<<(std::ostream& os, const XmmRegister& reg) {
32   return os << reg.AsFloatRegister();
33 }
34 
operator <<(std::ostream & os,const X87Register & reg)35 std::ostream& operator<<(std::ostream& os, const X87Register& reg) {
36   return os << "ST" << static_cast<int>(reg);
37 }
38 
call(CpuRegister reg)39 void X86_64Assembler::call(CpuRegister reg) {
40   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
41   EmitOptionalRex32(reg);
42   EmitUint8(0xFF);
43   EmitRegisterOperand(2, reg.LowBits());
44 }
45 
46 
call(const Address & address)47 void X86_64Assembler::call(const Address& address) {
48   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
49   EmitOptionalRex32(address);
50   EmitUint8(0xFF);
51   EmitOperand(2, address);
52 }
53 
54 
call(Label * label)55 void X86_64Assembler::call(Label* label) {
56   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
57   EmitUint8(0xE8);
58   static const int kSize = 5;
59   EmitLabel(label, kSize);
60 }
61 
pushq(CpuRegister reg)62 void X86_64Assembler::pushq(CpuRegister reg) {
63   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
64   EmitOptionalRex32(reg);
65   EmitUint8(0x50 + reg.LowBits());
66 }
67 
68 
pushq(const Address & address)69 void X86_64Assembler::pushq(const Address& address) {
70   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
71   EmitOptionalRex32(address);
72   EmitUint8(0xFF);
73   EmitOperand(6, address);
74 }
75 
76 
pushq(const Immediate & imm)77 void X86_64Assembler::pushq(const Immediate& imm) {
78   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
79   CHECK(imm.is_int32());  // pushq only supports 32b immediate.
80   if (imm.is_int8()) {
81     EmitUint8(0x6A);
82     EmitUint8(imm.value() & 0xFF);
83   } else {
84     EmitUint8(0x68);
85     EmitImmediate(imm);
86   }
87 }
88 
89 
popq(CpuRegister reg)90 void X86_64Assembler::popq(CpuRegister reg) {
91   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
92   EmitOptionalRex32(reg);
93   EmitUint8(0x58 + reg.LowBits());
94 }
95 
96 
popq(const Address & address)97 void X86_64Assembler::popq(const Address& address) {
98   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
99   EmitOptionalRex32(address);
100   EmitUint8(0x8F);
101   EmitOperand(0, address);
102 }
103 
104 
movq(CpuRegister dst,const Immediate & imm)105 void X86_64Assembler::movq(CpuRegister dst, const Immediate& imm) {
106   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
107   if (imm.is_int32()) {
108     // 32 bit. Note: sign-extends.
109     EmitRex64(dst);
110     EmitUint8(0xC7);
111     EmitRegisterOperand(0, dst.LowBits());
112     EmitInt32(static_cast<int32_t>(imm.value()));
113   } else {
114     EmitRex64(dst);
115     EmitUint8(0xB8 + dst.LowBits());
116     EmitInt64(imm.value());
117   }
118 }
119 
120 
movl(CpuRegister dst,const Immediate & imm)121 void X86_64Assembler::movl(CpuRegister dst, const Immediate& imm) {
122   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
123   EmitOptionalRex32(dst);
124   EmitUint8(0xB8 + dst.LowBits());
125   EmitImmediate(imm);
126 }
127 
128 
movq(CpuRegister dst,CpuRegister src)129 void X86_64Assembler::movq(CpuRegister dst, CpuRegister src) {
130   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
131   // 0x89 is movq r/m64 <- r64, with op1 in r/m and op2 in reg: so reverse EmitRex64
132   EmitRex64(src, dst);
133   EmitUint8(0x89);
134   EmitRegisterOperand(src.LowBits(), dst.LowBits());
135 }
136 
137 
movl(CpuRegister dst,CpuRegister src)138 void X86_64Assembler::movl(CpuRegister dst, CpuRegister src) {
139   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
140   EmitOptionalRex32(dst, src);
141   EmitUint8(0x8B);
142   EmitRegisterOperand(dst.LowBits(), src.LowBits());
143 }
144 
145 
movq(CpuRegister dst,const Address & src)146 void X86_64Assembler::movq(CpuRegister dst, const Address& src) {
147   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
148   EmitRex64(dst, src);
149   EmitUint8(0x8B);
150   EmitOperand(dst.LowBits(), src);
151 }
152 
153 
movl(CpuRegister dst,const Address & src)154 void X86_64Assembler::movl(CpuRegister dst, const Address& src) {
155   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
156   EmitOptionalRex32(dst, src);
157   EmitUint8(0x8B);
158   EmitOperand(dst.LowBits(), src);
159 }
160 
161 
movq(const Address & dst,CpuRegister src)162 void X86_64Assembler::movq(const Address& dst, CpuRegister src) {
163   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
164   EmitRex64(src, dst);
165   EmitUint8(0x89);
166   EmitOperand(src.LowBits(), dst);
167 }
168 
169 
movl(const Address & dst,CpuRegister src)170 void X86_64Assembler::movl(const Address& dst, CpuRegister src) {
171   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
172   EmitOptionalRex32(src, dst);
173   EmitUint8(0x89);
174   EmitOperand(src.LowBits(), dst);
175 }
176 
movl(const Address & dst,const Immediate & imm)177 void X86_64Assembler::movl(const Address& dst, const Immediate& imm) {
178   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
179   EmitOptionalRex32(dst);
180   EmitUint8(0xC7);
181   EmitOperand(0, dst);
182   EmitImmediate(imm);
183 }
184 
movzxb(CpuRegister dst,CpuRegister src)185 void X86_64Assembler::movzxb(CpuRegister dst, CpuRegister src) {
186   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
187   EmitOptionalByteRegNormalizingRex32(dst, src);
188   EmitUint8(0x0F);
189   EmitUint8(0xB6);
190   EmitRegisterOperand(dst.LowBits(), src.LowBits());
191 }
192 
193 
movzxb(CpuRegister dst,const Address & src)194 void X86_64Assembler::movzxb(CpuRegister dst, const Address& src) {
195   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
196   EmitOptionalByteRegNormalizingRex32(dst, src);
197   EmitUint8(0x0F);
198   EmitUint8(0xB6);
199   EmitOperand(dst.LowBits(), src);
200 }
201 
202 
movsxb(CpuRegister dst,CpuRegister src)203 void X86_64Assembler::movsxb(CpuRegister dst, CpuRegister src) {
204   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
205   EmitOptionalByteRegNormalizingRex32(dst, src);
206   EmitUint8(0x0F);
207   EmitUint8(0xBE);
208   EmitRegisterOperand(dst.LowBits(), src.LowBits());
209 }
210 
211 
movsxb(CpuRegister dst,const Address & src)212 void X86_64Assembler::movsxb(CpuRegister dst, const Address& src) {
213   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
214   EmitOptionalByteRegNormalizingRex32(dst, src);
215   EmitUint8(0x0F);
216   EmitUint8(0xBE);
217   EmitOperand(dst.LowBits(), src);
218 }
219 
220 
movb(CpuRegister,const Address &)221 void X86_64Assembler::movb(CpuRegister /*dst*/, const Address& /*src*/) {
222   LOG(FATAL) << "Use movzxb or movsxb instead.";
223 }
224 
225 
movb(const Address & dst,CpuRegister src)226 void X86_64Assembler::movb(const Address& dst, CpuRegister src) {
227   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
228   EmitOptionalByteRegNormalizingRex32(src, dst);
229   EmitUint8(0x88);
230   EmitOperand(src.LowBits(), dst);
231 }
232 
233 
movb(const Address & dst,const Immediate & imm)234 void X86_64Assembler::movb(const Address& dst, const Immediate& imm) {
235   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
236   EmitUint8(0xC6);
237   EmitOperand(Register::RAX, dst);
238   CHECK(imm.is_int8());
239   EmitUint8(imm.value() & 0xFF);
240 }
241 
242 
movzxw(CpuRegister dst,CpuRegister src)243 void X86_64Assembler::movzxw(CpuRegister dst, CpuRegister src) {
244   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
245   EmitOptionalRex32(dst, src);
246   EmitUint8(0x0F);
247   EmitUint8(0xB7);
248   EmitRegisterOperand(dst.LowBits(), src.LowBits());
249 }
250 
251 
movzxw(CpuRegister dst,const Address & src)252 void X86_64Assembler::movzxw(CpuRegister dst, const Address& src) {
253   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
254   EmitOptionalRex32(dst, src);
255   EmitUint8(0x0F);
256   EmitUint8(0xB7);
257   EmitOperand(dst.LowBits(), src);
258 }
259 
260 
movsxw(CpuRegister dst,CpuRegister src)261 void X86_64Assembler::movsxw(CpuRegister dst, CpuRegister src) {
262   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
263   EmitOptionalRex32(dst, src);
264   EmitUint8(0x0F);
265   EmitUint8(0xBF);
266   EmitRegisterOperand(dst.LowBits(), src.LowBits());
267 }
268 
269 
movsxw(CpuRegister dst,const Address & src)270 void X86_64Assembler::movsxw(CpuRegister dst, const Address& src) {
271   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
272   EmitOptionalRex32(dst, src);
273   EmitUint8(0x0F);
274   EmitUint8(0xBF);
275   EmitOperand(dst.LowBits(), src);
276 }
277 
278 
movw(CpuRegister,const Address &)279 void X86_64Assembler::movw(CpuRegister /*dst*/, const Address& /*src*/) {
280   LOG(FATAL) << "Use movzxw or movsxw instead.";
281 }
282 
283 
movw(const Address & dst,CpuRegister src)284 void X86_64Assembler::movw(const Address& dst, CpuRegister src) {
285   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
286   EmitOperandSizeOverride();
287   EmitOptionalRex32(src, dst);
288   EmitUint8(0x89);
289   EmitOperand(src.LowBits(), dst);
290 }
291 
292 
leaq(CpuRegister dst,const Address & src)293 void X86_64Assembler::leaq(CpuRegister dst, const Address& src) {
294   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
295   EmitRex64(dst, src);
296   EmitUint8(0x8D);
297   EmitOperand(dst.LowBits(), src);
298 }
299 
300 
movss(XmmRegister dst,const Address & src)301 void X86_64Assembler::movss(XmmRegister dst, const Address& src) {
302   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
303   EmitUint8(0xF3);
304   EmitOptionalRex32(dst, src);
305   EmitUint8(0x0F);
306   EmitUint8(0x10);
307   EmitOperand(dst.LowBits(), src);
308 }
309 
310 
movss(const Address & dst,XmmRegister src)311 void X86_64Assembler::movss(const Address& dst, XmmRegister src) {
312   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
313   EmitUint8(0xF3);
314   EmitOptionalRex32(src, dst);
315   EmitUint8(0x0F);
316   EmitUint8(0x11);
317   EmitOperand(src.LowBits(), dst);
318 }
319 
320 
movss(XmmRegister dst,XmmRegister src)321 void X86_64Assembler::movss(XmmRegister dst, XmmRegister src) {
322   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
323   EmitUint8(0xF3);
324   EmitOptionalRex32(dst, src);
325   EmitUint8(0x0F);
326   EmitUint8(0x11);
327   EmitXmmRegisterOperand(src.LowBits(), dst);
328 }
329 
330 
movd(XmmRegister dst,CpuRegister src)331 void X86_64Assembler::movd(XmmRegister dst, CpuRegister src) {
332   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
333   EmitUint8(0x66);
334   EmitOptionalRex32(dst, src);
335   EmitUint8(0x0F);
336   EmitUint8(0x6E);
337   EmitOperand(dst.LowBits(), Operand(src));
338 }
339 
340 
movd(CpuRegister dst,XmmRegister src)341 void X86_64Assembler::movd(CpuRegister dst, XmmRegister src) {
342   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
343   EmitUint8(0x66);
344   EmitOptionalRex32(src, dst);
345   EmitUint8(0x0F);
346   EmitUint8(0x7E);
347   EmitOperand(src.LowBits(), Operand(dst));
348 }
349 
350 
addss(XmmRegister dst,XmmRegister src)351 void X86_64Assembler::addss(XmmRegister dst, XmmRegister src) {
352   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
353   EmitUint8(0xF3);
354   EmitOptionalRex32(dst, src);
355   EmitUint8(0x0F);
356   EmitUint8(0x58);
357   EmitXmmRegisterOperand(dst.LowBits(), src);
358 }
359 
360 
addss(XmmRegister dst,const Address & src)361 void X86_64Assembler::addss(XmmRegister dst, const Address& src) {
362   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
363   EmitUint8(0xF3);
364   EmitOptionalRex32(dst, src);
365   EmitUint8(0x0F);
366   EmitUint8(0x58);
367   EmitOperand(dst.LowBits(), src);
368 }
369 
370 
subss(XmmRegister dst,XmmRegister src)371 void X86_64Assembler::subss(XmmRegister dst, XmmRegister src) {
372   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
373   EmitUint8(0xF3);
374   EmitOptionalRex32(dst, src);
375   EmitUint8(0x0F);
376   EmitUint8(0x5C);
377   EmitXmmRegisterOperand(dst.LowBits(), src);
378 }
379 
380 
subss(XmmRegister dst,const Address & src)381 void X86_64Assembler::subss(XmmRegister dst, const Address& src) {
382   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
383   EmitUint8(0xF3);
384   EmitOptionalRex32(dst, src);
385   EmitUint8(0x0F);
386   EmitUint8(0x5C);
387   EmitOperand(dst.LowBits(), src);
388 }
389 
390 
mulss(XmmRegister dst,XmmRegister src)391 void X86_64Assembler::mulss(XmmRegister dst, XmmRegister src) {
392   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
393   EmitUint8(0xF3);
394   EmitOptionalRex32(dst, src);
395   EmitUint8(0x0F);
396   EmitUint8(0x59);
397   EmitXmmRegisterOperand(dst.LowBits(), src);
398 }
399 
400 
mulss(XmmRegister dst,const Address & src)401 void X86_64Assembler::mulss(XmmRegister dst, const Address& src) {
402   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
403   EmitUint8(0xF3);
404   EmitOptionalRex32(dst, src);
405   EmitUint8(0x0F);
406   EmitUint8(0x59);
407   EmitOperand(dst.LowBits(), src);
408 }
409 
410 
divss(XmmRegister dst,XmmRegister src)411 void X86_64Assembler::divss(XmmRegister dst, XmmRegister src) {
412   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
413   EmitUint8(0xF3);
414   EmitOptionalRex32(dst, src);
415   EmitUint8(0x0F);
416   EmitUint8(0x5E);
417   EmitXmmRegisterOperand(dst.LowBits(), src);
418 }
419 
420 
divss(XmmRegister dst,const Address & src)421 void X86_64Assembler::divss(XmmRegister dst, const Address& src) {
422   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
423   EmitUint8(0xF3);
424   EmitOptionalRex32(dst, src);
425   EmitUint8(0x0F);
426   EmitUint8(0x5E);
427   EmitOperand(dst.LowBits(), src);
428 }
429 
430 
flds(const Address & src)431 void X86_64Assembler::flds(const Address& src) {
432   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
433   EmitUint8(0xD9);
434   EmitOperand(0, src);
435 }
436 
437 
fstps(const Address & dst)438 void X86_64Assembler::fstps(const Address& dst) {
439   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
440   EmitUint8(0xD9);
441   EmitOperand(3, dst);
442 }
443 
444 
movsd(XmmRegister dst,const Address & src)445 void X86_64Assembler::movsd(XmmRegister dst, const Address& src) {
446   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
447   EmitUint8(0xF2);
448   EmitOptionalRex32(dst, src);
449   EmitUint8(0x0F);
450   EmitUint8(0x10);
451   EmitOperand(dst.LowBits(), src);
452 }
453 
454 
movsd(const Address & dst,XmmRegister src)455 void X86_64Assembler::movsd(const Address& dst, XmmRegister src) {
456   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
457   EmitUint8(0xF2);
458   EmitOptionalRex32(src, dst);
459   EmitUint8(0x0F);
460   EmitUint8(0x11);
461   EmitOperand(src.LowBits(), dst);
462 }
463 
464 
movsd(XmmRegister dst,XmmRegister src)465 void X86_64Assembler::movsd(XmmRegister dst, XmmRegister src) {
466   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
467   EmitUint8(0xF2);
468   EmitOptionalRex32(dst, src);
469   EmitUint8(0x0F);
470   EmitUint8(0x11);
471   EmitXmmRegisterOperand(src.LowBits(), dst);
472 }
473 
474 
addsd(XmmRegister dst,XmmRegister src)475 void X86_64Assembler::addsd(XmmRegister dst, XmmRegister src) {
476   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
477   EmitUint8(0xF2);
478   EmitOptionalRex32(dst, src);
479   EmitUint8(0x0F);
480   EmitUint8(0x58);
481   EmitXmmRegisterOperand(dst.LowBits(), src);
482 }
483 
484 
addsd(XmmRegister dst,const Address & src)485 void X86_64Assembler::addsd(XmmRegister dst, const Address& src) {
486   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
487   EmitUint8(0xF2);
488   EmitOptionalRex32(dst, src);
489   EmitUint8(0x0F);
490   EmitUint8(0x58);
491   EmitOperand(dst.LowBits(), src);
492 }
493 
494 
subsd(XmmRegister dst,XmmRegister src)495 void X86_64Assembler::subsd(XmmRegister dst, XmmRegister src) {
496   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
497   EmitUint8(0xF2);
498   EmitOptionalRex32(dst, src);
499   EmitUint8(0x0F);
500   EmitUint8(0x5C);
501   EmitXmmRegisterOperand(dst.LowBits(), src);
502 }
503 
504 
subsd(XmmRegister dst,const Address & src)505 void X86_64Assembler::subsd(XmmRegister dst, const Address& src) {
506   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
507   EmitUint8(0xF2);
508   EmitOptionalRex32(dst, src);
509   EmitUint8(0x0F);
510   EmitUint8(0x5C);
511   EmitOperand(dst.LowBits(), src);
512 }
513 
514 
mulsd(XmmRegister dst,XmmRegister src)515 void X86_64Assembler::mulsd(XmmRegister dst, XmmRegister src) {
516   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
517   EmitUint8(0xF2);
518   EmitOptionalRex32(dst, src);
519   EmitUint8(0x0F);
520   EmitUint8(0x59);
521   EmitXmmRegisterOperand(dst.LowBits(), src);
522 }
523 
524 
mulsd(XmmRegister dst,const Address & src)525 void X86_64Assembler::mulsd(XmmRegister dst, const Address& src) {
526   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
527   EmitUint8(0xF2);
528   EmitOptionalRex32(dst, src);
529   EmitUint8(0x0F);
530   EmitUint8(0x59);
531   EmitOperand(dst.LowBits(), src);
532 }
533 
534 
divsd(XmmRegister dst,XmmRegister src)535 void X86_64Assembler::divsd(XmmRegister dst, XmmRegister src) {
536   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
537   EmitUint8(0xF2);
538   EmitOptionalRex32(dst, src);
539   EmitUint8(0x0F);
540   EmitUint8(0x5E);
541   EmitXmmRegisterOperand(dst.LowBits(), src);
542 }
543 
544 
divsd(XmmRegister dst,const Address & src)545 void X86_64Assembler::divsd(XmmRegister dst, const Address& src) {
546   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
547   EmitUint8(0xF2);
548   EmitOptionalRex32(dst, src);
549   EmitUint8(0x0F);
550   EmitUint8(0x5E);
551   EmitOperand(dst.LowBits(), src);
552 }
553 
554 
cvtsi2ss(XmmRegister dst,CpuRegister src)555 void X86_64Assembler::cvtsi2ss(XmmRegister dst, CpuRegister src) {
556   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
557   EmitUint8(0xF3);
558   EmitOptionalRex32(dst, src);
559   EmitUint8(0x0F);
560   EmitUint8(0x2A);
561   EmitOperand(dst.LowBits(), Operand(src));
562 }
563 
564 
cvtsi2sd(XmmRegister dst,CpuRegister src)565 void X86_64Assembler::cvtsi2sd(XmmRegister dst, CpuRegister src) {
566   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
567   EmitUint8(0xF2);
568   EmitOptionalRex32(dst, src);
569   EmitUint8(0x0F);
570   EmitUint8(0x2A);
571   EmitOperand(dst.LowBits(), Operand(src));
572 }
573 
574 
cvtss2si(CpuRegister dst,XmmRegister src)575 void X86_64Assembler::cvtss2si(CpuRegister dst, XmmRegister src) {
576   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
577   EmitUint8(0xF3);
578   EmitOptionalRex32(dst, src);
579   EmitUint8(0x0F);
580   EmitUint8(0x2D);
581   EmitXmmRegisterOperand(dst.LowBits(), src);
582 }
583 
584 
cvtss2sd(XmmRegister dst,XmmRegister src)585 void X86_64Assembler::cvtss2sd(XmmRegister dst, XmmRegister src) {
586   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
587   EmitUint8(0xF3);
588   EmitOptionalRex32(dst, src);
589   EmitUint8(0x0F);
590   EmitUint8(0x5A);
591   EmitXmmRegisterOperand(dst.LowBits(), src);
592 }
593 
594 
cvtsd2si(CpuRegister dst,XmmRegister src)595 void X86_64Assembler::cvtsd2si(CpuRegister dst, XmmRegister src) {
596   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
597   EmitUint8(0xF2);
598   EmitOptionalRex32(dst, src);
599   EmitUint8(0x0F);
600   EmitUint8(0x2D);
601   EmitXmmRegisterOperand(dst.LowBits(), src);
602 }
603 
604 
cvttss2si(CpuRegister dst,XmmRegister src)605 void X86_64Assembler::cvttss2si(CpuRegister dst, XmmRegister src) {
606   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
607   EmitUint8(0xF3);
608   EmitOptionalRex32(dst, src);
609   EmitUint8(0x0F);
610   EmitUint8(0x2C);
611   EmitXmmRegisterOperand(dst.LowBits(), src);
612 }
613 
614 
cvttsd2si(CpuRegister dst,XmmRegister src)615 void X86_64Assembler::cvttsd2si(CpuRegister dst, XmmRegister src) {
616   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
617   EmitUint8(0xF2);
618   EmitOptionalRex32(dst, src);
619   EmitUint8(0x0F);
620   EmitUint8(0x2C);
621   EmitXmmRegisterOperand(dst.LowBits(), src);
622 }
623 
624 
cvtsd2ss(XmmRegister dst,XmmRegister src)625 void X86_64Assembler::cvtsd2ss(XmmRegister dst, XmmRegister src) {
626   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
627   EmitUint8(0xF2);
628   EmitOptionalRex32(dst, src);
629   EmitUint8(0x0F);
630   EmitUint8(0x5A);
631   EmitXmmRegisterOperand(dst.LowBits(), src);
632 }
633 
634 
cvtdq2pd(XmmRegister dst,XmmRegister src)635 void X86_64Assembler::cvtdq2pd(XmmRegister dst, XmmRegister src) {
636   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
637   EmitUint8(0xF3);
638   EmitOptionalRex32(dst, src);
639   EmitUint8(0x0F);
640   EmitUint8(0xE6);
641   EmitXmmRegisterOperand(dst.LowBits(), src);
642 }
643 
644 
comiss(XmmRegister a,XmmRegister b)645 void X86_64Assembler::comiss(XmmRegister a, XmmRegister b) {
646   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
647   EmitOptionalRex32(a, b);
648   EmitUint8(0x0F);
649   EmitUint8(0x2F);
650   EmitXmmRegisterOperand(a.LowBits(), b);
651 }
652 
653 
comisd(XmmRegister a,XmmRegister b)654 void X86_64Assembler::comisd(XmmRegister a, XmmRegister b) {
655   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
656   EmitUint8(0x66);
657   EmitOptionalRex32(a, b);
658   EmitUint8(0x0F);
659   EmitUint8(0x2F);
660   EmitXmmRegisterOperand(a.LowBits(), b);
661 }
662 
663 
sqrtsd(XmmRegister dst,XmmRegister src)664 void X86_64Assembler::sqrtsd(XmmRegister dst, XmmRegister src) {
665   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
666   EmitUint8(0xF2);
667   EmitOptionalRex32(dst, src);
668   EmitUint8(0x0F);
669   EmitUint8(0x51);
670   EmitXmmRegisterOperand(dst.LowBits(), src);
671 }
672 
673 
sqrtss(XmmRegister dst,XmmRegister src)674 void X86_64Assembler::sqrtss(XmmRegister dst, XmmRegister src) {
675   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
676   EmitUint8(0xF3);
677   EmitOptionalRex32(dst, src);
678   EmitUint8(0x0F);
679   EmitUint8(0x51);
680   EmitXmmRegisterOperand(dst.LowBits(), src);
681 }
682 
683 
xorpd(XmmRegister dst,const Address & src)684 void X86_64Assembler::xorpd(XmmRegister dst, const Address& src) {
685   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
686   EmitUint8(0x66);
687   EmitOptionalRex32(dst, src);
688   EmitUint8(0x0F);
689   EmitUint8(0x57);
690   EmitOperand(dst.LowBits(), src);
691 }
692 
693 
xorpd(XmmRegister dst,XmmRegister src)694 void X86_64Assembler::xorpd(XmmRegister dst, XmmRegister src) {
695   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
696   EmitUint8(0x66);
697   EmitOptionalRex32(dst, src);
698   EmitUint8(0x0F);
699   EmitUint8(0x57);
700   EmitXmmRegisterOperand(dst.LowBits(), src);
701 }
702 
703 
xorps(XmmRegister dst,const Address & src)704 void X86_64Assembler::xorps(XmmRegister dst, const Address& src) {
705   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
706   EmitOptionalRex32(dst, src);
707   EmitUint8(0x0F);
708   EmitUint8(0x57);
709   EmitOperand(dst.LowBits(), src);
710 }
711 
712 
xorps(XmmRegister dst,XmmRegister src)713 void X86_64Assembler::xorps(XmmRegister dst, XmmRegister src) {
714   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
715   EmitOptionalRex32(dst, src);
716   EmitUint8(0x0F);
717   EmitUint8(0x57);
718   EmitXmmRegisterOperand(dst.LowBits(), src);
719 }
720 
721 
andpd(XmmRegister dst,const Address & src)722 void X86_64Assembler::andpd(XmmRegister dst, const Address& src) {
723   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
724   EmitUint8(0x66);
725   EmitOptionalRex32(dst, src);
726   EmitUint8(0x0F);
727   EmitUint8(0x54);
728   EmitOperand(dst.LowBits(), src);
729 }
730 
731 
fldl(const Address & src)732 void X86_64Assembler::fldl(const Address& src) {
733   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
734   EmitUint8(0xDD);
735   EmitOperand(0, src);
736 }
737 
738 
fstpl(const Address & dst)739 void X86_64Assembler::fstpl(const Address& dst) {
740   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
741   EmitUint8(0xDD);
742   EmitOperand(3, dst);
743 }
744 
745 
fnstcw(const Address & dst)746 void X86_64Assembler::fnstcw(const Address& dst) {
747   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
748   EmitUint8(0xD9);
749   EmitOperand(7, dst);
750 }
751 
752 
fldcw(const Address & src)753 void X86_64Assembler::fldcw(const Address& src) {
754   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
755   EmitUint8(0xD9);
756   EmitOperand(5, src);
757 }
758 
759 
fistpl(const Address & dst)760 void X86_64Assembler::fistpl(const Address& dst) {
761   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
762   EmitUint8(0xDF);
763   EmitOperand(7, dst);
764 }
765 
766 
fistps(const Address & dst)767 void X86_64Assembler::fistps(const Address& dst) {
768   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
769   EmitUint8(0xDB);
770   EmitOperand(3, dst);
771 }
772 
773 
fildl(const Address & src)774 void X86_64Assembler::fildl(const Address& src) {
775   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
776   EmitUint8(0xDF);
777   EmitOperand(5, src);
778 }
779 
780 
fincstp()781 void X86_64Assembler::fincstp() {
782   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
783   EmitUint8(0xD9);
784   EmitUint8(0xF7);
785 }
786 
787 
ffree(const Immediate & index)788 void X86_64Assembler::ffree(const Immediate& index) {
789   CHECK_LT(index.value(), 7);
790   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
791   EmitUint8(0xDD);
792   EmitUint8(0xC0 + index.value());
793 }
794 
795 
fsin()796 void X86_64Assembler::fsin() {
797   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
798   EmitUint8(0xD9);
799   EmitUint8(0xFE);
800 }
801 
802 
fcos()803 void X86_64Assembler::fcos() {
804   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
805   EmitUint8(0xD9);
806   EmitUint8(0xFF);
807 }
808 
809 
fptan()810 void X86_64Assembler::fptan() {
811   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
812   EmitUint8(0xD9);
813   EmitUint8(0xF2);
814 }
815 
816 
xchgl(CpuRegister dst,CpuRegister src)817 void X86_64Assembler::xchgl(CpuRegister dst, CpuRegister src) {
818   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
819   EmitOptionalRex32(dst, src);
820   EmitUint8(0x87);
821   EmitRegisterOperand(dst.LowBits(), src.LowBits());
822 }
823 
824 
xchgq(CpuRegister dst,CpuRegister src)825 void X86_64Assembler::xchgq(CpuRegister dst, CpuRegister src) {
826   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
827   EmitRex64(dst, src);
828   EmitUint8(0x87);
829   EmitOperand(dst.LowBits(), Operand(src));
830 }
831 
832 
xchgl(CpuRegister reg,const Address & address)833 void X86_64Assembler::xchgl(CpuRegister reg, const Address& address) {
834   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
835   EmitOptionalRex32(reg, address);
836   EmitUint8(0x87);
837   EmitOperand(reg.LowBits(), address);
838 }
839 
840 
cmpl(CpuRegister reg,const Immediate & imm)841 void X86_64Assembler::cmpl(CpuRegister reg, const Immediate& imm) {
842   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
843   EmitOptionalRex32(reg);
844   EmitComplex(7, Operand(reg), imm);
845 }
846 
847 
cmpl(CpuRegister reg0,CpuRegister reg1)848 void X86_64Assembler::cmpl(CpuRegister reg0, CpuRegister reg1) {
849   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
850   EmitOptionalRex32(reg0, reg1);
851   EmitUint8(0x3B);
852   EmitOperand(reg0.LowBits(), Operand(reg1));
853 }
854 
855 
cmpl(CpuRegister reg,const Address & address)856 void X86_64Assembler::cmpl(CpuRegister reg, const Address& address) {
857   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
858   EmitOptionalRex32(reg, address);
859   EmitUint8(0x3B);
860   EmitOperand(reg.LowBits(), address);
861 }
862 
863 
cmpq(CpuRegister reg0,CpuRegister reg1)864 void X86_64Assembler::cmpq(CpuRegister reg0, CpuRegister reg1) {
865   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
866   EmitRex64(reg0, reg1);
867   EmitUint8(0x3B);
868   EmitOperand(reg0.LowBits(), Operand(reg1));
869 }
870 
871 
cmpq(CpuRegister reg,const Immediate & imm)872 void X86_64Assembler::cmpq(CpuRegister reg, const Immediate& imm) {
873   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
874   CHECK(imm.is_int32());  // cmpq only supports 32b immediate.
875   EmitRex64(reg);
876   EmitComplex(7, Operand(reg), imm);
877 }
878 
879 
cmpq(CpuRegister reg,const Address & address)880 void X86_64Assembler::cmpq(CpuRegister reg, const Address& address) {
881   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
882   EmitRex64(reg);
883   EmitUint8(0x3B);
884   EmitOperand(reg.LowBits(), address);
885 }
886 
887 
addl(CpuRegister dst,CpuRegister src)888 void X86_64Assembler::addl(CpuRegister dst, CpuRegister src) {
889   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
890   EmitOptionalRex32(dst, src);
891   EmitUint8(0x03);
892   EmitRegisterOperand(dst.LowBits(), src.LowBits());
893 }
894 
895 
addl(CpuRegister reg,const Address & address)896 void X86_64Assembler::addl(CpuRegister reg, const Address& address) {
897   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
898   EmitOptionalRex32(reg, address);
899   EmitUint8(0x03);
900   EmitOperand(reg.LowBits(), address);
901 }
902 
903 
cmpl(const Address & address,CpuRegister reg)904 void X86_64Assembler::cmpl(const Address& address, CpuRegister reg) {
905   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
906   EmitOptionalRex32(reg, address);
907   EmitUint8(0x39);
908   EmitOperand(reg.LowBits(), address);
909 }
910 
911 
cmpl(const Address & address,const Immediate & imm)912 void X86_64Assembler::cmpl(const Address& address, const Immediate& imm) {
913   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
914   EmitOptionalRex32(address);
915   EmitComplex(7, address, imm);
916 }
917 
918 
testl(CpuRegister reg1,CpuRegister reg2)919 void X86_64Assembler::testl(CpuRegister reg1, CpuRegister reg2) {
920   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
921   EmitOptionalRex32(reg1, reg2);
922   EmitUint8(0x85);
923   EmitRegisterOperand(reg1.LowBits(), reg2.LowBits());
924 }
925 
926 
testl(CpuRegister reg,const Immediate & immediate)927 void X86_64Assembler::testl(CpuRegister reg, const Immediate& immediate) {
928   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
929   // For registers that have a byte variant (RAX, RBX, RCX, and RDX)
930   // we only test the byte CpuRegister to keep the encoding short.
931   if (immediate.is_uint8() && reg.AsRegister() < 4) {
932     // Use zero-extended 8-bit immediate.
933     if (reg.AsRegister() == RAX) {
934       EmitUint8(0xA8);
935     } else {
936       EmitUint8(0xF6);
937       EmitUint8(0xC0 + reg.AsRegister());
938     }
939     EmitUint8(immediate.value() & 0xFF);
940   } else if (reg.AsRegister() == RAX) {
941     // Use short form if the destination is RAX.
942     EmitUint8(0xA9);
943     EmitImmediate(immediate);
944   } else {
945     EmitOptionalRex32(reg);
946     EmitUint8(0xF7);
947     EmitOperand(0, Operand(reg));
948     EmitImmediate(immediate);
949   }
950 }
951 
952 
testq(CpuRegister reg,const Address & address)953 void X86_64Assembler::testq(CpuRegister reg, const Address& address) {
954   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
955   EmitRex64(reg);
956   EmitUint8(0x85);
957   EmitOperand(reg.LowBits(), address);
958 }
959 
960 
andl(CpuRegister dst,CpuRegister src)961 void X86_64Assembler::andl(CpuRegister dst, CpuRegister src) {
962   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
963   EmitOptionalRex32(dst, src);
964   EmitUint8(0x23);
965   EmitOperand(dst.LowBits(), Operand(src));
966 }
967 
968 
andl(CpuRegister dst,const Immediate & imm)969 void X86_64Assembler::andl(CpuRegister dst, const Immediate& imm) {
970   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
971   EmitOptionalRex32(dst);
972   EmitComplex(4, Operand(dst), imm);
973 }
974 
975 
andq(CpuRegister reg,const Immediate & imm)976 void X86_64Assembler::andq(CpuRegister reg, const Immediate& imm) {
977   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
978   CHECK(imm.is_int32());  // andq only supports 32b immediate.
979   EmitRex64(reg);
980   EmitComplex(4, Operand(reg), imm);
981 }
982 
983 
orl(CpuRegister dst,CpuRegister src)984 void X86_64Assembler::orl(CpuRegister dst, CpuRegister src) {
985   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
986   EmitOptionalRex32(dst, src);
987   EmitUint8(0x0B);
988   EmitOperand(dst.LowBits(), Operand(src));
989 }
990 
991 
orl(CpuRegister dst,const Immediate & imm)992 void X86_64Assembler::orl(CpuRegister dst, const Immediate& imm) {
993   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
994   EmitOptionalRex32(dst);
995   EmitComplex(1, Operand(dst), imm);
996 }
997 
998 
xorl(CpuRegister dst,CpuRegister src)999 void X86_64Assembler::xorl(CpuRegister dst, CpuRegister src) {
1000   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1001   EmitOptionalRex32(dst, src);
1002   EmitUint8(0x33);
1003   EmitOperand(dst.LowBits(), Operand(src));
1004 }
1005 
1006 
xorq(CpuRegister dst,CpuRegister src)1007 void X86_64Assembler::xorq(CpuRegister dst, CpuRegister src) {
1008   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1009   EmitRex64(dst, src);
1010   EmitUint8(0x33);
1011   EmitOperand(dst.LowBits(), Operand(src));
1012 }
1013 
1014 
xorq(CpuRegister dst,const Immediate & imm)1015 void X86_64Assembler::xorq(CpuRegister dst, const Immediate& imm) {
1016   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1017   CHECK(imm.is_int32());  // xorq only supports 32b immediate.
1018   EmitRex64(dst);
1019   EmitComplex(6, Operand(dst), imm);
1020 }
1021 
1022 #if 0
1023 void X86_64Assembler::rex(bool force, bool w, Register* r, Register* x, Register* b) {
1024   // REX.WRXB
1025   // W - 64-bit operand
1026   // R - MODRM.reg
1027   // X - SIB.index
1028   // B - MODRM.rm/SIB.base
1029   uint8_t rex = force ? 0x40 : 0;
1030   if (w) {
1031     rex |= 0x48;  // REX.W000
1032   }
1033   if (r != nullptr && *r >= Register::R8 && *r < Register::kNumberOfCpuRegisters) {
1034     rex |= 0x44;  // REX.0R00
1035     *r = static_cast<Register>(*r - 8);
1036   }
1037   if (x != nullptr && *x >= Register::R8 && *x < Register::kNumberOfCpuRegisters) {
1038     rex |= 0x42;  // REX.00X0
1039     *x = static_cast<Register>(*x - 8);
1040   }
1041   if (b != nullptr && *b >= Register::R8 && *b < Register::kNumberOfCpuRegisters) {
1042     rex |= 0x41;  // REX.000B
1043     *b = static_cast<Register>(*b - 8);
1044   }
1045   if (rex != 0) {
1046     EmitUint8(rex);
1047   }
1048 }
1049 
1050 void X86_64Assembler::rex_reg_mem(bool force, bool w, Register* dst, const Address& mem) {
1051   // REX.WRXB
1052   // W - 64-bit operand
1053   // R - MODRM.reg
1054   // X - SIB.index
1055   // B - MODRM.rm/SIB.base
1056   uint8_t rex = mem->rex();
1057   if (force) {
1058     rex |= 0x40;  // REX.0000
1059   }
1060   if (w) {
1061     rex |= 0x48;  // REX.W000
1062   }
1063   if (dst != nullptr && *dst >= Register::R8 && *dst < Register::kNumberOfCpuRegisters) {
1064     rex |= 0x44;  // REX.0R00
1065     *dst = static_cast<Register>(*dst - 8);
1066   }
1067   if (rex != 0) {
1068     EmitUint8(rex);
1069   }
1070 }
1071 
1072 void rex_mem_reg(bool force, bool w, Address* mem, Register* src);
1073 #endif
1074 
addl(CpuRegister reg,const Immediate & imm)1075 void X86_64Assembler::addl(CpuRegister reg, const Immediate& imm) {
1076   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1077   EmitOptionalRex32(reg);
1078   EmitComplex(0, Operand(reg), imm);
1079 }
1080 
1081 
addq(CpuRegister reg,const Immediate & imm)1082 void X86_64Assembler::addq(CpuRegister reg, const Immediate& imm) {
1083   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1084   CHECK(imm.is_int32());  // addq only supports 32b immediate.
1085   EmitRex64(reg);
1086   EmitComplex(0, Operand(reg), imm);
1087 }
1088 
1089 
addq(CpuRegister dst,const Address & address)1090 void X86_64Assembler::addq(CpuRegister dst, const Address& address) {
1091   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1092   EmitRex64(dst);
1093   EmitUint8(0x03);
1094   EmitOperand(dst.LowBits(), address);
1095 }
1096 
1097 
addq(CpuRegister dst,CpuRegister src)1098 void X86_64Assembler::addq(CpuRegister dst, CpuRegister src) {
1099   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1100   // 0x01 is addq r/m64 <- r/m64 + r64, with op1 in r/m and op2 in reg: so reverse EmitRex64
1101   EmitRex64(src, dst);
1102   EmitUint8(0x01);
1103   EmitRegisterOperand(src.LowBits(), dst.LowBits());
1104 }
1105 
1106 
addl(const Address & address,CpuRegister reg)1107 void X86_64Assembler::addl(const Address& address, CpuRegister reg) {
1108   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1109   EmitOptionalRex32(reg, address);
1110   EmitUint8(0x01);
1111   EmitOperand(reg.LowBits(), address);
1112 }
1113 
1114 
addl(const Address & address,const Immediate & imm)1115 void X86_64Assembler::addl(const Address& address, const Immediate& imm) {
1116   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1117   EmitOptionalRex32(address);
1118   EmitComplex(0, address, imm);
1119 }
1120 
1121 
subl(CpuRegister dst,CpuRegister src)1122 void X86_64Assembler::subl(CpuRegister dst, CpuRegister src) {
1123   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1124   EmitOptionalRex32(dst, src);
1125   EmitUint8(0x2B);
1126   EmitOperand(dst.LowBits(), Operand(src));
1127 }
1128 
1129 
subl(CpuRegister reg,const Immediate & imm)1130 void X86_64Assembler::subl(CpuRegister reg, const Immediate& imm) {
1131   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1132   EmitOptionalRex32(reg);
1133   EmitComplex(5, Operand(reg), imm);
1134 }
1135 
1136 
subq(CpuRegister reg,const Immediate & imm)1137 void X86_64Assembler::subq(CpuRegister reg, const Immediate& imm) {
1138   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1139   CHECK(imm.is_int32());  // subq only supports 32b immediate.
1140   EmitRex64(reg);
1141   EmitComplex(5, Operand(reg), imm);
1142 }
1143 
1144 
subq(CpuRegister dst,CpuRegister src)1145 void X86_64Assembler::subq(CpuRegister dst, CpuRegister src) {
1146   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1147   EmitRex64(dst, src);
1148   EmitUint8(0x2B);
1149   EmitRegisterOperand(dst.LowBits(), src.LowBits());
1150 }
1151 
1152 
subq(CpuRegister reg,const Address & address)1153 void X86_64Assembler::subq(CpuRegister reg, const Address& address) {
1154   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1155   EmitRex64(reg);
1156   EmitUint8(0x2B);
1157   EmitOperand(reg.LowBits() & 7, address);
1158 }
1159 
1160 
subl(CpuRegister reg,const Address & address)1161 void X86_64Assembler::subl(CpuRegister reg, const Address& address) {
1162   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1163   EmitOptionalRex32(reg, address);
1164   EmitUint8(0x2B);
1165   EmitOperand(reg.LowBits(), address);
1166 }
1167 
1168 
cdq()1169 void X86_64Assembler::cdq() {
1170   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1171   EmitUint8(0x99);
1172 }
1173 
1174 
idivl(CpuRegister reg)1175 void X86_64Assembler::idivl(CpuRegister reg) {
1176   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1177   EmitOptionalRex32(reg);
1178   EmitUint8(0xF7);
1179   EmitUint8(0xF8 | reg.LowBits());
1180 }
1181 
1182 
imull(CpuRegister dst,CpuRegister src)1183 void X86_64Assembler::imull(CpuRegister dst, CpuRegister src) {
1184   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1185   EmitOptionalRex32(dst, src);
1186   EmitUint8(0x0F);
1187   EmitUint8(0xAF);
1188   EmitOperand(dst.LowBits(), Operand(src));
1189 }
1190 
1191 
imull(CpuRegister reg,const Immediate & imm)1192 void X86_64Assembler::imull(CpuRegister reg, const Immediate& imm) {
1193   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1194   EmitOptionalRex32(reg);
1195   EmitUint8(0x69);
1196   EmitOperand(reg.LowBits(), Operand(reg));
1197   EmitImmediate(imm);
1198 }
1199 
1200 
imull(CpuRegister reg,const Address & address)1201 void X86_64Assembler::imull(CpuRegister reg, const Address& address) {
1202   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1203   EmitOptionalRex32(reg, address);
1204   EmitUint8(0x0F);
1205   EmitUint8(0xAF);
1206   EmitOperand(reg.LowBits(), address);
1207 }
1208 
1209 
imull(CpuRegister reg)1210 void X86_64Assembler::imull(CpuRegister reg) {
1211   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1212   EmitOptionalRex32(reg);
1213   EmitUint8(0xF7);
1214   EmitOperand(5, Operand(reg));
1215 }
1216 
1217 
imull(const Address & address)1218 void X86_64Assembler::imull(const Address& address) {
1219   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1220   EmitOptionalRex32(address);
1221   EmitUint8(0xF7);
1222   EmitOperand(5, address);
1223 }
1224 
1225 
mull(CpuRegister reg)1226 void X86_64Assembler::mull(CpuRegister reg) {
1227   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1228   EmitOptionalRex32(reg);
1229   EmitUint8(0xF7);
1230   EmitOperand(4, Operand(reg));
1231 }
1232 
1233 
mull(const Address & address)1234 void X86_64Assembler::mull(const Address& address) {
1235   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1236   EmitOptionalRex32(address);
1237   EmitUint8(0xF7);
1238   EmitOperand(4, address);
1239 }
1240 
1241 
1242 
shll(CpuRegister reg,const Immediate & imm)1243 void X86_64Assembler::shll(CpuRegister reg, const Immediate& imm) {
1244   EmitGenericShift(false, 4, reg, imm);
1245 }
1246 
1247 
shll(CpuRegister operand,CpuRegister shifter)1248 void X86_64Assembler::shll(CpuRegister operand, CpuRegister shifter) {
1249   EmitGenericShift(4, operand, shifter);
1250 }
1251 
1252 
shrl(CpuRegister reg,const Immediate & imm)1253 void X86_64Assembler::shrl(CpuRegister reg, const Immediate& imm) {
1254   EmitGenericShift(false, 5, reg, imm);
1255 }
1256 
1257 
shrq(CpuRegister reg,const Immediate & imm)1258 void X86_64Assembler::shrq(CpuRegister reg, const Immediate& imm) {
1259   EmitGenericShift(true, 5, reg, imm);
1260 }
1261 
1262 
shrl(CpuRegister operand,CpuRegister shifter)1263 void X86_64Assembler::shrl(CpuRegister operand, CpuRegister shifter) {
1264   EmitGenericShift(5, operand, shifter);
1265 }
1266 
1267 
sarl(CpuRegister reg,const Immediate & imm)1268 void X86_64Assembler::sarl(CpuRegister reg, const Immediate& imm) {
1269   EmitGenericShift(false, 7, reg, imm);
1270 }
1271 
1272 
sarl(CpuRegister operand,CpuRegister shifter)1273 void X86_64Assembler::sarl(CpuRegister operand, CpuRegister shifter) {
1274   EmitGenericShift(7, operand, shifter);
1275 }
1276 
1277 
negl(CpuRegister reg)1278 void X86_64Assembler::negl(CpuRegister reg) {
1279   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1280   EmitOptionalRex32(reg);
1281   EmitUint8(0xF7);
1282   EmitOperand(3, Operand(reg));
1283 }
1284 
1285 
notl(CpuRegister reg)1286 void X86_64Assembler::notl(CpuRegister reg) {
1287   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1288   EmitOptionalRex32(reg);
1289   EmitUint8(0xF7);
1290   EmitUint8(0xD0 | reg.LowBits());
1291 }
1292 
1293 
enter(const Immediate & imm)1294 void X86_64Assembler::enter(const Immediate& imm) {
1295   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1296   EmitUint8(0xC8);
1297   CHECK(imm.is_uint16());
1298   EmitUint8(imm.value() & 0xFF);
1299   EmitUint8((imm.value() >> 8) & 0xFF);
1300   EmitUint8(0x00);
1301 }
1302 
1303 
leave()1304 void X86_64Assembler::leave() {
1305   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1306   EmitUint8(0xC9);
1307 }
1308 
1309 
ret()1310 void X86_64Assembler::ret() {
1311   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1312   EmitUint8(0xC3);
1313 }
1314 
1315 
ret(const Immediate & imm)1316 void X86_64Assembler::ret(const Immediate& imm) {
1317   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1318   EmitUint8(0xC2);
1319   CHECK(imm.is_uint16());
1320   EmitUint8(imm.value() & 0xFF);
1321   EmitUint8((imm.value() >> 8) & 0xFF);
1322 }
1323 
1324 
1325 
nop()1326 void X86_64Assembler::nop() {
1327   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1328   EmitUint8(0x90);
1329 }
1330 
1331 
int3()1332 void X86_64Assembler::int3() {
1333   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1334   EmitUint8(0xCC);
1335 }
1336 
1337 
hlt()1338 void X86_64Assembler::hlt() {
1339   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1340   EmitUint8(0xF4);
1341 }
1342 
1343 
j(Condition condition,Label * label)1344 void X86_64Assembler::j(Condition condition, Label* label) {
1345   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1346   if (label->IsBound()) {
1347     static const int kShortSize = 2;
1348     static const int kLongSize = 6;
1349     int offset = label->Position() - buffer_.Size();
1350     CHECK_LE(offset, 0);
1351     if (IsInt(8, offset - kShortSize)) {
1352       EmitUint8(0x70 + condition);
1353       EmitUint8((offset - kShortSize) & 0xFF);
1354     } else {
1355       EmitUint8(0x0F);
1356       EmitUint8(0x80 + condition);
1357       EmitInt32(offset - kLongSize);
1358     }
1359   } else {
1360     EmitUint8(0x0F);
1361     EmitUint8(0x80 + condition);
1362     EmitLabelLink(label);
1363   }
1364 }
1365 
1366 
jmp(CpuRegister reg)1367 void X86_64Assembler::jmp(CpuRegister reg) {
1368   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1369   EmitOptionalRex32(reg);
1370   EmitUint8(0xFF);
1371   EmitRegisterOperand(4, reg.LowBits());
1372 }
1373 
jmp(const Address & address)1374 void X86_64Assembler::jmp(const Address& address) {
1375   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1376   EmitOptionalRex32(address);
1377   EmitUint8(0xFF);
1378   EmitOperand(4, address);
1379 }
1380 
jmp(Label * label)1381 void X86_64Assembler::jmp(Label* label) {
1382   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1383   if (label->IsBound()) {
1384     static const int kShortSize = 2;
1385     static const int kLongSize = 5;
1386     int offset = label->Position() - buffer_.Size();
1387     CHECK_LE(offset, 0);
1388     if (IsInt(8, offset - kShortSize)) {
1389       EmitUint8(0xEB);
1390       EmitUint8((offset - kShortSize) & 0xFF);
1391     } else {
1392       EmitUint8(0xE9);
1393       EmitInt32(offset - kLongSize);
1394     }
1395   } else {
1396     EmitUint8(0xE9);
1397     EmitLabelLink(label);
1398   }
1399 }
1400 
1401 
lock()1402 X86_64Assembler* X86_64Assembler::lock() {
1403   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1404   EmitUint8(0xF0);
1405   return this;
1406 }
1407 
1408 
cmpxchgl(const Address & address,CpuRegister reg)1409 void X86_64Assembler::cmpxchgl(const Address& address, CpuRegister reg) {
1410   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1411   EmitUint8(0x0F);
1412   EmitUint8(0xB1);
1413   EmitOperand(reg.LowBits(), address);
1414 }
1415 
mfence()1416 void X86_64Assembler::mfence() {
1417   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1418   EmitUint8(0x0F);
1419   EmitUint8(0xAE);
1420   EmitUint8(0xF0);
1421 }
1422 
1423 
gs()1424 X86_64Assembler* X86_64Assembler::gs() {
1425   // TODO: gs is a prefix and not an instruction
1426   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1427   EmitUint8(0x65);
1428   return this;
1429 }
1430 
1431 
AddImmediate(CpuRegister reg,const Immediate & imm)1432 void X86_64Assembler::AddImmediate(CpuRegister reg, const Immediate& imm) {
1433   int value = imm.value();
1434   if (value != 0) {
1435     if (value > 0) {
1436       addl(reg, imm);
1437     } else {
1438       subl(reg, Immediate(value));
1439     }
1440   }
1441 }
1442 
1443 
setcc(Condition condition,CpuRegister dst)1444 void X86_64Assembler::setcc(Condition condition, CpuRegister dst) {
1445   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1446   // RSP, RBP, RDI, RSI need rex prefix (else the pattern encodes ah/bh/ch/dh).
1447   if (dst.NeedsRex() || dst.AsRegister() > 3) {
1448     EmitOptionalRex(true, false, false, false, dst.NeedsRex());
1449   }
1450   EmitUint8(0x0F);
1451   EmitUint8(0x90 + condition);
1452   EmitUint8(0xC0 + dst.LowBits());
1453 }
1454 
1455 
LoadDoubleConstant(XmmRegister dst,double value)1456 void X86_64Assembler::LoadDoubleConstant(XmmRegister dst, double value) {
1457   // TODO: Need to have a code constants table.
1458   int64_t constant = bit_cast<int64_t, double>(value);
1459   pushq(Immediate(High32Bits(constant)));
1460   pushq(Immediate(Low32Bits(constant)));
1461   movsd(dst, Address(CpuRegister(RSP), 0));
1462   addq(CpuRegister(RSP), Immediate(2 * kWordSize));
1463 }
1464 
1465 
FloatNegate(XmmRegister f)1466 void X86_64Assembler::FloatNegate(XmmRegister f) {
1467   static const struct {
1468     uint32_t a;
1469     uint32_t b;
1470     uint32_t c;
1471     uint32_t d;
1472   } float_negate_constant __attribute__((aligned(16))) =
1473       { 0x80000000, 0x00000000, 0x80000000, 0x00000000 };
1474   xorps(f, Address::Absolute(reinterpret_cast<uword>(&float_negate_constant)));
1475 }
1476 
1477 
DoubleNegate(XmmRegister d)1478 void X86_64Assembler::DoubleNegate(XmmRegister d) {
1479   static const struct {
1480     uint64_t a;
1481     uint64_t b;
1482   } double_negate_constant __attribute__((aligned(16))) =
1483       {0x8000000000000000LL, 0x8000000000000000LL};
1484   xorpd(d, Address::Absolute(reinterpret_cast<uword>(&double_negate_constant)));
1485 }
1486 
1487 
DoubleAbs(XmmRegister reg)1488 void X86_64Assembler::DoubleAbs(XmmRegister reg) {
1489   static const struct {
1490     uint64_t a;
1491     uint64_t b;
1492   } double_abs_constant __attribute__((aligned(16))) =
1493       {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL};
1494   andpd(reg, Address::Absolute(reinterpret_cast<uword>(&double_abs_constant)));
1495 }
1496 
1497 
Align(int alignment,int offset)1498 void X86_64Assembler::Align(int alignment, int offset) {
1499   CHECK(IsPowerOfTwo(alignment));
1500   // Emit nop instruction until the real position is aligned.
1501   while (((offset + buffer_.GetPosition()) & (alignment-1)) != 0) {
1502     nop();
1503   }
1504 }
1505 
1506 
Bind(Label * label)1507 void X86_64Assembler::Bind(Label* label) {
1508   int bound = buffer_.Size();
1509   CHECK(!label->IsBound());  // Labels can only be bound once.
1510   while (label->IsLinked()) {
1511     int position = label->LinkPosition();
1512     int next = buffer_.Load<int32_t>(position);
1513     buffer_.Store<int32_t>(position, bound - (position + 4));
1514     label->position_ = next;
1515   }
1516   label->BindTo(bound);
1517 }
1518 
1519 
EmitOperand(uint8_t reg_or_opcode,const Operand & operand)1520 void X86_64Assembler::EmitOperand(uint8_t reg_or_opcode, const Operand& operand) {
1521   CHECK_GE(reg_or_opcode, 0);
1522   CHECK_LT(reg_or_opcode, 8);
1523   const int length = operand.length_;
1524   CHECK_GT(length, 0);
1525   // Emit the ModRM byte updated with the given reg value.
1526   CHECK_EQ(operand.encoding_[0] & 0x38, 0);
1527   EmitUint8(operand.encoding_[0] + (reg_or_opcode << 3));
1528   // Emit the rest of the encoded operand.
1529   for (int i = 1; i < length; i++) {
1530     EmitUint8(operand.encoding_[i]);
1531   }
1532 }
1533 
1534 
EmitImmediate(const Immediate & imm)1535 void X86_64Assembler::EmitImmediate(const Immediate& imm) {
1536   if (imm.is_int32()) {
1537     EmitInt32(static_cast<int32_t>(imm.value()));
1538   } else {
1539     EmitInt64(imm.value());
1540   }
1541 }
1542 
1543 
EmitComplex(uint8_t reg_or_opcode,const Operand & operand,const Immediate & immediate)1544 void X86_64Assembler::EmitComplex(uint8_t reg_or_opcode,
1545                                   const Operand& operand,
1546                                   const Immediate& immediate) {
1547   CHECK_GE(reg_or_opcode, 0);
1548   CHECK_LT(reg_or_opcode, 8);
1549   if (immediate.is_int8()) {
1550     // Use sign-extended 8-bit immediate.
1551     EmitUint8(0x83);
1552     EmitOperand(reg_or_opcode, operand);
1553     EmitUint8(immediate.value() & 0xFF);
1554   } else if (operand.IsRegister(CpuRegister(RAX))) {
1555     // Use short form if the destination is eax.
1556     EmitUint8(0x05 + (reg_or_opcode << 3));
1557     EmitImmediate(immediate);
1558   } else {
1559     EmitUint8(0x81);
1560     EmitOperand(reg_or_opcode, operand);
1561     EmitImmediate(immediate);
1562   }
1563 }
1564 
1565 
EmitLabel(Label * label,int instruction_size)1566 void X86_64Assembler::EmitLabel(Label* label, int instruction_size) {
1567   if (label->IsBound()) {
1568     int offset = label->Position() - buffer_.Size();
1569     CHECK_LE(offset, 0);
1570     EmitInt32(offset - instruction_size);
1571   } else {
1572     EmitLabelLink(label);
1573   }
1574 }
1575 
1576 
EmitLabelLink(Label * label)1577 void X86_64Assembler::EmitLabelLink(Label* label) {
1578   CHECK(!label->IsBound());
1579   int position = buffer_.Size();
1580   EmitInt32(label->position_);
1581   label->LinkTo(position);
1582 }
1583 
1584 
EmitGenericShift(bool wide,int reg_or_opcode,CpuRegister reg,const Immediate & imm)1585 void X86_64Assembler::EmitGenericShift(bool wide,
1586                                        int reg_or_opcode,
1587                                        CpuRegister reg,
1588                                        const Immediate& imm) {
1589   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1590   CHECK(imm.is_int8());
1591   if (wide) {
1592     EmitRex64(reg);
1593   }
1594   if (imm.value() == 1) {
1595     EmitUint8(0xD1);
1596     EmitOperand(reg_or_opcode, Operand(reg));
1597   } else {
1598     EmitUint8(0xC1);
1599     EmitOperand(reg_or_opcode, Operand(reg));
1600     EmitUint8(imm.value() & 0xFF);
1601   }
1602 }
1603 
1604 
EmitGenericShift(int reg_or_opcode,CpuRegister operand,CpuRegister shifter)1605 void X86_64Assembler::EmitGenericShift(int reg_or_opcode,
1606                                        CpuRegister operand,
1607                                        CpuRegister shifter) {
1608   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1609   CHECK_EQ(shifter.AsRegister(), RCX);
1610   EmitUint8(0xD3);
1611   EmitOperand(reg_or_opcode, Operand(operand));
1612 }
1613 
EmitOptionalRex(bool force,bool w,bool r,bool x,bool b)1614 void X86_64Assembler::EmitOptionalRex(bool force, bool w, bool r, bool x, bool b) {
1615   // REX.WRXB
1616   // W - 64-bit operand
1617   // R - MODRM.reg
1618   // X - SIB.index
1619   // B - MODRM.rm/SIB.base
1620   uint8_t rex = force ? 0x40 : 0;
1621   if (w) {
1622     rex |= 0x48;  // REX.W000
1623   }
1624   if (r) {
1625     rex |= 0x44;  // REX.0R00
1626   }
1627   if (x) {
1628     rex |= 0x42;  // REX.00X0
1629   }
1630   if (b) {
1631     rex |= 0x41;  // REX.000B
1632   }
1633   if (rex != 0) {
1634     EmitUint8(rex);
1635   }
1636 }
1637 
EmitOptionalRex32(CpuRegister reg)1638 void X86_64Assembler::EmitOptionalRex32(CpuRegister reg) {
1639   EmitOptionalRex(false, false, false, false, reg.NeedsRex());
1640 }
1641 
EmitOptionalRex32(CpuRegister dst,CpuRegister src)1642 void X86_64Assembler::EmitOptionalRex32(CpuRegister dst, CpuRegister src) {
1643   EmitOptionalRex(false, false, dst.NeedsRex(), false, src.NeedsRex());
1644 }
1645 
EmitOptionalRex32(XmmRegister dst,XmmRegister src)1646 void X86_64Assembler::EmitOptionalRex32(XmmRegister dst, XmmRegister src) {
1647   EmitOptionalRex(false, false, dst.NeedsRex(), false, src.NeedsRex());
1648 }
1649 
EmitOptionalRex32(CpuRegister dst,XmmRegister src)1650 void X86_64Assembler::EmitOptionalRex32(CpuRegister dst, XmmRegister src) {
1651   EmitOptionalRex(false, false, dst.NeedsRex(), false, src.NeedsRex());
1652 }
1653 
EmitOptionalRex32(XmmRegister dst,CpuRegister src)1654 void X86_64Assembler::EmitOptionalRex32(XmmRegister dst, CpuRegister src) {
1655   EmitOptionalRex(false, false, dst.NeedsRex(), false, src.NeedsRex());
1656 }
1657 
EmitOptionalRex32(const Operand & operand)1658 void X86_64Assembler::EmitOptionalRex32(const Operand& operand) {
1659   uint8_t rex = operand.rex();
1660   if (rex != 0) {
1661     EmitUint8(rex);
1662   }
1663 }
1664 
EmitOptionalRex32(CpuRegister dst,const Operand & operand)1665 void X86_64Assembler::EmitOptionalRex32(CpuRegister dst, const Operand& operand) {
1666   uint8_t rex = operand.rex();
1667   if (dst.NeedsRex()) {
1668     rex |= 0x44;  // REX.0R00
1669   }
1670   if (rex != 0) {
1671     EmitUint8(rex);
1672   }
1673 }
1674 
EmitOptionalRex32(XmmRegister dst,const Operand & operand)1675 void X86_64Assembler::EmitOptionalRex32(XmmRegister dst, const Operand& operand) {
1676   uint8_t rex = operand.rex();
1677   if (dst.NeedsRex()) {
1678     rex |= 0x44;  // REX.0R00
1679   }
1680   if (rex != 0) {
1681     EmitUint8(rex);
1682   }
1683 }
1684 
EmitRex64(CpuRegister reg)1685 void X86_64Assembler::EmitRex64(CpuRegister reg) {
1686   EmitOptionalRex(false, true, false, false, reg.NeedsRex());
1687 }
1688 
EmitRex64(CpuRegister dst,CpuRegister src)1689 void X86_64Assembler::EmitRex64(CpuRegister dst, CpuRegister src) {
1690   EmitOptionalRex(false, true, dst.NeedsRex(), false, src.NeedsRex());
1691 }
1692 
EmitRex64(CpuRegister dst,const Operand & operand)1693 void X86_64Assembler::EmitRex64(CpuRegister dst, const Operand& operand) {
1694   uint8_t rex = 0x48 | operand.rex();  // REX.W000
1695   if (dst.NeedsRex()) {
1696     rex |= 0x44;  // REX.0R00
1697   }
1698   if (rex != 0) {
1699     EmitUint8(rex);
1700   }
1701 }
1702 
EmitOptionalByteRegNormalizingRex32(CpuRegister dst,CpuRegister src)1703 void X86_64Assembler::EmitOptionalByteRegNormalizingRex32(CpuRegister dst, CpuRegister src) {
1704   EmitOptionalRex(true, false, dst.NeedsRex(), false, src.NeedsRex());
1705 }
1706 
EmitOptionalByteRegNormalizingRex32(CpuRegister dst,const Operand & operand)1707 void X86_64Assembler::EmitOptionalByteRegNormalizingRex32(CpuRegister dst, const Operand& operand) {
1708   uint8_t rex = 0x40 | operand.rex();  // REX.0000
1709   if (dst.NeedsRex()) {
1710     rex |= 0x44;  // REX.0R00
1711   }
1712   if (rex != 0) {
1713     EmitUint8(rex);
1714   }
1715 }
1716 
1717 constexpr size_t kFramePointerSize = 8;
1718 
BuildFrame(size_t frame_size,ManagedRegister method_reg,const std::vector<ManagedRegister> & spill_regs,const ManagedRegisterEntrySpills & entry_spills)1719 void X86_64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
1720                                  const std::vector<ManagedRegister>& spill_regs,
1721                                  const ManagedRegisterEntrySpills& entry_spills) {
1722   CHECK_ALIGNED(frame_size, kStackAlignment);
1723   int gpr_count = 0;
1724   for (int i = spill_regs.size() - 1; i >= 0; --i) {
1725     x86_64::X86_64ManagedRegister spill = spill_regs.at(i).AsX86_64();
1726     if (spill.IsCpuRegister()) {
1727       pushq(spill.AsCpuRegister());
1728       gpr_count++;
1729     }
1730   }
1731   // return address then method on stack
1732   int64_t rest_of_frame = static_cast<int64_t>(frame_size)
1733                           - (gpr_count * kFramePointerSize)
1734                           - kFramePointerSize /*return address*/;
1735   subq(CpuRegister(RSP), Immediate(rest_of_frame));
1736   // spill xmms
1737   int64_t offset = rest_of_frame;
1738   for (int i = spill_regs.size() - 1; i >= 0; --i) {
1739     x86_64::X86_64ManagedRegister spill = spill_regs.at(i).AsX86_64();
1740     if (spill.IsXmmRegister()) {
1741       offset -= sizeof(double);
1742       movsd(Address(CpuRegister(RSP), offset), spill.AsXmmRegister());
1743     }
1744   }
1745 
1746   DCHECK_EQ(4U, sizeof(StackReference<mirror::ArtMethod>));
1747 
1748   movl(Address(CpuRegister(RSP), 0), method_reg.AsX86_64().AsCpuRegister());
1749 
1750   for (size_t i = 0; i < entry_spills.size(); ++i) {
1751     ManagedRegisterSpill spill = entry_spills.at(i);
1752     if (spill.AsX86_64().IsCpuRegister()) {
1753       if (spill.getSize() == 8) {
1754         movq(Address(CpuRegister(RSP), frame_size + spill.getSpillOffset()),
1755              spill.AsX86_64().AsCpuRegister());
1756       } else {
1757         CHECK_EQ(spill.getSize(), 4);
1758         movl(Address(CpuRegister(RSP), frame_size + spill.getSpillOffset()), spill.AsX86_64().AsCpuRegister());
1759       }
1760     } else {
1761       if (spill.getSize() == 8) {
1762         movsd(Address(CpuRegister(RSP), frame_size + spill.getSpillOffset()), spill.AsX86_64().AsXmmRegister());
1763       } else {
1764         CHECK_EQ(spill.getSize(), 4);
1765         movss(Address(CpuRegister(RSP), frame_size + spill.getSpillOffset()), spill.AsX86_64().AsXmmRegister());
1766       }
1767     }
1768   }
1769 }
1770 
RemoveFrame(size_t frame_size,const std::vector<ManagedRegister> & spill_regs)1771 void X86_64Assembler::RemoveFrame(size_t frame_size,
1772                             const std::vector<ManagedRegister>& spill_regs) {
1773   CHECK_ALIGNED(frame_size, kStackAlignment);
1774   int gpr_count = 0;
1775   // unspill xmms
1776   int64_t offset = static_cast<int64_t>(frame_size) - (spill_regs.size() * kFramePointerSize) - 2 * kFramePointerSize;
1777   for (size_t i = 0; i < spill_regs.size(); ++i) {
1778     x86_64::X86_64ManagedRegister spill = spill_regs.at(i).AsX86_64();
1779     if (spill.IsXmmRegister()) {
1780       offset += sizeof(double);
1781       movsd(spill.AsXmmRegister(), Address(CpuRegister(RSP), offset));
1782     } else {
1783       gpr_count++;
1784     }
1785   }
1786   addq(CpuRegister(RSP), Immediate(static_cast<int64_t>(frame_size) - (gpr_count * kFramePointerSize) - kFramePointerSize));
1787   for (size_t i = 0; i < spill_regs.size(); ++i) {
1788     x86_64::X86_64ManagedRegister spill = spill_regs.at(i).AsX86_64();
1789     if (spill.IsCpuRegister()) {
1790       popq(spill.AsCpuRegister());
1791     }
1792   }
1793   ret();
1794 }
1795 
IncreaseFrameSize(size_t adjust)1796 void X86_64Assembler::IncreaseFrameSize(size_t adjust) {
1797   CHECK_ALIGNED(adjust, kStackAlignment);
1798   addq(CpuRegister(RSP), Immediate(-static_cast<int64_t>(adjust)));
1799 }
1800 
DecreaseFrameSize(size_t adjust)1801 void X86_64Assembler::DecreaseFrameSize(size_t adjust) {
1802   CHECK_ALIGNED(adjust, kStackAlignment);
1803   addq(CpuRegister(RSP), Immediate(adjust));
1804 }
1805 
Store(FrameOffset offs,ManagedRegister msrc,size_t size)1806 void X86_64Assembler::Store(FrameOffset offs, ManagedRegister msrc, size_t size) {
1807   X86_64ManagedRegister src = msrc.AsX86_64();
1808   if (src.IsNoRegister()) {
1809     CHECK_EQ(0u, size);
1810   } else if (src.IsCpuRegister()) {
1811     if (size == 4) {
1812       CHECK_EQ(4u, size);
1813       movl(Address(CpuRegister(RSP), offs), src.AsCpuRegister());
1814     } else {
1815       CHECK_EQ(8u, size);
1816       movq(Address(CpuRegister(RSP), offs), src.AsCpuRegister());
1817     }
1818   } else if (src.IsRegisterPair()) {
1819     CHECK_EQ(0u, size);
1820     movq(Address(CpuRegister(RSP), offs), src.AsRegisterPairLow());
1821     movq(Address(CpuRegister(RSP), FrameOffset(offs.Int32Value()+4)),
1822          src.AsRegisterPairHigh());
1823   } else if (src.IsX87Register()) {
1824     if (size == 4) {
1825       fstps(Address(CpuRegister(RSP), offs));
1826     } else {
1827       fstpl(Address(CpuRegister(RSP), offs));
1828     }
1829   } else {
1830     CHECK(src.IsXmmRegister());
1831     if (size == 4) {
1832       movss(Address(CpuRegister(RSP), offs), src.AsXmmRegister());
1833     } else {
1834       movsd(Address(CpuRegister(RSP), offs), src.AsXmmRegister());
1835     }
1836   }
1837 }
1838 
StoreRef(FrameOffset dest,ManagedRegister msrc)1839 void X86_64Assembler::StoreRef(FrameOffset dest, ManagedRegister msrc) {
1840   X86_64ManagedRegister src = msrc.AsX86_64();
1841   CHECK(src.IsCpuRegister());
1842   movl(Address(CpuRegister(RSP), dest), src.AsCpuRegister());
1843 }
1844 
StoreRawPtr(FrameOffset dest,ManagedRegister msrc)1845 void X86_64Assembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) {
1846   X86_64ManagedRegister src = msrc.AsX86_64();
1847   CHECK(src.IsCpuRegister());
1848   movq(Address(CpuRegister(RSP), dest), src.AsCpuRegister());
1849 }
1850 
StoreImmediateToFrame(FrameOffset dest,uint32_t imm,ManagedRegister)1851 void X86_64Assembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
1852                                             ManagedRegister) {
1853   movl(Address(CpuRegister(RSP), dest), Immediate(imm));  // TODO(64) movq?
1854 }
1855 
StoreImmediateToThread64(ThreadOffset<8> dest,uint32_t imm,ManagedRegister)1856 void X86_64Assembler::StoreImmediateToThread64(ThreadOffset<8> dest, uint32_t imm,
1857                                                ManagedRegister) {
1858   gs()->movl(Address::Absolute(dest, true), Immediate(imm));  // TODO(64) movq?
1859 }
1860 
StoreStackOffsetToThread64(ThreadOffset<8> thr_offs,FrameOffset fr_offs,ManagedRegister mscratch)1861 void X86_64Assembler::StoreStackOffsetToThread64(ThreadOffset<8> thr_offs,
1862                                                  FrameOffset fr_offs,
1863                                                  ManagedRegister mscratch) {
1864   X86_64ManagedRegister scratch = mscratch.AsX86_64();
1865   CHECK(scratch.IsCpuRegister());
1866   leaq(scratch.AsCpuRegister(), Address(CpuRegister(RSP), fr_offs));
1867   gs()->movq(Address::Absolute(thr_offs, true), scratch.AsCpuRegister());
1868 }
1869 
StoreStackPointerToThread64(ThreadOffset<8> thr_offs)1870 void X86_64Assembler::StoreStackPointerToThread64(ThreadOffset<8> thr_offs) {
1871   gs()->movq(Address::Absolute(thr_offs, true), CpuRegister(RSP));
1872 }
1873 
StoreSpanning(FrameOffset,ManagedRegister,FrameOffset,ManagedRegister)1874 void X86_64Assembler::StoreSpanning(FrameOffset /*dst*/, ManagedRegister /*src*/,
1875                                  FrameOffset /*in_off*/, ManagedRegister /*scratch*/) {
1876   UNIMPLEMENTED(FATAL);  // this case only currently exists for ARM
1877 }
1878 
Load(ManagedRegister mdest,FrameOffset src,size_t size)1879 void X86_64Assembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) {
1880   X86_64ManagedRegister dest = mdest.AsX86_64();
1881   if (dest.IsNoRegister()) {
1882     CHECK_EQ(0u, size);
1883   } else if (dest.IsCpuRegister()) {
1884     if (size == 4) {
1885       CHECK_EQ(4u, size);
1886       movl(dest.AsCpuRegister(), Address(CpuRegister(RSP), src));
1887     } else {
1888       CHECK_EQ(8u, size);
1889       movq(dest.AsCpuRegister(), Address(CpuRegister(RSP), src));
1890     }
1891   } else if (dest.IsRegisterPair()) {
1892     CHECK_EQ(0u, size);
1893     movq(dest.AsRegisterPairLow(), Address(CpuRegister(RSP), src));
1894     movq(dest.AsRegisterPairHigh(), Address(CpuRegister(RSP), FrameOffset(src.Int32Value()+4)));
1895   } else if (dest.IsX87Register()) {
1896     if (size == 4) {
1897       flds(Address(CpuRegister(RSP), src));
1898     } else {
1899       fldl(Address(CpuRegister(RSP), src));
1900     }
1901   } else {
1902     CHECK(dest.IsXmmRegister());
1903     if (size == 4) {
1904       movss(dest.AsXmmRegister(), Address(CpuRegister(RSP), src));
1905     } else {
1906       movsd(dest.AsXmmRegister(), Address(CpuRegister(RSP), src));
1907     }
1908   }
1909 }
1910 
LoadFromThread64(ManagedRegister mdest,ThreadOffset<8> src,size_t size)1911 void X86_64Assembler::LoadFromThread64(ManagedRegister mdest, ThreadOffset<8> src, size_t size) {
1912   X86_64ManagedRegister dest = mdest.AsX86_64();
1913   if (dest.IsNoRegister()) {
1914     CHECK_EQ(0u, size);
1915   } else if (dest.IsCpuRegister()) {
1916     CHECK_EQ(4u, size);
1917     gs()->movl(dest.AsCpuRegister(), Address::Absolute(src, true));
1918   } else if (dest.IsRegisterPair()) {
1919     CHECK_EQ(8u, size);
1920     gs()->movq(dest.AsRegisterPairLow(), Address::Absolute(src, true));
1921   } else if (dest.IsX87Register()) {
1922     if (size == 4) {
1923       gs()->flds(Address::Absolute(src, true));
1924     } else {
1925       gs()->fldl(Address::Absolute(src, true));
1926     }
1927   } else {
1928     CHECK(dest.IsXmmRegister());
1929     if (size == 4) {
1930       gs()->movss(dest.AsXmmRegister(), Address::Absolute(src, true));
1931     } else {
1932       gs()->movsd(dest.AsXmmRegister(), Address::Absolute(src, true));
1933     }
1934   }
1935 }
1936 
LoadRef(ManagedRegister mdest,FrameOffset src)1937 void X86_64Assembler::LoadRef(ManagedRegister mdest, FrameOffset  src) {
1938   X86_64ManagedRegister dest = mdest.AsX86_64();
1939   CHECK(dest.IsCpuRegister());
1940   movq(dest.AsCpuRegister(), Address(CpuRegister(RSP), src));
1941 }
1942 
LoadRef(ManagedRegister mdest,ManagedRegister base,MemberOffset offs)1943 void X86_64Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base,
1944                            MemberOffset offs) {
1945   X86_64ManagedRegister dest = mdest.AsX86_64();
1946   CHECK(dest.IsCpuRegister() && dest.IsCpuRegister());
1947   movq(dest.AsCpuRegister(), Address(base.AsX86_64().AsCpuRegister(), offs));
1948 }
1949 
LoadRawPtr(ManagedRegister mdest,ManagedRegister base,Offset offs)1950 void X86_64Assembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base,
1951                               Offset offs) {
1952   X86_64ManagedRegister dest = mdest.AsX86_64();
1953   CHECK(dest.IsCpuRegister() && dest.IsCpuRegister());
1954   movq(dest.AsCpuRegister(), Address(base.AsX86_64().AsCpuRegister(), offs));
1955 }
1956 
LoadRawPtrFromThread64(ManagedRegister mdest,ThreadOffset<8> offs)1957 void X86_64Assembler::LoadRawPtrFromThread64(ManagedRegister mdest, ThreadOffset<8> offs) {
1958   X86_64ManagedRegister dest = mdest.AsX86_64();
1959   CHECK(dest.IsCpuRegister());
1960   gs()->movq(dest.AsCpuRegister(), Address::Absolute(offs, true));
1961 }
1962 
SignExtend(ManagedRegister mreg,size_t size)1963 void X86_64Assembler::SignExtend(ManagedRegister mreg, size_t size) {
1964   X86_64ManagedRegister reg = mreg.AsX86_64();
1965   CHECK(size == 1 || size == 2) << size;
1966   CHECK(reg.IsCpuRegister()) << reg;
1967   if (size == 1) {
1968     movsxb(reg.AsCpuRegister(), reg.AsCpuRegister());
1969   } else {
1970     movsxw(reg.AsCpuRegister(), reg.AsCpuRegister());
1971   }
1972 }
1973 
ZeroExtend(ManagedRegister mreg,size_t size)1974 void X86_64Assembler::ZeroExtend(ManagedRegister mreg, size_t size) {
1975   X86_64ManagedRegister reg = mreg.AsX86_64();
1976   CHECK(size == 1 || size == 2) << size;
1977   CHECK(reg.IsCpuRegister()) << reg;
1978   if (size == 1) {
1979     movzxb(reg.AsCpuRegister(), reg.AsCpuRegister());
1980   } else {
1981     movzxw(reg.AsCpuRegister(), reg.AsCpuRegister());
1982   }
1983 }
1984 
Move(ManagedRegister mdest,ManagedRegister msrc,size_t size)1985 void X86_64Assembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) {
1986   X86_64ManagedRegister dest = mdest.AsX86_64();
1987   X86_64ManagedRegister src = msrc.AsX86_64();
1988   if (!dest.Equals(src)) {
1989     if (dest.IsCpuRegister() && src.IsCpuRegister()) {
1990       movq(dest.AsCpuRegister(), src.AsCpuRegister());
1991     } else if (src.IsX87Register() && dest.IsXmmRegister()) {
1992       // Pass via stack and pop X87 register
1993       subl(CpuRegister(RSP), Immediate(16));
1994       if (size == 4) {
1995         CHECK_EQ(src.AsX87Register(), ST0);
1996         fstps(Address(CpuRegister(RSP), 0));
1997         movss(dest.AsXmmRegister(), Address(CpuRegister(RSP), 0));
1998       } else {
1999         CHECK_EQ(src.AsX87Register(), ST0);
2000         fstpl(Address(CpuRegister(RSP), 0));
2001         movsd(dest.AsXmmRegister(), Address(CpuRegister(RSP), 0));
2002       }
2003       addq(CpuRegister(RSP), Immediate(16));
2004     } else {
2005       // TODO: x87, SSE
2006       UNIMPLEMENTED(FATAL) << ": Move " << dest << ", " << src;
2007     }
2008   }
2009 }
2010 
CopyRef(FrameOffset dest,FrameOffset src,ManagedRegister mscratch)2011 void X86_64Assembler::CopyRef(FrameOffset dest, FrameOffset src,
2012                            ManagedRegister mscratch) {
2013   X86_64ManagedRegister scratch = mscratch.AsX86_64();
2014   CHECK(scratch.IsCpuRegister());
2015   movl(scratch.AsCpuRegister(), Address(CpuRegister(RSP), src));
2016   movl(Address(CpuRegister(RSP), dest), scratch.AsCpuRegister());
2017 }
2018 
CopyRawPtrFromThread64(FrameOffset fr_offs,ThreadOffset<8> thr_offs,ManagedRegister mscratch)2019 void X86_64Assembler::CopyRawPtrFromThread64(FrameOffset fr_offs,
2020                                              ThreadOffset<8> thr_offs,
2021                                              ManagedRegister mscratch) {
2022   X86_64ManagedRegister scratch = mscratch.AsX86_64();
2023   CHECK(scratch.IsCpuRegister());
2024   gs()->movq(scratch.AsCpuRegister(), Address::Absolute(thr_offs, true));
2025   Store(fr_offs, scratch, 8);
2026 }
2027 
CopyRawPtrToThread64(ThreadOffset<8> thr_offs,FrameOffset fr_offs,ManagedRegister mscratch)2028 void X86_64Assembler::CopyRawPtrToThread64(ThreadOffset<8> thr_offs,
2029                                            FrameOffset fr_offs,
2030                                            ManagedRegister mscratch) {
2031   X86_64ManagedRegister scratch = mscratch.AsX86_64();
2032   CHECK(scratch.IsCpuRegister());
2033   Load(scratch, fr_offs, 8);
2034   gs()->movq(Address::Absolute(thr_offs, true), scratch.AsCpuRegister());
2035 }
2036 
Copy(FrameOffset dest,FrameOffset src,ManagedRegister mscratch,size_t size)2037 void X86_64Assembler::Copy(FrameOffset dest, FrameOffset src,
2038                         ManagedRegister mscratch,
2039                         size_t size) {
2040   X86_64ManagedRegister scratch = mscratch.AsX86_64();
2041   if (scratch.IsCpuRegister() && size == 8) {
2042     Load(scratch, src, 4);
2043     Store(dest, scratch, 4);
2044     Load(scratch, FrameOffset(src.Int32Value() + 4), 4);
2045     Store(FrameOffset(dest.Int32Value() + 4), scratch, 4);
2046   } else {
2047     Load(scratch, src, size);
2048     Store(dest, scratch, size);
2049   }
2050 }
2051 
Copy(FrameOffset,ManagedRegister,Offset,ManagedRegister,size_t)2052 void X86_64Assembler::Copy(FrameOffset /*dst*/, ManagedRegister /*src_base*/, Offset /*src_offset*/,
2053                         ManagedRegister /*scratch*/, size_t /*size*/) {
2054   UNIMPLEMENTED(FATAL);
2055 }
2056 
Copy(ManagedRegister dest_base,Offset dest_offset,FrameOffset src,ManagedRegister scratch,size_t size)2057 void X86_64Assembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
2058                         ManagedRegister scratch, size_t size) {
2059   CHECK(scratch.IsNoRegister());
2060   CHECK_EQ(size, 4u);
2061   pushq(Address(CpuRegister(RSP), src));
2062   popq(Address(dest_base.AsX86_64().AsCpuRegister(), dest_offset));
2063 }
2064 
Copy(FrameOffset dest,FrameOffset src_base,Offset src_offset,ManagedRegister mscratch,size_t size)2065 void X86_64Assembler::Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset,
2066                         ManagedRegister mscratch, size_t size) {
2067   CpuRegister scratch = mscratch.AsX86_64().AsCpuRegister();
2068   CHECK_EQ(size, 4u);
2069   movq(scratch, Address(CpuRegister(RSP), src_base));
2070   movq(scratch, Address(scratch, src_offset));
2071   movq(Address(CpuRegister(RSP), dest), scratch);
2072 }
2073 
Copy(ManagedRegister dest,Offset dest_offset,ManagedRegister src,Offset src_offset,ManagedRegister scratch,size_t size)2074 void X86_64Assembler::Copy(ManagedRegister dest, Offset dest_offset,
2075                         ManagedRegister src, Offset src_offset,
2076                         ManagedRegister scratch, size_t size) {
2077   CHECK_EQ(size, 4u);
2078   CHECK(scratch.IsNoRegister());
2079   pushq(Address(src.AsX86_64().AsCpuRegister(), src_offset));
2080   popq(Address(dest.AsX86_64().AsCpuRegister(), dest_offset));
2081 }
2082 
Copy(FrameOffset dest,Offset dest_offset,FrameOffset src,Offset src_offset,ManagedRegister mscratch,size_t size)2083 void X86_64Assembler::Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
2084                         ManagedRegister mscratch, size_t size) {
2085   CpuRegister scratch = mscratch.AsX86_64().AsCpuRegister();
2086   CHECK_EQ(size, 4u);
2087   CHECK_EQ(dest.Int32Value(), src.Int32Value());
2088   movq(scratch, Address(CpuRegister(RSP), src));
2089   pushq(Address(scratch, src_offset));
2090   popq(Address(scratch, dest_offset));
2091 }
2092 
MemoryBarrier(ManagedRegister)2093 void X86_64Assembler::MemoryBarrier(ManagedRegister) {
2094 #if ANDROID_SMP != 0
2095   mfence();
2096 #endif
2097 }
2098 
CreateHandleScopeEntry(ManagedRegister mout_reg,FrameOffset handle_scope_offset,ManagedRegister min_reg,bool null_allowed)2099 void X86_64Assembler::CreateHandleScopeEntry(ManagedRegister mout_reg,
2100                                    FrameOffset handle_scope_offset,
2101                                    ManagedRegister min_reg, bool null_allowed) {
2102   X86_64ManagedRegister out_reg = mout_reg.AsX86_64();
2103   X86_64ManagedRegister in_reg = min_reg.AsX86_64();
2104   if (in_reg.IsNoRegister()) {  // TODO(64): && null_allowed
2105     // Use out_reg as indicator of NULL
2106     in_reg = out_reg;
2107     // TODO: movzwl
2108     movl(in_reg.AsCpuRegister(), Address(CpuRegister(RSP), handle_scope_offset));
2109   }
2110   CHECK(in_reg.IsCpuRegister());
2111   CHECK(out_reg.IsCpuRegister());
2112   VerifyObject(in_reg, null_allowed);
2113   if (null_allowed) {
2114     Label null_arg;
2115     if (!out_reg.Equals(in_reg)) {
2116       xorl(out_reg.AsCpuRegister(), out_reg.AsCpuRegister());
2117     }
2118     testl(in_reg.AsCpuRegister(), in_reg.AsCpuRegister());
2119     j(kZero, &null_arg);
2120     leaq(out_reg.AsCpuRegister(), Address(CpuRegister(RSP), handle_scope_offset));
2121     Bind(&null_arg);
2122   } else {
2123     leaq(out_reg.AsCpuRegister(), Address(CpuRegister(RSP), handle_scope_offset));
2124   }
2125 }
2126 
CreateHandleScopeEntry(FrameOffset out_off,FrameOffset handle_scope_offset,ManagedRegister mscratch,bool null_allowed)2127 void X86_64Assembler::CreateHandleScopeEntry(FrameOffset out_off,
2128                                    FrameOffset handle_scope_offset,
2129                                    ManagedRegister mscratch,
2130                                    bool null_allowed) {
2131   X86_64ManagedRegister scratch = mscratch.AsX86_64();
2132   CHECK(scratch.IsCpuRegister());
2133   if (null_allowed) {
2134     Label null_arg;
2135     movl(scratch.AsCpuRegister(), Address(CpuRegister(RSP), handle_scope_offset));
2136     testl(scratch.AsCpuRegister(), scratch.AsCpuRegister());
2137     j(kZero, &null_arg);
2138     leaq(scratch.AsCpuRegister(), Address(CpuRegister(RSP), handle_scope_offset));
2139     Bind(&null_arg);
2140   } else {
2141     leaq(scratch.AsCpuRegister(), Address(CpuRegister(RSP), handle_scope_offset));
2142   }
2143   Store(out_off, scratch, 8);
2144 }
2145 
2146 // Given a handle scope entry, load the associated reference.
LoadReferenceFromHandleScope(ManagedRegister mout_reg,ManagedRegister min_reg)2147 void X86_64Assembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg,
2148                                          ManagedRegister min_reg) {
2149   X86_64ManagedRegister out_reg = mout_reg.AsX86_64();
2150   X86_64ManagedRegister in_reg = min_reg.AsX86_64();
2151   CHECK(out_reg.IsCpuRegister());
2152   CHECK(in_reg.IsCpuRegister());
2153   Label null_arg;
2154   if (!out_reg.Equals(in_reg)) {
2155     xorl(out_reg.AsCpuRegister(), out_reg.AsCpuRegister());
2156   }
2157   testl(in_reg.AsCpuRegister(), in_reg.AsCpuRegister());
2158   j(kZero, &null_arg);
2159   movq(out_reg.AsCpuRegister(), Address(in_reg.AsCpuRegister(), 0));
2160   Bind(&null_arg);
2161 }
2162 
VerifyObject(ManagedRegister,bool)2163 void X86_64Assembler::VerifyObject(ManagedRegister /*src*/, bool /*could_be_null*/) {
2164   // TODO: not validating references
2165 }
2166 
VerifyObject(FrameOffset,bool)2167 void X86_64Assembler::VerifyObject(FrameOffset /*src*/, bool /*could_be_null*/) {
2168   // TODO: not validating references
2169 }
2170 
Call(ManagedRegister mbase,Offset offset,ManagedRegister)2171 void X86_64Assembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister) {
2172   X86_64ManagedRegister base = mbase.AsX86_64();
2173   CHECK(base.IsCpuRegister());
2174   call(Address(base.AsCpuRegister(), offset.Int32Value()));
2175   // TODO: place reference map on call
2176 }
2177 
Call(FrameOffset base,Offset offset,ManagedRegister mscratch)2178 void X86_64Assembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
2179   CpuRegister scratch = mscratch.AsX86_64().AsCpuRegister();
2180   movl(scratch, Address(CpuRegister(RSP), base));
2181   call(Address(scratch, offset));
2182 }
2183 
CallFromThread64(ThreadOffset<8> offset,ManagedRegister)2184 void X86_64Assembler::CallFromThread64(ThreadOffset<8> offset, ManagedRegister /*mscratch*/) {
2185   gs()->call(Address::Absolute(offset, true));
2186 }
2187 
GetCurrentThread(ManagedRegister tr)2188 void X86_64Assembler::GetCurrentThread(ManagedRegister tr) {
2189   gs()->movq(tr.AsX86_64().AsCpuRegister(), Address::Absolute(Thread::SelfOffset<8>(), true));
2190 }
2191 
GetCurrentThread(FrameOffset offset,ManagedRegister mscratch)2192 void X86_64Assembler::GetCurrentThread(FrameOffset offset, ManagedRegister mscratch) {
2193   X86_64ManagedRegister scratch = mscratch.AsX86_64();
2194   gs()->movq(scratch.AsCpuRegister(), Address::Absolute(Thread::SelfOffset<8>(), true));
2195   movq(Address(CpuRegister(RSP), offset), scratch.AsCpuRegister());
2196 }
2197 
2198 // Slowpath entered when Thread::Current()->_exception is non-null
2199 class X86_64ExceptionSlowPath FINAL : public SlowPath {
2200  public:
X86_64ExceptionSlowPath(size_t stack_adjust)2201   explicit X86_64ExceptionSlowPath(size_t stack_adjust) : stack_adjust_(stack_adjust) {}
2202   virtual void Emit(Assembler *sp_asm) OVERRIDE;
2203  private:
2204   const size_t stack_adjust_;
2205 };
2206 
ExceptionPoll(ManagedRegister,size_t stack_adjust)2207 void X86_64Assembler::ExceptionPoll(ManagedRegister /*scratch*/, size_t stack_adjust) {
2208   X86_64ExceptionSlowPath* slow = new X86_64ExceptionSlowPath(stack_adjust);
2209   buffer_.EnqueueSlowPath(slow);
2210   gs()->cmpl(Address::Absolute(Thread::ExceptionOffset<8>(), true), Immediate(0));
2211   j(kNotEqual, slow->Entry());
2212 }
2213 
Emit(Assembler * sasm)2214 void X86_64ExceptionSlowPath::Emit(Assembler *sasm) {
2215   X86_64Assembler* sp_asm = down_cast<X86_64Assembler*>(sasm);
2216 #define __ sp_asm->
2217   __ Bind(&entry_);
2218   // Note: the return value is dead
2219   if (stack_adjust_ != 0) {  // Fix up the frame.
2220     __ DecreaseFrameSize(stack_adjust_);
2221   }
2222   // Pass exception as argument in RDI
2223   __ gs()->movq(CpuRegister(RDI), Address::Absolute(Thread::ExceptionOffset<8>(), true));
2224   __ gs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(8, pDeliverException), true));
2225   // this call should never return
2226   __ int3();
2227 #undef __
2228 }
2229 
2230 }  // namespace x86_64
2231 }  // namespace art
2232 
2233