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 #ifndef ART_COMPILER_UTILS_X86_64_ASSEMBLER_X86_64_H_
18 #define ART_COMPILER_UTILS_X86_64_ASSEMBLER_X86_64_H_
19 
20 #include <vector>
21 
22 #include "base/bit_utils.h"
23 #include "base/macros.h"
24 #include "constants_x86_64.h"
25 #include "globals.h"
26 #include "managed_register_x86_64.h"
27 #include "offsets.h"
28 #include "utils/assembler.h"
29 
30 namespace art {
31 namespace x86_64 {
32 
33 // Encodes an immediate value for operands.
34 //
35 // Note: Immediates can be 64b on x86-64 for certain instructions, but are often restricted
36 // to 32b.
37 //
38 // Note: As we support cross-compilation, the value type must be int64_t. Please be aware of
39 // conversion rules in expressions regarding negation, especially size_t on 32b.
40 class Immediate : public ValueObject {
41  public:
Immediate(int64_t value_in)42   explicit Immediate(int64_t value_in) : value_(value_in) {}
43 
value()44   int64_t value() const { return value_; }
45 
is_int8()46   bool is_int8() const { return IsInt<8>(value_); }
is_uint8()47   bool is_uint8() const { return IsUint<8>(value_); }
is_int16()48   bool is_int16() const { return IsInt<16>(value_); }
is_uint16()49   bool is_uint16() const { return IsUint<16>(value_); }
is_int32()50   bool is_int32() const { return IsInt<32>(value_); }
51 
52  private:
53   const int64_t value_;
54 };
55 
56 
57 class Operand : public ValueObject {
58  public:
mod()59   uint8_t mod() const {
60     return (encoding_at(0) >> 6) & 3;
61   }
62 
rm()63   Register rm() const {
64     return static_cast<Register>(encoding_at(0) & 7);
65   }
66 
scale()67   ScaleFactor scale() const {
68     return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
69   }
70 
index()71   Register index() const {
72     return static_cast<Register>((encoding_at(1) >> 3) & 7);
73   }
74 
base()75   Register base() const {
76     return static_cast<Register>(encoding_at(1) & 7);
77   }
78 
rex()79   uint8_t rex() const {
80     return rex_;
81   }
82 
disp8()83   int8_t disp8() const {
84     CHECK_GE(length_, 2);
85     return static_cast<int8_t>(encoding_[length_ - 1]);
86   }
87 
disp32()88   int32_t disp32() const {
89     CHECK_GE(length_, 5);
90     int32_t value;
91     memcpy(&value, &encoding_[length_ - 4], sizeof(value));
92     return value;
93   }
94 
IsRegister(CpuRegister reg)95   bool IsRegister(CpuRegister reg) const {
96     return ((encoding_[0] & 0xF8) == 0xC0)  // Addressing mode is register only.
97         && ((encoding_[0] & 0x07) == reg.LowBits())  // Register codes match.
98         && (reg.NeedsRex() == ((rex_ & 1) != 0));  // REX.000B bits match.
99   }
100 
GetFixup()101   AssemblerFixup* GetFixup() const {
102     return fixup_;
103   }
104 
105  protected:
106   // Operand can be sub classed (e.g: Address).
Operand()107   Operand() : rex_(0), length_(0), fixup_(nullptr) { }
108 
SetModRM(uint8_t mod_in,CpuRegister rm_in)109   void SetModRM(uint8_t mod_in, CpuRegister rm_in) {
110     CHECK_EQ(mod_in & ~3, 0);
111     if (rm_in.NeedsRex()) {
112       rex_ |= 0x41;  // REX.000B
113     }
114     encoding_[0] = (mod_in << 6) | rm_in.LowBits();
115     length_ = 1;
116   }
117 
SetSIB(ScaleFactor scale_in,CpuRegister index_in,CpuRegister base_in)118   void SetSIB(ScaleFactor scale_in, CpuRegister index_in, CpuRegister base_in) {
119     CHECK_EQ(length_, 1);
120     CHECK_EQ(scale_in & ~3, 0);
121     if (base_in.NeedsRex()) {
122       rex_ |= 0x41;  // REX.000B
123     }
124     if (index_in.NeedsRex()) {
125       rex_ |= 0x42;  // REX.00X0
126     }
127     encoding_[1] = (scale_in << 6) | (static_cast<uint8_t>(index_in.LowBits()) << 3) |
128         static_cast<uint8_t>(base_in.LowBits());
129     length_ = 2;
130   }
131 
SetDisp8(int8_t disp)132   void SetDisp8(int8_t disp) {
133     CHECK(length_ == 1 || length_ == 2);
134     encoding_[length_++] = static_cast<uint8_t>(disp);
135   }
136 
SetDisp32(int32_t disp)137   void SetDisp32(int32_t disp) {
138     CHECK(length_ == 1 || length_ == 2);
139     int disp_size = sizeof(disp);
140     memmove(&encoding_[length_], &disp, disp_size);
141     length_ += disp_size;
142   }
143 
SetFixup(AssemblerFixup * fixup)144   void SetFixup(AssemblerFixup* fixup) {
145     fixup_ = fixup;
146   }
147 
148  private:
149   uint8_t rex_;
150   uint8_t length_;
151   uint8_t encoding_[6];
152   AssemblerFixup* fixup_;
153 
Operand(CpuRegister reg)154   explicit Operand(CpuRegister reg) : rex_(0), length_(0), fixup_(nullptr) { SetModRM(3, reg); }
155 
156   // Get the operand encoding byte at the given index.
encoding_at(int index_in)157   uint8_t encoding_at(int index_in) const {
158     CHECK_GE(index_in, 0);
159     CHECK_LT(index_in, length_);
160     return encoding_[index_in];
161   }
162 
163   friend class X86_64Assembler;
164 };
165 
166 
167 class Address : public Operand {
168  public:
Address(CpuRegister base_in,int32_t disp)169   Address(CpuRegister base_in, int32_t disp) {
170     Init(base_in, disp);
171   }
172 
Address(CpuRegister base_in,Offset disp)173   Address(CpuRegister base_in, Offset disp) {
174     Init(base_in, disp.Int32Value());
175   }
176 
Address(CpuRegister base_in,FrameOffset disp)177   Address(CpuRegister base_in, FrameOffset disp) {
178     CHECK_EQ(base_in.AsRegister(), RSP);
179     Init(CpuRegister(RSP), disp.Int32Value());
180   }
181 
Address(CpuRegister base_in,MemberOffset disp)182   Address(CpuRegister base_in, MemberOffset disp) {
183     Init(base_in, disp.Int32Value());
184   }
185 
Init(CpuRegister base_in,int32_t disp)186   void Init(CpuRegister base_in, int32_t disp) {
187     if (disp == 0 && base_in.LowBits() != RBP) {
188       SetModRM(0, base_in);
189       if (base_in.LowBits() == RSP) {
190         SetSIB(TIMES_1, CpuRegister(RSP), base_in);
191       }
192     } else if (disp >= -128 && disp <= 127) {
193       SetModRM(1, base_in);
194       if (base_in.LowBits() == RSP) {
195         SetSIB(TIMES_1, CpuRegister(RSP), base_in);
196       }
197       SetDisp8(disp);
198     } else {
199       SetModRM(2, base_in);
200       if (base_in.LowBits() == RSP) {
201         SetSIB(TIMES_1, CpuRegister(RSP), base_in);
202       }
203       SetDisp32(disp);
204     }
205   }
206 
207 
Address(CpuRegister index_in,ScaleFactor scale_in,int32_t disp)208   Address(CpuRegister index_in, ScaleFactor scale_in, int32_t disp) {
209     CHECK_NE(index_in.AsRegister(), RSP);  // Illegal addressing mode.
210     SetModRM(0, CpuRegister(RSP));
211     SetSIB(scale_in, index_in, CpuRegister(RBP));
212     SetDisp32(disp);
213   }
214 
Address(CpuRegister base_in,CpuRegister index_in,ScaleFactor scale_in,int32_t disp)215   Address(CpuRegister base_in, CpuRegister index_in, ScaleFactor scale_in, int32_t disp) {
216     CHECK_NE(index_in.AsRegister(), RSP);  // Illegal addressing mode.
217     if (disp == 0 && base_in.LowBits() != RBP) {
218       SetModRM(0, CpuRegister(RSP));
219       SetSIB(scale_in, index_in, base_in);
220     } else if (disp >= -128 && disp <= 127) {
221       SetModRM(1, CpuRegister(RSP));
222       SetSIB(scale_in, index_in, base_in);
223       SetDisp8(disp);
224     } else {
225       SetModRM(2, CpuRegister(RSP));
226       SetSIB(scale_in, index_in, base_in);
227       SetDisp32(disp);
228     }
229   }
230 
231   // If no_rip is true then the Absolute address isn't RIP relative.
232   static Address Absolute(uintptr_t addr, bool no_rip = false) {
233     Address result;
234     if (no_rip) {
235       result.SetModRM(0, CpuRegister(RSP));
236       result.SetSIB(TIMES_1, CpuRegister(RSP), CpuRegister(RBP));
237       result.SetDisp32(addr);
238     } else {
239       // RIP addressing is done using RBP as the base register.
240       // The value in RBP isn't used.  Instead the offset is added to RIP.
241       result.SetModRM(0, CpuRegister(RBP));
242       result.SetDisp32(addr);
243     }
244     return result;
245   }
246 
247   // An RIP relative address that will be fixed up later.
RIP(AssemblerFixup * fixup)248   static Address RIP(AssemblerFixup* fixup) {
249     Address result;
250     // RIP addressing is done using RBP as the base register.
251     // The value in RBP isn't used.  Instead the offset is added to RIP.
252     result.SetModRM(0, CpuRegister(RBP));
253     result.SetDisp32(0);
254     result.SetFixup(fixup);
255     return result;
256   }
257 
258   // If no_rip is true then the Absolute address isn't RIP relative.
259   static Address Absolute(ThreadOffset<8> addr, bool no_rip = false) {
260     return Absolute(addr.Int32Value(), no_rip);
261   }
262 
263  private:
Address()264   Address() {}
265 };
266 
267 
268 /**
269  * Class to handle constant area values.
270  */
271 class ConstantArea {
272   public:
ConstantArea()273     ConstantArea() {}
274 
275     // Add a double to the constant area, returning the offset into
276     // the constant area where the literal resides.
277     int AddDouble(double v);
278 
279     // Add a float to the constant area, returning the offset into
280     // the constant area where the literal resides.
281     int AddFloat(float v);
282 
283     // Add an int32_t to the constant area, returning the offset into
284     // the constant area where the literal resides.
285     int AddInt32(int32_t v);
286 
287     // Add an int64_t to the constant area, returning the offset into
288     // the constant area where the literal resides.
289     int AddInt64(int64_t v);
290 
GetSize()291     int GetSize() const {
292       return buffer_.size() * elem_size_;
293     }
294 
GetBuffer()295     const std::vector<int32_t>& GetBuffer() const {
296       return buffer_;
297     }
298 
299   private:
300     static constexpr size_t elem_size_ = sizeof(int32_t);
301     std::vector<int32_t> buffer_;
302 };
303 
304 
305 class X86_64Assembler FINAL : public Assembler {
306  public:
X86_64Assembler()307   X86_64Assembler() {}
~X86_64Assembler()308   virtual ~X86_64Assembler() {}
309 
310   /*
311    * Emit Machine Instructions.
312    */
313   void call(CpuRegister reg);
314   void call(const Address& address);
315   void call(Label* label);
316 
317   void pushq(CpuRegister reg);
318   void pushq(const Address& address);
319   void pushq(const Immediate& imm);
320 
321   void popq(CpuRegister reg);
322   void popq(const Address& address);
323 
324   void movq(CpuRegister dst, const Immediate& src);
325   void movl(CpuRegister dst, const Immediate& src);
326   void movq(CpuRegister dst, CpuRegister src);
327   void movl(CpuRegister dst, CpuRegister src);
328 
329   void movq(CpuRegister dst, const Address& src);
330   void movl(CpuRegister dst, const Address& src);
331   void movq(const Address& dst, CpuRegister src);
332   void movq(const Address& dst, const Immediate& src);
333   void movl(const Address& dst, CpuRegister src);
334   void movl(const Address& dst, const Immediate& imm);
335 
336   void cmov(Condition c, CpuRegister dst, CpuRegister src);  // This is the 64b version.
337   void cmov(Condition c, CpuRegister dst, CpuRegister src, bool is64bit);
338 
339   void movzxb(CpuRegister dst, CpuRegister src);
340   void movzxb(CpuRegister dst, const Address& src);
341   void movsxb(CpuRegister dst, CpuRegister src);
342   void movsxb(CpuRegister dst, const Address& src);
343   void movb(CpuRegister dst, const Address& src);
344   void movb(const Address& dst, CpuRegister src);
345   void movb(const Address& dst, const Immediate& imm);
346 
347   void movzxw(CpuRegister dst, CpuRegister src);
348   void movzxw(CpuRegister dst, const Address& src);
349   void movsxw(CpuRegister dst, CpuRegister src);
350   void movsxw(CpuRegister dst, const Address& src);
351   void movw(CpuRegister dst, const Address& src);
352   void movw(const Address& dst, CpuRegister src);
353   void movw(const Address& dst, const Immediate& imm);
354 
355   void leaq(CpuRegister dst, const Address& src);
356   void leal(CpuRegister dst, const Address& src);
357 
358   void movaps(XmmRegister dst, XmmRegister src);
359 
360   void movss(XmmRegister dst, const Address& src);
361   void movss(const Address& dst, XmmRegister src);
362   void movss(XmmRegister dst, XmmRegister src);
363 
364   void movsxd(CpuRegister dst, CpuRegister src);
365   void movsxd(CpuRegister dst, const Address& src);
366 
367   void movd(XmmRegister dst, CpuRegister src);  // Note: this is the r64 version, formally movq.
368   void movd(CpuRegister dst, XmmRegister src);  // Note: this is the r64 version, formally movq.
369   void movd(XmmRegister dst, CpuRegister src, bool is64bit);
370   void movd(CpuRegister dst, XmmRegister src, bool is64bit);
371 
372   void addss(XmmRegister dst, XmmRegister src);
373   void addss(XmmRegister dst, const Address& src);
374   void subss(XmmRegister dst, XmmRegister src);
375   void subss(XmmRegister dst, const Address& src);
376   void mulss(XmmRegister dst, XmmRegister src);
377   void mulss(XmmRegister dst, const Address& src);
378   void divss(XmmRegister dst, XmmRegister src);
379   void divss(XmmRegister dst, const Address& src);
380 
381   void movsd(XmmRegister dst, const Address& src);
382   void movsd(const Address& dst, XmmRegister src);
383   void movsd(XmmRegister dst, XmmRegister src);
384 
385   void addsd(XmmRegister dst, XmmRegister src);
386   void addsd(XmmRegister dst, const Address& src);
387   void subsd(XmmRegister dst, XmmRegister src);
388   void subsd(XmmRegister dst, const Address& src);
389   void mulsd(XmmRegister dst, XmmRegister src);
390   void mulsd(XmmRegister dst, const Address& src);
391   void divsd(XmmRegister dst, XmmRegister src);
392   void divsd(XmmRegister dst, const Address& src);
393 
394   void cvtsi2ss(XmmRegister dst, CpuRegister src);  // Note: this is the r/m32 version.
395   void cvtsi2ss(XmmRegister dst, CpuRegister src, bool is64bit);
396   void cvtsi2ss(XmmRegister dst, const Address& src, bool is64bit);
397   void cvtsi2sd(XmmRegister dst, CpuRegister src);  // Note: this is the r/m32 version.
398   void cvtsi2sd(XmmRegister dst, CpuRegister src, bool is64bit);
399   void cvtsi2sd(XmmRegister dst, const Address& src, bool is64bit);
400 
401   void cvtss2si(CpuRegister dst, XmmRegister src);  // Note: this is the r32 version.
402   void cvtss2sd(XmmRegister dst, XmmRegister src);
403   void cvtss2sd(XmmRegister dst, const Address& src);
404 
405   void cvtsd2si(CpuRegister dst, XmmRegister src);  // Note: this is the r32 version.
406   void cvtsd2ss(XmmRegister dst, XmmRegister src);
407   void cvtsd2ss(XmmRegister dst, const Address& src);
408 
409   void cvttss2si(CpuRegister dst, XmmRegister src);  // Note: this is the r32 version.
410   void cvttss2si(CpuRegister dst, XmmRegister src, bool is64bit);
411   void cvttsd2si(CpuRegister dst, XmmRegister src);  // Note: this is the r32 version.
412   void cvttsd2si(CpuRegister dst, XmmRegister src, bool is64bit);
413 
414   void cvtdq2pd(XmmRegister dst, XmmRegister src);
415 
416   void comiss(XmmRegister a, XmmRegister b);
417   void comiss(XmmRegister a, const Address& b);
418   void comisd(XmmRegister a, XmmRegister b);
419   void comisd(XmmRegister a, const Address& b);
420   void ucomiss(XmmRegister a, XmmRegister b);
421   void ucomiss(XmmRegister a, const Address& b);
422   void ucomisd(XmmRegister a, XmmRegister b);
423   void ucomisd(XmmRegister a, const Address& b);
424 
425   void roundsd(XmmRegister dst, XmmRegister src, const Immediate& imm);
426   void roundss(XmmRegister dst, XmmRegister src, const Immediate& imm);
427 
428   void sqrtsd(XmmRegister dst, XmmRegister src);
429   void sqrtss(XmmRegister dst, XmmRegister src);
430 
431   void xorpd(XmmRegister dst, const Address& src);
432   void xorpd(XmmRegister dst, XmmRegister src);
433   void xorps(XmmRegister dst, const Address& src);
434   void xorps(XmmRegister dst, XmmRegister src);
435 
436   void andpd(XmmRegister dst, const Address& src);
437   void andpd(XmmRegister dst, XmmRegister src);
438   void andps(XmmRegister dst, XmmRegister src);
439 
440   void orpd(XmmRegister dst, XmmRegister src);
441   void orps(XmmRegister dst, XmmRegister src);
442 
443   void flds(const Address& src);
444   void fstps(const Address& dst);
445   void fsts(const Address& dst);
446 
447   void fldl(const Address& src);
448   void fstpl(const Address& dst);
449   void fstl(const Address& dst);
450 
451   void fstsw();
452 
453   void fucompp();
454 
455   void fnstcw(const Address& dst);
456   void fldcw(const Address& src);
457 
458   void fistpl(const Address& dst);
459   void fistps(const Address& dst);
460   void fildl(const Address& src);
461   void filds(const Address& src);
462 
463   void fincstp();
464   void ffree(const Immediate& index);
465 
466   void fsin();
467   void fcos();
468   void fptan();
469   void fprem();
470 
471   void xchgl(CpuRegister dst, CpuRegister src);
472   void xchgq(CpuRegister dst, CpuRegister src);
473   void xchgl(CpuRegister reg, const Address& address);
474 
475   void cmpw(const Address& address, const Immediate& imm);
476 
477   void cmpl(CpuRegister reg, const Immediate& imm);
478   void cmpl(CpuRegister reg0, CpuRegister reg1);
479   void cmpl(CpuRegister reg, const Address& address);
480   void cmpl(const Address& address, CpuRegister reg);
481   void cmpl(const Address& address, const Immediate& imm);
482 
483   void cmpq(CpuRegister reg0, CpuRegister reg1);
484   void cmpq(CpuRegister reg0, const Immediate& imm);
485   void cmpq(CpuRegister reg0, const Address& address);
486   void cmpq(const Address& address, const Immediate& imm);
487 
488   void testl(CpuRegister reg1, CpuRegister reg2);
489   void testl(CpuRegister reg, const Address& address);
490   void testl(CpuRegister reg, const Immediate& imm);
491 
492   void testq(CpuRegister reg1, CpuRegister reg2);
493   void testq(CpuRegister reg, const Address& address);
494 
495   void andl(CpuRegister dst, const Immediate& imm);
496   void andl(CpuRegister dst, CpuRegister src);
497   void andl(CpuRegister reg, const Address& address);
498   void andq(CpuRegister dst, const Immediate& imm);
499   void andq(CpuRegister dst, CpuRegister src);
500   void andq(CpuRegister reg, const Address& address);
501 
502   void orl(CpuRegister dst, const Immediate& imm);
503   void orl(CpuRegister dst, CpuRegister src);
504   void orl(CpuRegister reg, const Address& address);
505   void orq(CpuRegister dst, CpuRegister src);
506   void orq(CpuRegister dst, const Immediate& imm);
507   void orq(CpuRegister reg, const Address& address);
508 
509   void xorl(CpuRegister dst, CpuRegister src);
510   void xorl(CpuRegister dst, const Immediate& imm);
511   void xorl(CpuRegister reg, const Address& address);
512   void xorq(CpuRegister dst, const Immediate& imm);
513   void xorq(CpuRegister dst, CpuRegister src);
514   void xorq(CpuRegister reg, const Address& address);
515 
516   void addl(CpuRegister dst, CpuRegister src);
517   void addl(CpuRegister reg, const Immediate& imm);
518   void addl(CpuRegister reg, const Address& address);
519   void addl(const Address& address, CpuRegister reg);
520   void addl(const Address& address, const Immediate& imm);
521 
522   void addq(CpuRegister reg, const Immediate& imm);
523   void addq(CpuRegister dst, CpuRegister src);
524   void addq(CpuRegister dst, const Address& address);
525 
526   void subl(CpuRegister dst, CpuRegister src);
527   void subl(CpuRegister reg, const Immediate& imm);
528   void subl(CpuRegister reg, const Address& address);
529 
530   void subq(CpuRegister reg, const Immediate& imm);
531   void subq(CpuRegister dst, CpuRegister src);
532   void subq(CpuRegister dst, const Address& address);
533 
534   void cdq();
535   void cqo();
536 
537   void idivl(CpuRegister reg);
538   void idivq(CpuRegister reg);
539 
540   void imull(CpuRegister dst, CpuRegister src);
541   void imull(CpuRegister reg, const Immediate& imm);
542   void imull(CpuRegister reg, const Address& address);
543 
544   void imulq(CpuRegister src);
545   void imulq(CpuRegister dst, CpuRegister src);
546   void imulq(CpuRegister reg, const Immediate& imm);
547   void imulq(CpuRegister reg, const Address& address);
548   void imulq(CpuRegister dst, CpuRegister reg, const Immediate& imm);
549 
550   void imull(CpuRegister reg);
551   void imull(const Address& address);
552 
553   void mull(CpuRegister reg);
554   void mull(const Address& address);
555 
556   void shll(CpuRegister reg, const Immediate& imm);
557   void shll(CpuRegister operand, CpuRegister shifter);
558   void shrl(CpuRegister reg, const Immediate& imm);
559   void shrl(CpuRegister operand, CpuRegister shifter);
560   void sarl(CpuRegister reg, const Immediate& imm);
561   void sarl(CpuRegister operand, CpuRegister shifter);
562 
563   void shlq(CpuRegister reg, const Immediate& imm);
564   void shlq(CpuRegister operand, CpuRegister shifter);
565   void shrq(CpuRegister reg, const Immediate& imm);
566   void shrq(CpuRegister operand, CpuRegister shifter);
567   void sarq(CpuRegister reg, const Immediate& imm);
568   void sarq(CpuRegister operand, CpuRegister shifter);
569 
570   void negl(CpuRegister reg);
571   void negq(CpuRegister reg);
572 
573   void notl(CpuRegister reg);
574   void notq(CpuRegister reg);
575 
576   void enter(const Immediate& imm);
577   void leave();
578 
579   void ret();
580   void ret(const Immediate& imm);
581 
582   void nop();
583   void int3();
584   void hlt();
585 
586   void j(Condition condition, Label* label);
587 
588   void jmp(CpuRegister reg);
589   void jmp(const Address& address);
590   void jmp(Label* label);
591 
592   X86_64Assembler* lock();
593   void cmpxchgl(const Address& address, CpuRegister reg);
594   void cmpxchgq(const Address& address, CpuRegister reg);
595 
596   void mfence();
597 
598   X86_64Assembler* gs();
599 
600   void setcc(Condition condition, CpuRegister dst);
601 
602   void bswapl(CpuRegister dst);
603   void bswapq(CpuRegister dst);
604 
605   void repne_scasw();
606 
607   //
608   // Macros for High-level operations.
609   //
610 
611   void AddImmediate(CpuRegister reg, const Immediate& imm);
612 
613   void LoadDoubleConstant(XmmRegister dst, double value);
614 
LockCmpxchgl(const Address & address,CpuRegister reg)615   void LockCmpxchgl(const Address& address, CpuRegister reg) {
616     lock()->cmpxchgl(address, reg);
617   }
618 
LockCmpxchgq(const Address & address,CpuRegister reg)619   void LockCmpxchgq(const Address& address, CpuRegister reg) {
620     lock()->cmpxchgq(address, reg);
621   }
622 
623   //
624   // Misc. functionality
625   //
PreferredLoopAlignment()626   int PreferredLoopAlignment() { return 16; }
627   void Align(int alignment, int offset);
628   void Bind(Label* label);
629 
630   //
631   // Overridden common assembler high-level functionality
632   //
633 
634   // Emit code that will create an activation on the stack
635   void BuildFrame(size_t frame_size, ManagedRegister method_reg,
636                   const std::vector<ManagedRegister>& callee_save_regs,
637                   const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
638 
639   // Emit code that will remove an activation from the stack
640   void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
641       OVERRIDE;
642 
643   void IncreaseFrameSize(size_t adjust) OVERRIDE;
644   void DecreaseFrameSize(size_t adjust) OVERRIDE;
645 
646   // Store routines
647   void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE;
648   void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE;
649   void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE;
650 
651   void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE;
652 
653   void StoreImmediateToThread64(ThreadOffset<8> dest, uint32_t imm, ManagedRegister scratch)
654       OVERRIDE;
655 
656   void StoreStackOffsetToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs,
657                                   ManagedRegister scratch) OVERRIDE;
658 
659   void StoreStackPointerToThread64(ThreadOffset<8> thr_offs) OVERRIDE;
660 
661   void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
662                      ManagedRegister scratch) OVERRIDE;
663 
664   // Load routines
665   void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
666 
667   void LoadFromThread64(ManagedRegister dest, ThreadOffset<8> src, size_t size) OVERRIDE;
668 
669   void LoadRef(ManagedRegister dest, FrameOffset  src) OVERRIDE;
670 
671   void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs,
672                bool poison_reference) OVERRIDE;
673 
674   void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
675 
676   void LoadRawPtrFromThread64(ManagedRegister dest, ThreadOffset<8> offs) OVERRIDE;
677 
678   // Copying routines
679   void Move(ManagedRegister dest, ManagedRegister src, size_t size);
680 
681   void CopyRawPtrFromThread64(FrameOffset fr_offs, ThreadOffset<8> thr_offs,
682                               ManagedRegister scratch) OVERRIDE;
683 
684   void CopyRawPtrToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
685       OVERRIDE;
686 
687   void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE;
688 
689   void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE;
690 
691   void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
692             size_t size) OVERRIDE;
693 
694   void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch,
695             size_t size) OVERRIDE;
696 
697   void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch,
698             size_t size) OVERRIDE;
699 
700   void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
701             ManagedRegister scratch, size_t size) OVERRIDE;
702 
703   void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
704             ManagedRegister scratch, size_t size) OVERRIDE;
705 
706   void MemoryBarrier(ManagedRegister) OVERRIDE;
707 
708   // Sign extension
709   void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
710 
711   // Zero extension
712   void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
713 
714   // Exploit fast access in managed code to Thread::Current()
715   void GetCurrentThread(ManagedRegister tr) OVERRIDE;
716   void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE;
717 
718   // Set up out_reg to hold a Object** into the handle scope, or to be null if the
719   // value is null and null_allowed. in_reg holds a possibly stale reference
720   // that can be used to avoid loading the handle scope entry to see if the value is
721   // null.
722   void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset,
723                               ManagedRegister in_reg, bool null_allowed) OVERRIDE;
724 
725   // Set up out_off to hold a Object** into the handle scope, or to be null if the
726   // value is null and null_allowed.
727   void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset,
728                               ManagedRegister scratch, bool null_allowed) OVERRIDE;
729 
730   // src holds a handle scope entry (Object**) load this into dst
731   virtual void LoadReferenceFromHandleScope(ManagedRegister dst,
732                                      ManagedRegister src);
733 
734   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
735   // know that src may not be null.
736   void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
737   void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
738 
739   // Call to address held at [base+offset]
740   void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
741   void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
742   void CallFromThread64(ThreadOffset<8> offset, ManagedRegister scratch) OVERRIDE;
743 
744   // Generate code to check if Thread::Current()->exception_ is non-null
745   // and branch to a ExceptionSlowPath if it is.
746   void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
747 
748   // Add a double to the constant area, returning the offset into
749   // the constant area where the literal resides.
AddDouble(double v)750   int AddDouble(double v) { return constant_area_.AddDouble(v); }
751 
752   // Add a float to the constant area, returning the offset into
753   // the constant area where the literal resides.
AddFloat(float v)754   int AddFloat(float v)   { return constant_area_.AddFloat(v); }
755 
756   // Add an int32_t to the constant area, returning the offset into
757   // the constant area where the literal resides.
AddInt32(int32_t v)758   int AddInt32(int32_t v) { return constant_area_.AddInt32(v); }
759 
760   // Add an int64_t to the constant area, returning the offset into
761   // the constant area where the literal resides.
AddInt64(int64_t v)762   int AddInt64(int64_t v) { return constant_area_.AddInt64(v); }
763 
764   // Add the contents of the constant area to the assembler buffer.
765   void AddConstantArea();
766 
767   // Is the constant area empty? Return true if there are no literals in the constant area.
IsConstantAreaEmpty()768   bool IsConstantAreaEmpty() const { return constant_area_.GetSize() == 0; }
769 
770  private:
771   void EmitUint8(uint8_t value);
772   void EmitInt32(int32_t value);
773   void EmitInt64(int64_t value);
774   void EmitRegisterOperand(uint8_t rm, uint8_t reg);
775   void EmitXmmRegisterOperand(uint8_t rm, XmmRegister reg);
776   void EmitFixup(AssemblerFixup* fixup);
777   void EmitOperandSizeOverride();
778 
779   void EmitOperand(uint8_t rm, const Operand& operand);
780   void EmitImmediate(const Immediate& imm);
781   void EmitComplex(uint8_t rm, const Operand& operand, const Immediate& immediate);
782   void EmitLabel(Label* label, int instruction_size);
783   void EmitLabelLink(Label* label);
784   void EmitNearLabelLink(Label* label);
785 
786   void EmitGenericShift(bool wide, int rm, CpuRegister reg, const Immediate& imm);
787   void EmitGenericShift(bool wide, int rm, CpuRegister operand, CpuRegister shifter);
788 
789   // If any input is not false, output the necessary rex prefix.
790   void EmitOptionalRex(bool force, bool w, bool r, bool x, bool b);
791 
792   // Emit a rex prefix byte if necessary for reg. ie if reg is a register in the range R8 to R15.
793   void EmitOptionalRex32(CpuRegister reg);
794   void EmitOptionalRex32(CpuRegister dst, CpuRegister src);
795   void EmitOptionalRex32(XmmRegister dst, XmmRegister src);
796   void EmitOptionalRex32(CpuRegister dst, XmmRegister src);
797   void EmitOptionalRex32(XmmRegister dst, CpuRegister src);
798   void EmitOptionalRex32(const Operand& operand);
799   void EmitOptionalRex32(CpuRegister dst, const Operand& operand);
800   void EmitOptionalRex32(XmmRegister dst, const Operand& operand);
801 
802   // Emit a REX.W prefix plus necessary register bit encodings.
803   void EmitRex64();
804   void EmitRex64(CpuRegister reg);
805   void EmitRex64(const Operand& operand);
806   void EmitRex64(CpuRegister dst, CpuRegister src);
807   void EmitRex64(CpuRegister dst, const Operand& operand);
808   void EmitRex64(XmmRegister dst, const Operand& operand);
809   void EmitRex64(XmmRegister dst, CpuRegister src);
810   void EmitRex64(CpuRegister dst, XmmRegister src);
811 
812   // Emit a REX prefix to normalize byte registers plus necessary register bit encodings.
813   void EmitOptionalByteRegNormalizingRex32(CpuRegister dst, CpuRegister src);
814   void EmitOptionalByteRegNormalizingRex32(CpuRegister dst, const Operand& operand);
815 
816   ConstantArea constant_area_;
817 
818   DISALLOW_COPY_AND_ASSIGN(X86_64Assembler);
819 };
820 
EmitUint8(uint8_t value)821 inline void X86_64Assembler::EmitUint8(uint8_t value) {
822   buffer_.Emit<uint8_t>(value);
823 }
824 
EmitInt32(int32_t value)825 inline void X86_64Assembler::EmitInt32(int32_t value) {
826   buffer_.Emit<int32_t>(value);
827 }
828 
EmitInt64(int64_t value)829 inline void X86_64Assembler::EmitInt64(int64_t value) {
830   // Write this 64-bit value as two 32-bit words for alignment reasons
831   // (this is essentially when running on ARM, which does not allow
832   // 64-bit unaligned accesses).  We assume little-endianness here.
833   EmitInt32(Low32Bits(value));
834   EmitInt32(High32Bits(value));
835 }
836 
EmitRegisterOperand(uint8_t rm,uint8_t reg)837 inline void X86_64Assembler::EmitRegisterOperand(uint8_t rm, uint8_t reg) {
838   CHECK_GE(rm, 0);
839   CHECK_LT(rm, 8);
840   buffer_.Emit<uint8_t>((0xC0 | (reg & 7)) + (rm << 3));
841 }
842 
EmitXmmRegisterOperand(uint8_t rm,XmmRegister reg)843 inline void X86_64Assembler::EmitXmmRegisterOperand(uint8_t rm, XmmRegister reg) {
844   EmitRegisterOperand(rm, static_cast<uint8_t>(reg.AsFloatRegister()));
845 }
846 
EmitFixup(AssemblerFixup * fixup)847 inline void X86_64Assembler::EmitFixup(AssemblerFixup* fixup) {
848   buffer_.EmitFixup(fixup);
849 }
850 
EmitOperandSizeOverride()851 inline void X86_64Assembler::EmitOperandSizeOverride() {
852   EmitUint8(0x66);
853 }
854 
855 }  // namespace x86_64
856 }  // namespace art
857 
858 #endif  // ART_COMPILER_UTILS_X86_64_ASSEMBLER_X86_64_H_
859