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