1 /*
2  * Copyright (C) 2011 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_ASSEMBLER_X86_H_
18 #define ART_COMPILER_UTILS_X86_ASSEMBLER_X86_H_
19 
20 #include <vector>
21 
22 #include "base/arena_containers.h"
23 #include "base/bit_utils.h"
24 #include "base/macros.h"
25 #include "constants_x86.h"
26 #include "globals.h"
27 #include "managed_register_x86.h"
28 #include "offsets.h"
29 #include "utils/array_ref.h"
30 #include "utils/assembler.h"
31 
32 namespace art {
33 namespace x86 {
34 
35 class Immediate : public ValueObject {
36  public:
Immediate(int32_t value_in)37   explicit Immediate(int32_t value_in) : value_(value_in) {}
38 
value()39   int32_t value() const { return value_; }
40 
is_int8()41   bool is_int8() const { return IsInt<8>(value_); }
is_uint8()42   bool is_uint8() const { return IsUint<8>(value_); }
is_int16()43   bool is_int16() const { return IsInt<16>(value_); }
is_uint16()44   bool is_uint16() const { return IsUint<16>(value_); }
45 
46  private:
47   const int32_t value_;
48 };
49 
50 
51 class Operand : public ValueObject {
52  public:
mod()53   uint8_t mod() const {
54     return (encoding_at(0) >> 6) & 3;
55   }
56 
rm()57   Register rm() const {
58     return static_cast<Register>(encoding_at(0) & 7);
59   }
60 
scale()61   ScaleFactor scale() const {
62     return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
63   }
64 
index()65   Register index() const {
66     return static_cast<Register>((encoding_at(1) >> 3) & 7);
67   }
68 
base()69   Register base() const {
70     return static_cast<Register>(encoding_at(1) & 7);
71   }
72 
disp8()73   int8_t disp8() const {
74     CHECK_GE(length_, 2);
75     return static_cast<int8_t>(encoding_[length_ - 1]);
76   }
77 
disp32()78   int32_t disp32() const {
79     CHECK_GE(length_, 5);
80     int32_t value;
81     memcpy(&value, &encoding_[length_ - 4], sizeof(value));
82     return value;
83   }
84 
IsRegister(Register reg)85   bool IsRegister(Register reg) const {
86     return ((encoding_[0] & 0xF8) == 0xC0)  // Addressing mode is register only.
87         && ((encoding_[0] & 0x07) == reg);  // Register codes match.
88   }
89 
90  protected:
91   // Operand can be sub classed (e.g: Address).
Operand()92   Operand() : length_(0), fixup_(nullptr) { }
93 
SetModRM(int mod_in,Register rm_in)94   void SetModRM(int mod_in, Register rm_in) {
95     CHECK_EQ(mod_in & ~3, 0);
96     encoding_[0] = (mod_in << 6) | rm_in;
97     length_ = 1;
98   }
99 
SetSIB(ScaleFactor scale_in,Register index_in,Register base_in)100   void SetSIB(ScaleFactor scale_in, Register index_in, Register base_in) {
101     CHECK_EQ(length_, 1);
102     CHECK_EQ(scale_in & ~3, 0);
103     encoding_[1] = (scale_in << 6) | (index_in << 3) | base_in;
104     length_ = 2;
105   }
106 
SetDisp8(int8_t disp)107   void SetDisp8(int8_t disp) {
108     CHECK(length_ == 1 || length_ == 2);
109     encoding_[length_++] = static_cast<uint8_t>(disp);
110   }
111 
SetDisp32(int32_t disp)112   void SetDisp32(int32_t disp) {
113     CHECK(length_ == 1 || length_ == 2);
114     int disp_size = sizeof(disp);
115     memmove(&encoding_[length_], &disp, disp_size);
116     length_ += disp_size;
117   }
118 
GetFixup()119   AssemblerFixup* GetFixup() const {
120     return fixup_;
121   }
122 
SetFixup(AssemblerFixup * fixup)123   void SetFixup(AssemblerFixup* fixup) {
124     fixup_ = fixup;
125   }
126 
127  private:
128   uint8_t length_;
129   uint8_t encoding_[6];
130 
131   // A fixup can be associated with the operand, in order to be applied after the
132   // code has been generated. This is used for constant area fixups.
133   AssemblerFixup* fixup_;
134 
Operand(Register reg)135   explicit Operand(Register reg) : fixup_(nullptr) { SetModRM(3, reg); }
136 
137   // Get the operand encoding byte at the given index.
encoding_at(int index_in)138   uint8_t encoding_at(int index_in) const {
139     CHECK_GE(index_in, 0);
140     CHECK_LT(index_in, length_);
141     return encoding_[index_in];
142   }
143 
144   friend class X86Assembler;
145 };
146 
147 
148 class Address : public Operand {
149  public:
Address(Register base_in,int32_t disp)150   Address(Register base_in, int32_t disp) {
151     Init(base_in, disp);
152   }
153 
Address(Register base_in,int32_t disp,AssemblerFixup * fixup)154   Address(Register base_in, int32_t disp, AssemblerFixup *fixup) {
155     Init(base_in, disp);
156     SetFixup(fixup);
157   }
158 
Address(Register base_in,Offset disp)159   Address(Register base_in, Offset disp) {
160     Init(base_in, disp.Int32Value());
161   }
162 
Address(Register base_in,FrameOffset disp)163   Address(Register base_in, FrameOffset disp) {
164     CHECK_EQ(base_in, ESP);
165     Init(ESP, disp.Int32Value());
166   }
167 
Address(Register base_in,MemberOffset disp)168   Address(Register base_in, MemberOffset disp) {
169     Init(base_in, disp.Int32Value());
170   }
171 
Address(Register index_in,ScaleFactor scale_in,int32_t disp)172   Address(Register index_in, ScaleFactor scale_in, int32_t disp) {
173     CHECK_NE(index_in, ESP);  // Illegal addressing mode.
174     SetModRM(0, ESP);
175     SetSIB(scale_in, index_in, EBP);
176     SetDisp32(disp);
177   }
178 
Address(Register base_in,Register index_in,ScaleFactor scale_in,int32_t disp)179   Address(Register base_in, Register index_in, ScaleFactor scale_in, int32_t disp) {
180     Init(base_in, index_in, scale_in, disp);
181   }
182 
Address(Register base_in,Register index_in,ScaleFactor scale_in,int32_t disp,AssemblerFixup * fixup)183   Address(Register base_in,
184           Register index_in,
185           ScaleFactor scale_in,
186           int32_t disp, AssemblerFixup *fixup) {
187     Init(base_in, index_in, scale_in, disp);
188     SetFixup(fixup);
189   }
190 
Absolute(uintptr_t addr)191   static Address Absolute(uintptr_t addr) {
192     Address result;
193     result.SetModRM(0, EBP);
194     result.SetDisp32(addr);
195     return result;
196   }
197 
Absolute(ThreadOffset<4> addr)198   static Address Absolute(ThreadOffset<4> addr) {
199     return Absolute(addr.Int32Value());
200   }
201 
202  private:
Address()203   Address() {}
204 
Init(Register base_in,int32_t disp)205   void Init(Register base_in, int32_t disp) {
206     if (disp == 0 && base_in != EBP) {
207       SetModRM(0, base_in);
208       if (base_in == ESP) SetSIB(TIMES_1, ESP, base_in);
209     } else if (disp >= -128 && disp <= 127) {
210       SetModRM(1, base_in);
211       if (base_in == ESP) SetSIB(TIMES_1, ESP, base_in);
212       SetDisp8(disp);
213     } else {
214       SetModRM(2, base_in);
215       if (base_in == ESP) SetSIB(TIMES_1, ESP, base_in);
216       SetDisp32(disp);
217     }
218   }
219 
Init(Register base_in,Register index_in,ScaleFactor scale_in,int32_t disp)220   void Init(Register base_in, Register index_in, ScaleFactor scale_in, int32_t disp) {
221     CHECK_NE(index_in, ESP);  // Illegal addressing mode.
222     if (disp == 0 && base_in != EBP) {
223       SetModRM(0, ESP);
224       SetSIB(scale_in, index_in, base_in);
225     } else if (disp >= -128 && disp <= 127) {
226       SetModRM(1, ESP);
227       SetSIB(scale_in, index_in, base_in);
228       SetDisp8(disp);
229     } else {
230       SetModRM(2, ESP);
231       SetSIB(scale_in, index_in, base_in);
232       SetDisp32(disp);
233     }
234   }
235 };
236 
237 
238 // This is equivalent to the Label class, used in a slightly different context. We
239 // inherit the functionality of the Label class, but prevent unintended
240 // derived-to-base conversions by making the base class private.
241 class NearLabel : private Label {
242  public:
NearLabel()243   NearLabel() : Label() {}
244 
245   // Expose the Label routines that we need.
246   using Label::Position;
247   using Label::LinkPosition;
248   using Label::IsBound;
249   using Label::IsUnused;
250   using Label::IsLinked;
251 
252  private:
253   using Label::BindTo;
254   using Label::LinkTo;
255 
256   friend class x86::X86Assembler;
257 
258   DISALLOW_COPY_AND_ASSIGN(NearLabel);
259 };
260 
261 /**
262  * Class to handle constant area values.
263  */
264 class ConstantArea {
265  public:
ConstantArea(ArenaAllocator * arena)266   explicit ConstantArea(ArenaAllocator* arena) : buffer_(arena->Adapter(kArenaAllocAssembler)) {}
267 
268   // Add a double to the constant area, returning the offset into
269   // the constant area where the literal resides.
270   size_t AddDouble(double v);
271 
272   // Add a float to the constant area, returning the offset into
273   // the constant area where the literal resides.
274   size_t AddFloat(float v);
275 
276   // Add an int32_t to the constant area, returning the offset into
277   // the constant area where the literal resides.
278   size_t AddInt32(int32_t v);
279 
280   // Add an int32_t to the end of the constant area, returning the offset into
281   // the constant area where the literal resides.
282   size_t AppendInt32(int32_t v);
283 
284   // Add an int64_t to the constant area, returning the offset into
285   // the constant area where the literal resides.
286   size_t AddInt64(int64_t v);
287 
IsEmpty()288   bool IsEmpty() const {
289     return buffer_.size() == 0;
290   }
291 
GetSize()292   size_t GetSize() const {
293     return buffer_.size() * elem_size_;
294   }
295 
GetBuffer()296   ArrayRef<const int32_t> GetBuffer() const {
297     return ArrayRef<const int32_t>(buffer_);
298   }
299 
300  private:
301   static constexpr size_t elem_size_ = sizeof(int32_t);
302   ArenaVector<int32_t> buffer_;
303 };
304 
305 class X86Assembler FINAL : public Assembler {
306  public:
X86Assembler(ArenaAllocator * arena)307   explicit X86Assembler(ArenaAllocator* arena) : Assembler(arena), constant_area_(arena) {}
~X86Assembler()308   virtual ~X86Assembler() {}
309 
310   /*
311    * Emit Machine Instructions.
312    */
313   void call(Register reg);
314   void call(const Address& address);
315   void call(Label* label);
316   void call(const ExternalLabel& label);
317 
318   void pushl(Register reg);
319   void pushl(const Address& address);
320   void pushl(const Immediate& imm);
321 
322   void popl(Register reg);
323   void popl(const Address& address);
324 
325   void movl(Register dst, const Immediate& src);
326   void movl(Register dst, Register src);
327 
328   void movl(Register dst, const Address& src);
329   void movl(const Address& dst, Register src);
330   void movl(const Address& dst, const Immediate& imm);
331   void movl(const Address& dst, Label* lbl);
332 
333   void movntl(const Address& dst, Register src);
334 
335   void bswapl(Register dst);
336 
337   void bsfl(Register dst, Register src);
338   void bsfl(Register dst, const Address& src);
339   void bsrl(Register dst, Register src);
340   void bsrl(Register dst, const Address& src);
341 
342   void popcntl(Register dst, Register src);
343   void popcntl(Register dst, const Address& src);
344 
345   void rorl(Register reg, const Immediate& imm);
346   void rorl(Register operand, Register shifter);
347   void roll(Register reg, const Immediate& imm);
348   void roll(Register operand, Register shifter);
349 
350   void movzxb(Register dst, ByteRegister src);
351   void movzxb(Register dst, const Address& src);
352   void movsxb(Register dst, ByteRegister src);
353   void movsxb(Register dst, const Address& src);
354   void movb(Register dst, const Address& src);
355   void movb(const Address& dst, ByteRegister src);
356   void movb(const Address& dst, const Immediate& imm);
357 
358   void movzxw(Register dst, Register src);
359   void movzxw(Register dst, const Address& src);
360   void movsxw(Register dst, Register src);
361   void movsxw(Register dst, const Address& src);
362   void movw(Register dst, const Address& src);
363   void movw(const Address& dst, Register src);
364   void movw(const Address& dst, const Immediate& imm);
365 
366   void leal(Register dst, const Address& src);
367 
368   void cmovl(Condition condition, Register dst, Register src);
369   void cmovl(Condition condition, Register dst, const Address& src);
370 
371   void setb(Condition condition, Register dst);
372 
373   void movaps(XmmRegister dst, XmmRegister src);
374   void movss(XmmRegister dst, const Address& src);
375   void movss(const Address& dst, XmmRegister src);
376   void movss(XmmRegister dst, XmmRegister src);
377 
378   void movd(XmmRegister dst, Register src);
379   void movd(Register dst, XmmRegister src);
380 
381   void addss(XmmRegister dst, XmmRegister src);
382   void addss(XmmRegister dst, const Address& src);
383   void subss(XmmRegister dst, XmmRegister src);
384   void subss(XmmRegister dst, const Address& src);
385   void mulss(XmmRegister dst, XmmRegister src);
386   void mulss(XmmRegister dst, const Address& src);
387   void divss(XmmRegister dst, XmmRegister src);
388   void divss(XmmRegister dst, const Address& src);
389 
390   void movsd(XmmRegister dst, const Address& src);
391   void movsd(const Address& dst, XmmRegister src);
392   void movsd(XmmRegister dst, XmmRegister src);
393 
394   void psrlq(XmmRegister reg, const Immediate& shift_count);
395   void punpckldq(XmmRegister dst, XmmRegister src);
396 
397   void movhpd(XmmRegister dst, const Address& src);
398   void movhpd(const Address& dst, XmmRegister src);
399 
400   void psrldq(XmmRegister reg, const Immediate& shift_count);
401 
402   void addsd(XmmRegister dst, XmmRegister src);
403   void addsd(XmmRegister dst, const Address& src);
404   void subsd(XmmRegister dst, XmmRegister src);
405   void subsd(XmmRegister dst, const Address& src);
406   void mulsd(XmmRegister dst, XmmRegister src);
407   void mulsd(XmmRegister dst, const Address& src);
408   void divsd(XmmRegister dst, XmmRegister src);
409   void divsd(XmmRegister dst, const Address& src);
410 
411   void cvtsi2ss(XmmRegister dst, Register src);
412   void cvtsi2sd(XmmRegister dst, Register src);
413 
414   void cvtss2si(Register dst, XmmRegister src);
415   void cvtss2sd(XmmRegister dst, XmmRegister src);
416 
417   void cvtsd2si(Register dst, XmmRegister src);
418   void cvtsd2ss(XmmRegister dst, XmmRegister src);
419 
420   void cvttss2si(Register dst, XmmRegister src);
421   void cvttsd2si(Register dst, XmmRegister src);
422 
423   void cvtdq2pd(XmmRegister dst, XmmRegister src);
424 
425   void comiss(XmmRegister a, XmmRegister b);
426   void comisd(XmmRegister a, XmmRegister b);
427   void ucomiss(XmmRegister a, XmmRegister b);
428   void ucomiss(XmmRegister a, const Address& b);
429   void ucomisd(XmmRegister a, XmmRegister b);
430   void ucomisd(XmmRegister a, const Address& b);
431 
432   void roundsd(XmmRegister dst, XmmRegister src, const Immediate& imm);
433   void roundss(XmmRegister dst, XmmRegister src, const Immediate& imm);
434 
435   void sqrtsd(XmmRegister dst, XmmRegister src);
436   void sqrtss(XmmRegister dst, XmmRegister src);
437 
438   void xorpd(XmmRegister dst, const Address& src);
439   void xorpd(XmmRegister dst, XmmRegister src);
440   void xorps(XmmRegister dst, const Address& src);
441   void xorps(XmmRegister dst, XmmRegister src);
442 
443   void andpd(XmmRegister dst, XmmRegister src);
444   void andpd(XmmRegister dst, const Address& src);
445   void andps(XmmRegister dst, XmmRegister src);
446   void andps(XmmRegister dst, const Address& src);
447 
448   void orpd(XmmRegister dst, XmmRegister src);
449   void orps(XmmRegister dst, XmmRegister src);
450 
451   void flds(const Address& src);
452   void fstps(const Address& dst);
453   void fsts(const Address& dst);
454 
455   void fldl(const Address& src);
456   void fstpl(const Address& dst);
457   void fstl(const Address& dst);
458 
459   void fstsw();
460 
461   void fucompp();
462 
463   void fnstcw(const Address& dst);
464   void fldcw(const Address& src);
465 
466   void fistpl(const Address& dst);
467   void fistps(const Address& dst);
468   void fildl(const Address& src);
469   void filds(const Address& src);
470 
471   void fincstp();
472   void ffree(const Immediate& index);
473 
474   void fsin();
475   void fcos();
476   void fptan();
477   void fprem();
478 
479   void xchgl(Register dst, Register src);
480   void xchgl(Register reg, const Address& address);
481 
482   void cmpw(const Address& address, const Immediate& imm);
483 
484   void cmpl(Register reg, const Immediate& imm);
485   void cmpl(Register reg0, Register reg1);
486   void cmpl(Register reg, const Address& address);
487 
488   void cmpl(const Address& address, Register reg);
489   void cmpl(const Address& address, const Immediate& imm);
490 
491   void testl(Register reg1, Register reg2);
492   void testl(Register reg, const Immediate& imm);
493   void testl(Register reg1, const Address& address);
494 
495   void andl(Register dst, const Immediate& imm);
496   void andl(Register dst, Register src);
497   void andl(Register dst, const Address& address);
498 
499   void orl(Register dst, const Immediate& imm);
500   void orl(Register dst, Register src);
501   void orl(Register dst, const Address& address);
502 
503   void xorl(Register dst, Register src);
504   void xorl(Register dst, const Immediate& imm);
505   void xorl(Register dst, const Address& address);
506 
507   void addl(Register dst, Register src);
508   void addl(Register reg, const Immediate& imm);
509   void addl(Register reg, const Address& address);
510 
511   void addl(const Address& address, Register reg);
512   void addl(const Address& address, const Immediate& imm);
513 
514   void adcl(Register dst, Register src);
515   void adcl(Register reg, const Immediate& imm);
516   void adcl(Register dst, const Address& address);
517 
518   void subl(Register dst, Register src);
519   void subl(Register reg, const Immediate& imm);
520   void subl(Register reg, const Address& address);
521   void subl(const Address& address, Register src);
522 
523   void cdq();
524 
525   void idivl(Register reg);
526 
527   void imull(Register dst, Register src);
528   void imull(Register reg, const Immediate& imm);
529   void imull(Register dst, Register src, const Immediate& imm);
530   void imull(Register reg, const Address& address);
531 
532   void imull(Register reg);
533   void imull(const Address& address);
534 
535   void mull(Register reg);
536   void mull(const Address& address);
537 
538   void sbbl(Register dst, Register src);
539   void sbbl(Register reg, const Immediate& imm);
540   void sbbl(Register reg, const Address& address);
541   void sbbl(const Address& address, Register src);
542 
543   void incl(Register reg);
544   void incl(const Address& address);
545 
546   void decl(Register reg);
547   void decl(const Address& address);
548 
549   void shll(Register reg, const Immediate& imm);
550   void shll(Register operand, Register shifter);
551   void shll(const Address& address, const Immediate& imm);
552   void shll(const Address& address, Register shifter);
553   void shrl(Register reg, const Immediate& imm);
554   void shrl(Register operand, Register shifter);
555   void shrl(const Address& address, const Immediate& imm);
556   void shrl(const Address& address, Register shifter);
557   void sarl(Register reg, const Immediate& imm);
558   void sarl(Register operand, Register shifter);
559   void sarl(const Address& address, const Immediate& imm);
560   void sarl(const Address& address, Register shifter);
561   void shld(Register dst, Register src, Register shifter);
562   void shld(Register dst, Register src, const Immediate& imm);
563   void shrd(Register dst, Register src, Register shifter);
564   void shrd(Register dst, Register src, const Immediate& imm);
565 
566   void negl(Register reg);
567   void notl(Register reg);
568 
569   void enter(const Immediate& imm);
570   void leave();
571 
572   void ret();
573   void ret(const Immediate& imm);
574 
575   void nop();
576   void int3();
577   void hlt();
578 
579   void j(Condition condition, Label* label);
580   void j(Condition condition, NearLabel* label);
581   void jecxz(NearLabel* label);
582 
583   void jmp(Register reg);
584   void jmp(const Address& address);
585   void jmp(Label* label);
586   void jmp(NearLabel* label);
587 
588   void repne_scasw();
589   void repe_cmpsw();
590   void repe_cmpsl();
591   void rep_movsw();
592 
593   X86Assembler* lock();
594   void cmpxchgl(const Address& address, Register reg);
595   void cmpxchg8b(const Address& address);
596 
597   void mfence();
598 
599   X86Assembler* fs();
600   X86Assembler* gs();
601 
602   //
603   // Macros for High-level operations.
604   //
605 
606   void AddImmediate(Register reg, const Immediate& imm);
607 
608   void LoadLongConstant(XmmRegister dst, int64_t value);
609   void LoadDoubleConstant(XmmRegister dst, double value);
610 
LockCmpxchgl(const Address & address,Register reg)611   void LockCmpxchgl(const Address& address, Register reg) {
612     lock()->cmpxchgl(address, reg);
613   }
614 
LockCmpxchg8b(const Address & address)615   void LockCmpxchg8b(const Address& address) {
616     lock()->cmpxchg8b(address);
617   }
618 
619   //
620   // Misc. functionality
621   //
PreferredLoopAlignment()622   int PreferredLoopAlignment() { return 16; }
623   void Align(int alignment, int offset);
624   void Bind(Label* label) OVERRIDE;
Jump(Label * label)625   void Jump(Label* label) OVERRIDE {
626     jmp(label);
627   }
628   void Bind(NearLabel* 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 StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister scratch)
654       OVERRIDE;
655 
656   void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs,
657                                   ManagedRegister scratch) OVERRIDE;
658 
659   void StoreStackPointerToThread32(ThreadOffset<4> 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 LoadFromThread32(ManagedRegister dest, ThreadOffset<4> 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 unpoison_reference) OVERRIDE;
673 
674   void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
675 
676   void LoadRawPtrFromThread32(ManagedRegister dest, ThreadOffset<4> offs) OVERRIDE;
677 
678   // Copying routines
679   void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE;
680 
681   void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs,
682                               ManagedRegister scratch) OVERRIDE;
683 
684   void CopyRawPtrToThread32(ThreadOffset<4> 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   void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
732 
733   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
734   // know that src may not be null.
735   void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
736   void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
737 
738   // Call to address held at [base+offset]
739   void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
740   void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
741   void CallFromThread32(ThreadOffset<4> offset, ManagedRegister scratch) OVERRIDE;
742 
743   // Generate code to check if Thread::Current()->exception_ is non-null
744   // and branch to a ExceptionSlowPath if it is.
745   void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
746 
747   //
748   // Heap poisoning.
749   //
750 
751   // Poison a heap reference contained in `reg`.
PoisonHeapReference(Register reg)752   void PoisonHeapReference(Register reg) { negl(reg); }
753   // Unpoison a heap reference contained in `reg`.
UnpoisonHeapReference(Register reg)754   void UnpoisonHeapReference(Register reg) { negl(reg); }
755   // Unpoison a heap reference contained in `reg` if heap poisoning is enabled.
MaybeUnpoisonHeapReference(Register reg)756   void MaybeUnpoisonHeapReference(Register reg) {
757     if (kPoisonHeapReferences) {
758       UnpoisonHeapReference(reg);
759     }
760   }
761 
762   // Add a double to the constant area, returning the offset into
763   // the constant area where the literal resides.
AddDouble(double v)764   size_t AddDouble(double v) { return constant_area_.AddDouble(v); }
765 
766   // Add a float to the constant area, returning the offset into
767   // the constant area where the literal resides.
AddFloat(float v)768   size_t AddFloat(float v)   { return constant_area_.AddFloat(v); }
769 
770   // Add an int32_t to the constant area, returning the offset into
771   // the constant area where the literal resides.
AddInt32(int32_t v)772   size_t AddInt32(int32_t v) {
773     return constant_area_.AddInt32(v);
774   }
775 
776   // Add an int32_t to the end of the constant area, returning the offset into
777   // the constant area where the literal resides.
AppendInt32(int32_t v)778   size_t AppendInt32(int32_t v) {
779     return constant_area_.AppendInt32(v);
780   }
781 
782   // Add an int64_t to the constant area, returning the offset into
783   // the constant area where the literal resides.
AddInt64(int64_t v)784   size_t AddInt64(int64_t v) { return constant_area_.AddInt64(v); }
785 
786   // Add the contents of the constant area to the assembler buffer.
787   void AddConstantArea();
788 
789   // Is the constant area empty? Return true if there are no literals in the constant area.
IsConstantAreaEmpty()790   bool IsConstantAreaEmpty() const { return constant_area_.IsEmpty(); }
791 
792   // Return the current size of the constant area.
ConstantAreaSize()793   size_t ConstantAreaSize() const { return constant_area_.GetSize(); }
794 
795  private:
796   inline void EmitUint8(uint8_t value);
797   inline void EmitInt32(int32_t value);
798   inline void EmitRegisterOperand(int rm, int reg);
799   inline void EmitXmmRegisterOperand(int rm, XmmRegister reg);
800   inline void EmitFixup(AssemblerFixup* fixup);
801   inline void EmitOperandSizeOverride();
802 
803   void EmitOperand(int rm, const Operand& operand);
804   void EmitImmediate(const Immediate& imm);
805   void EmitComplex(int rm, const Operand& operand, const Immediate& immediate);
806   void EmitLabel(Label* label, int instruction_size);
807   void EmitLabelLink(Label* label);
808   void EmitLabelLink(NearLabel* label);
809 
810   void EmitGenericShift(int rm, const Operand& operand, const Immediate& imm);
811   void EmitGenericShift(int rm, const Operand& operand, Register shifter);
812 
813   ConstantArea constant_area_;
814 
815   DISALLOW_COPY_AND_ASSIGN(X86Assembler);
816 };
817 
EmitUint8(uint8_t value)818 inline void X86Assembler::EmitUint8(uint8_t value) {
819   buffer_.Emit<uint8_t>(value);
820 }
821 
EmitInt32(int32_t value)822 inline void X86Assembler::EmitInt32(int32_t value) {
823   buffer_.Emit<int32_t>(value);
824 }
825 
EmitRegisterOperand(int rm,int reg)826 inline void X86Assembler::EmitRegisterOperand(int rm, int reg) {
827   CHECK_GE(rm, 0);
828   CHECK_LT(rm, 8);
829   buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg);
830 }
831 
EmitXmmRegisterOperand(int rm,XmmRegister reg)832 inline void X86Assembler::EmitXmmRegisterOperand(int rm, XmmRegister reg) {
833   EmitRegisterOperand(rm, static_cast<Register>(reg));
834 }
835 
EmitFixup(AssemblerFixup * fixup)836 inline void X86Assembler::EmitFixup(AssemblerFixup* fixup) {
837   buffer_.EmitFixup(fixup);
838 }
839 
EmitOperandSizeOverride()840 inline void X86Assembler::EmitOperandSizeOverride() {
841   EmitUint8(0x66);
842 }
843 
844 // Slowpath entered when Thread::Current()->_exception is non-null
845 class X86ExceptionSlowPath FINAL : public SlowPath {
846  public:
X86ExceptionSlowPath(size_t stack_adjust)847   explicit X86ExceptionSlowPath(size_t stack_adjust) : stack_adjust_(stack_adjust) {}
848   virtual void Emit(Assembler *sp_asm) OVERRIDE;
849  private:
850   const size_t stack_adjust_;
851 };
852 
853 }  // namespace x86
854 }  // namespace art
855 
856 #endif  // ART_COMPILER_UTILS_X86_ASSEMBLER_X86_H_
857