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 #include "base/bit_utils.h"
22 #include "base/macros.h"
23 #include "constants_x86.h"
24 #include "globals.h"
25 #include "managed_register_x86.h"
26 #include "offsets.h"
27 #include "utils/assembler.h"
28 
29 namespace art {
30 namespace x86 {
31 
32 class Immediate : public ValueObject {
33  public:
Immediate(int32_t value_in)34   explicit Immediate(int32_t value_in) : value_(value_in) {}
35 
value()36   int32_t value() const { return value_; }
37 
is_int8()38   bool is_int8() const { return IsInt<8>(value_); }
is_uint8()39   bool is_uint8() const { return IsUint<8>(value_); }
is_int16()40   bool is_int16() const { return IsInt<16>(value_); }
is_uint16()41   bool is_uint16() const { return IsUint<16>(value_); }
42 
43  private:
44   const int32_t value_;
45 };
46 
47 
48 class Operand : public ValueObject {
49  public:
mod()50   uint8_t mod() const {
51     return (encoding_at(0) >> 6) & 3;
52   }
53 
rm()54   Register rm() const {
55     return static_cast<Register>(encoding_at(0) & 7);
56   }
57 
scale()58   ScaleFactor scale() const {
59     return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
60   }
61 
index()62   Register index() const {
63     return static_cast<Register>((encoding_at(1) >> 3) & 7);
64   }
65 
base()66   Register base() const {
67     return static_cast<Register>(encoding_at(1) & 7);
68   }
69 
disp8()70   int8_t disp8() const {
71     CHECK_GE(length_, 2);
72     return static_cast<int8_t>(encoding_[length_ - 1]);
73   }
74 
disp32()75   int32_t disp32() const {
76     CHECK_GE(length_, 5);
77     int32_t value;
78     memcpy(&value, &encoding_[length_ - 4], sizeof(value));
79     return value;
80   }
81 
IsRegister(Register reg)82   bool IsRegister(Register reg) const {
83     return ((encoding_[0] & 0xF8) == 0xC0)  // Addressing mode is register only.
84         && ((encoding_[0] & 0x07) == reg);  // Register codes match.
85   }
86 
87  protected:
88   // Operand can be sub classed (e.g: Address).
Operand()89   Operand() : length_(0) { }
90 
SetModRM(int mod_in,Register rm_in)91   void SetModRM(int mod_in, Register rm_in) {
92     CHECK_EQ(mod_in & ~3, 0);
93     encoding_[0] = (mod_in << 6) | rm_in;
94     length_ = 1;
95   }
96 
SetSIB(ScaleFactor scale_in,Register index_in,Register base_in)97   void SetSIB(ScaleFactor scale_in, Register index_in, Register base_in) {
98     CHECK_EQ(length_, 1);
99     CHECK_EQ(scale_in & ~3, 0);
100     encoding_[1] = (scale_in << 6) | (index_in << 3) | base_in;
101     length_ = 2;
102   }
103 
SetDisp8(int8_t disp)104   void SetDisp8(int8_t disp) {
105     CHECK(length_ == 1 || length_ == 2);
106     encoding_[length_++] = static_cast<uint8_t>(disp);
107   }
108 
SetDisp32(int32_t disp)109   void SetDisp32(int32_t disp) {
110     CHECK(length_ == 1 || length_ == 2);
111     int disp_size = sizeof(disp);
112     memmove(&encoding_[length_], &disp, disp_size);
113     length_ += disp_size;
114   }
115 
116  private:
117   uint8_t length_;
118   uint8_t encoding_[6];
119 
Operand(Register reg)120   explicit Operand(Register reg) { SetModRM(3, reg); }
121 
122   // Get the operand encoding byte at the given index.
encoding_at(int index_in)123   uint8_t encoding_at(int index_in) const {
124     CHECK_GE(index_in, 0);
125     CHECK_LT(index_in, length_);
126     return encoding_[index_in];
127   }
128 
129   friend class X86Assembler;
130 };
131 
132 
133 class Address : public Operand {
134  public:
Address(Register base_in,int32_t disp)135   Address(Register base_in, int32_t disp) {
136     Init(base_in, disp);
137   }
138 
Address(Register base_in,Offset disp)139   Address(Register base_in, Offset disp) {
140     Init(base_in, disp.Int32Value());
141   }
142 
Address(Register base_in,FrameOffset disp)143   Address(Register base_in, FrameOffset disp) {
144     CHECK_EQ(base_in, ESP);
145     Init(ESP, disp.Int32Value());
146   }
147 
Address(Register base_in,MemberOffset disp)148   Address(Register base_in, MemberOffset disp) {
149     Init(base_in, disp.Int32Value());
150   }
151 
Init(Register base_in,int32_t disp)152   void Init(Register base_in, int32_t disp) {
153     if (disp == 0 && base_in != EBP) {
154       SetModRM(0, base_in);
155       if (base_in == ESP) SetSIB(TIMES_1, ESP, base_in);
156     } else if (disp >= -128 && disp <= 127) {
157       SetModRM(1, base_in);
158       if (base_in == ESP) SetSIB(TIMES_1, ESP, base_in);
159       SetDisp8(disp);
160     } else {
161       SetModRM(2, base_in);
162       if (base_in == ESP) SetSIB(TIMES_1, ESP, base_in);
163       SetDisp32(disp);
164     }
165   }
166 
Address(Register index_in,ScaleFactor scale_in,int32_t disp)167   Address(Register index_in, ScaleFactor scale_in, int32_t disp) {
168     CHECK_NE(index_in, ESP);  // Illegal addressing mode.
169     SetModRM(0, ESP);
170     SetSIB(scale_in, index_in, EBP);
171     SetDisp32(disp);
172   }
173 
Address(Register base_in,Register index_in,ScaleFactor scale_in,int32_t disp)174   Address(Register base_in, Register index_in, ScaleFactor scale_in, int32_t disp) {
175     CHECK_NE(index_in, ESP);  // Illegal addressing mode.
176     if (disp == 0 && base_in != EBP) {
177       SetModRM(0, ESP);
178       SetSIB(scale_in, index_in, base_in);
179     } else if (disp >= -128 && disp <= 127) {
180       SetModRM(1, ESP);
181       SetSIB(scale_in, index_in, base_in);
182       SetDisp8(disp);
183     } else {
184       SetModRM(2, ESP);
185       SetSIB(scale_in, index_in, base_in);
186       SetDisp32(disp);
187     }
188   }
189 
Absolute(uintptr_t addr)190   static Address Absolute(uintptr_t addr) {
191     Address result;
192     result.SetModRM(0, EBP);
193     result.SetDisp32(addr);
194     return result;
195   }
196 
Absolute(ThreadOffset<4> addr)197   static Address Absolute(ThreadOffset<4> addr) {
198     return Absolute(addr.Int32Value());
199   }
200 
201  private:
Address()202   Address() {}
203 };
204 
205 
206 class X86Assembler FINAL : public Assembler {
207  public:
X86Assembler()208   explicit X86Assembler() {}
~X86Assembler()209   virtual ~X86Assembler() {}
210 
211   /*
212    * Emit Machine Instructions.
213    */
214   void call(Register reg);
215   void call(const Address& address);
216   void call(Label* label);
217   void call(const ExternalLabel& label);
218 
219   void pushl(Register reg);
220   void pushl(const Address& address);
221   void pushl(const Immediate& imm);
222 
223   void popl(Register reg);
224   void popl(const Address& address);
225 
226   void movl(Register dst, const Immediate& src);
227   void movl(Register dst, Register src);
228 
229   void movl(Register dst, const Address& src);
230   void movl(const Address& dst, Register src);
231   void movl(const Address& dst, const Immediate& imm);
232   void movl(const Address& dst, Label* lbl);
233 
234   void bswapl(Register dst);
235 
236   void movzxb(Register dst, ByteRegister src);
237   void movzxb(Register dst, const Address& src);
238   void movsxb(Register dst, ByteRegister src);
239   void movsxb(Register dst, const Address& src);
240   void movb(Register dst, const Address& src);
241   void movb(const Address& dst, ByteRegister src);
242   void movb(const Address& dst, const Immediate& imm);
243 
244   void movzxw(Register dst, Register src);
245   void movzxw(Register dst, const Address& src);
246   void movsxw(Register dst, Register src);
247   void movsxw(Register dst, const Address& src);
248   void movw(Register dst, const Address& src);
249   void movw(const Address& dst, Register src);
250   void movw(const Address& dst, const Immediate& imm);
251 
252   void leal(Register dst, const Address& src);
253 
254   void cmovl(Condition condition, Register dst, Register src);
255 
256   void setb(Condition condition, Register dst);
257 
258   void movaps(XmmRegister dst, XmmRegister src);
259   void movss(XmmRegister dst, const Address& src);
260   void movss(const Address& dst, XmmRegister src);
261   void movss(XmmRegister dst, XmmRegister src);
262 
263   void movd(XmmRegister dst, Register src);
264   void movd(Register dst, XmmRegister src);
265 
266   void addss(XmmRegister dst, XmmRegister src);
267   void addss(XmmRegister dst, const Address& src);
268   void subss(XmmRegister dst, XmmRegister src);
269   void subss(XmmRegister dst, const Address& src);
270   void mulss(XmmRegister dst, XmmRegister src);
271   void mulss(XmmRegister dst, const Address& src);
272   void divss(XmmRegister dst, XmmRegister src);
273   void divss(XmmRegister dst, const Address& src);
274 
275   void movsd(XmmRegister dst, const Address& src);
276   void movsd(const Address& dst, XmmRegister src);
277   void movsd(XmmRegister dst, XmmRegister src);
278 
279   void psrlq(XmmRegister reg, const Immediate& shift_count);
280   void punpckldq(XmmRegister dst, XmmRegister src);
281 
282   void movhpd(XmmRegister dst, const Address& src);
283   void movhpd(const Address& dst, XmmRegister src);
284 
285   void psrldq(XmmRegister reg, const Immediate& shift_count);
286 
287   void addsd(XmmRegister dst, XmmRegister src);
288   void addsd(XmmRegister dst, const Address& src);
289   void subsd(XmmRegister dst, XmmRegister src);
290   void subsd(XmmRegister dst, const Address& src);
291   void mulsd(XmmRegister dst, XmmRegister src);
292   void mulsd(XmmRegister dst, const Address& src);
293   void divsd(XmmRegister dst, XmmRegister src);
294   void divsd(XmmRegister dst, const Address& src);
295 
296   void cvtsi2ss(XmmRegister dst, Register src);
297   void cvtsi2sd(XmmRegister dst, Register src);
298 
299   void cvtss2si(Register dst, XmmRegister src);
300   void cvtss2sd(XmmRegister dst, XmmRegister src);
301 
302   void cvtsd2si(Register dst, XmmRegister src);
303   void cvtsd2ss(XmmRegister dst, XmmRegister src);
304 
305   void cvttss2si(Register dst, XmmRegister src);
306   void cvttsd2si(Register dst, XmmRegister src);
307 
308   void cvtdq2pd(XmmRegister dst, XmmRegister src);
309 
310   void comiss(XmmRegister a, XmmRegister b);
311   void comisd(XmmRegister a, XmmRegister b);
312   void ucomiss(XmmRegister a, XmmRegister b);
313   void ucomisd(XmmRegister a, XmmRegister b);
314 
315   void roundsd(XmmRegister dst, XmmRegister src, const Immediate& imm);
316   void roundss(XmmRegister dst, XmmRegister src, const Immediate& imm);
317 
318   void sqrtsd(XmmRegister dst, XmmRegister src);
319   void sqrtss(XmmRegister dst, XmmRegister src);
320 
321   void xorpd(XmmRegister dst, const Address& src);
322   void xorpd(XmmRegister dst, XmmRegister src);
323   void xorps(XmmRegister dst, const Address& src);
324   void xorps(XmmRegister dst, XmmRegister src);
325 
326   void andpd(XmmRegister dst, XmmRegister src);
327   void andpd(XmmRegister dst, const Address& src);
328   void andps(XmmRegister dst, XmmRegister src);
329   void andps(XmmRegister dst, const Address& src);
330 
331   void orpd(XmmRegister dst, XmmRegister src);
332   void orps(XmmRegister dst, XmmRegister src);
333 
334   void flds(const Address& src);
335   void fstps(const Address& dst);
336   void fsts(const Address& dst);
337 
338   void fldl(const Address& src);
339   void fstpl(const Address& dst);
340   void fstl(const Address& dst);
341 
342   void fstsw();
343 
344   void fucompp();
345 
346   void fnstcw(const Address& dst);
347   void fldcw(const Address& src);
348 
349   void fistpl(const Address& dst);
350   void fistps(const Address& dst);
351   void fildl(const Address& src);
352   void filds(const Address& src);
353 
354   void fincstp();
355   void ffree(const Immediate& index);
356 
357   void fsin();
358   void fcos();
359   void fptan();
360   void fprem();
361 
362   void xchgl(Register dst, Register src);
363   void xchgl(Register reg, const Address& address);
364 
365   void cmpw(const Address& address, const Immediate& imm);
366 
367   void cmpl(Register reg, const Immediate& imm);
368   void cmpl(Register reg0, Register reg1);
369   void cmpl(Register reg, const Address& address);
370 
371   void cmpl(const Address& address, Register reg);
372   void cmpl(const Address& address, const Immediate& imm);
373 
374   void testl(Register reg1, Register reg2);
375   void testl(Register reg, const Immediate& imm);
376   void testl(Register reg1, const Address& address);
377 
378   void andl(Register dst, const Immediate& imm);
379   void andl(Register dst, Register src);
380   void andl(Register dst, const Address& address);
381 
382   void orl(Register dst, const Immediate& imm);
383   void orl(Register dst, Register src);
384   void orl(Register dst, const Address& address);
385 
386   void xorl(Register dst, Register src);
387   void xorl(Register dst, const Immediate& imm);
388   void xorl(Register dst, const Address& address);
389 
390   void addl(Register dst, Register src);
391   void addl(Register reg, const Immediate& imm);
392   void addl(Register reg, const Address& address);
393 
394   void addl(const Address& address, Register reg);
395   void addl(const Address& address, const Immediate& imm);
396 
397   void adcl(Register dst, Register src);
398   void adcl(Register reg, const Immediate& imm);
399   void adcl(Register dst, const Address& address);
400 
401   void subl(Register dst, Register src);
402   void subl(Register reg, const Immediate& imm);
403   void subl(Register reg, const Address& address);
404   void subl(const Address& address, Register src);
405 
406   void cdq();
407 
408   void idivl(Register reg);
409 
410   void imull(Register dst, Register src);
411   void imull(Register reg, const Immediate& imm);
412   void imull(Register reg, const Address& address);
413 
414   void imull(Register reg);
415   void imull(const Address& address);
416 
417   void mull(Register reg);
418   void mull(const Address& address);
419 
420   void sbbl(Register dst, Register src);
421   void sbbl(Register reg, const Immediate& imm);
422   void sbbl(Register reg, const Address& address);
423   void sbbl(const Address& address, Register src);
424 
425   void incl(Register reg);
426   void incl(const Address& address);
427 
428   void decl(Register reg);
429   void decl(const Address& address);
430 
431   void shll(Register reg, const Immediate& imm);
432   void shll(Register operand, Register shifter);
433   void shll(const Address& address, const Immediate& imm);
434   void shll(const Address& address, Register shifter);
435   void shrl(Register reg, const Immediate& imm);
436   void shrl(Register operand, Register shifter);
437   void shrl(const Address& address, const Immediate& imm);
438   void shrl(const Address& address, Register shifter);
439   void sarl(Register reg, const Immediate& imm);
440   void sarl(Register operand, Register shifter);
441   void sarl(const Address& address, const Immediate& imm);
442   void sarl(const Address& address, Register shifter);
443   void shld(Register dst, Register src, Register shifter);
444   void shld(Register dst, Register src, const Immediate& imm);
445   void shrd(Register dst, Register src, Register shifter);
446   void shrd(Register dst, Register src, const Immediate& imm);
447 
448   void negl(Register reg);
449   void notl(Register reg);
450 
451   void enter(const Immediate& imm);
452   void leave();
453 
454   void ret();
455   void ret(const Immediate& imm);
456 
457   void nop();
458   void int3();
459   void hlt();
460 
461   void j(Condition condition, Label* label);
462 
463   void jmp(Register reg);
464   void jmp(const Address& address);
465   void jmp(Label* label);
466 
467   void repne_scasw();
468 
469   X86Assembler* lock();
470   void cmpxchgl(const Address& address, Register reg);
471   void cmpxchg8b(const Address& address);
472 
473   void mfence();
474 
475   X86Assembler* fs();
476   X86Assembler* gs();
477 
478   //
479   // Macros for High-level operations.
480   //
481 
482   void AddImmediate(Register reg, const Immediate& imm);
483 
484   void LoadLongConstant(XmmRegister dst, int64_t value);
485   void LoadDoubleConstant(XmmRegister dst, double value);
486 
LockCmpxchgl(const Address & address,Register reg)487   void LockCmpxchgl(const Address& address, Register reg) {
488     lock()->cmpxchgl(address, reg);
489   }
490 
LockCmpxchg8b(const Address & address)491   void LockCmpxchg8b(const Address& address) {
492     lock()->cmpxchg8b(address);
493   }
494 
495   //
496   // Misc. functionality
497   //
PreferredLoopAlignment()498   int PreferredLoopAlignment() { return 16; }
499   void Align(int alignment, int offset);
500   void Bind(Label* label);
501 
502   //
503   // Overridden common assembler high-level functionality
504   //
505 
506   // Emit code that will create an activation on the stack
507   void BuildFrame(size_t frame_size, ManagedRegister method_reg,
508                   const std::vector<ManagedRegister>& callee_save_regs,
509                   const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
510 
511   // Emit code that will remove an activation from the stack
512   void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
513       OVERRIDE;
514 
515   void IncreaseFrameSize(size_t adjust) OVERRIDE;
516   void DecreaseFrameSize(size_t adjust) OVERRIDE;
517 
518   // Store routines
519   void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE;
520   void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE;
521   void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE;
522 
523   void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE;
524 
525   void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister scratch)
526       OVERRIDE;
527 
528   void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs,
529                                   ManagedRegister scratch) OVERRIDE;
530 
531   void StoreStackPointerToThread32(ThreadOffset<4> thr_offs) OVERRIDE;
532 
533   void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
534                      ManagedRegister scratch) OVERRIDE;
535 
536   // Load routines
537   void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
538 
539   void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size) OVERRIDE;
540 
541   void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
542 
543   void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs,
544                bool poison_reference) OVERRIDE;
545 
546   void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
547 
548   void LoadRawPtrFromThread32(ManagedRegister dest, ThreadOffset<4> offs) OVERRIDE;
549 
550   // Copying routines
551   void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE;
552 
553   void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs,
554                               ManagedRegister scratch) OVERRIDE;
555 
556   void CopyRawPtrToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
557       OVERRIDE;
558 
559   void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE;
560 
561   void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE;
562 
563   void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
564             size_t size) OVERRIDE;
565 
566   void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch,
567             size_t size) OVERRIDE;
568 
569   void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch,
570             size_t size) OVERRIDE;
571 
572   void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
573             ManagedRegister scratch, size_t size) OVERRIDE;
574 
575   void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
576             ManagedRegister scratch, size_t size) OVERRIDE;
577 
578   void MemoryBarrier(ManagedRegister) OVERRIDE;
579 
580   // Sign extension
581   void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
582 
583   // Zero extension
584   void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
585 
586   // Exploit fast access in managed code to Thread::Current()
587   void GetCurrentThread(ManagedRegister tr) OVERRIDE;
588   void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE;
589 
590   // Set up out_reg to hold a Object** into the handle scope, or to be null if the
591   // value is null and null_allowed. in_reg holds a possibly stale reference
592   // that can be used to avoid loading the handle scope entry to see if the value is
593   // null.
594   void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset,
595                               ManagedRegister in_reg, bool null_allowed) OVERRIDE;
596 
597   // Set up out_off to hold a Object** into the handle scope, or to be null if the
598   // value is null and null_allowed.
599   void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset,
600                               ManagedRegister scratch, bool null_allowed) OVERRIDE;
601 
602   // src holds a handle scope entry (Object**) load this into dst
603   void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
604 
605   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
606   // know that src may not be null.
607   void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
608   void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
609 
610   // Call to address held at [base+offset]
611   void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
612   void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
613   void CallFromThread32(ThreadOffset<4> offset, ManagedRegister scratch) OVERRIDE;
614 
615   // Generate code to check if Thread::Current()->exception_ is non-null
616   // and branch to a ExceptionSlowPath if it is.
617   void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
618 
619  private:
620   inline void EmitUint8(uint8_t value);
621   inline void EmitInt32(int32_t value);
622   inline void EmitRegisterOperand(int rm, int reg);
623   inline void EmitXmmRegisterOperand(int rm, XmmRegister reg);
624   inline void EmitFixup(AssemblerFixup* fixup);
625   inline void EmitOperandSizeOverride();
626 
627   void EmitOperand(int rm, const Operand& operand);
628   void EmitImmediate(const Immediate& imm);
629   void EmitComplex(int rm, const Operand& operand, const Immediate& immediate);
630   void EmitLabel(Label* label, int instruction_size);
631   void EmitLabelLink(Label* label);
632   void EmitNearLabelLink(Label* label);
633 
634   void EmitGenericShift(int rm, const Operand& operand, const Immediate& imm);
635   void EmitGenericShift(int rm, const Operand& operand, Register shifter);
636 
637   DISALLOW_COPY_AND_ASSIGN(X86Assembler);
638 };
639 
EmitUint8(uint8_t value)640 inline void X86Assembler::EmitUint8(uint8_t value) {
641   buffer_.Emit<uint8_t>(value);
642 }
643 
EmitInt32(int32_t value)644 inline void X86Assembler::EmitInt32(int32_t value) {
645   buffer_.Emit<int32_t>(value);
646 }
647 
EmitRegisterOperand(int rm,int reg)648 inline void X86Assembler::EmitRegisterOperand(int rm, int reg) {
649   CHECK_GE(rm, 0);
650   CHECK_LT(rm, 8);
651   buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg);
652 }
653 
EmitXmmRegisterOperand(int rm,XmmRegister reg)654 inline void X86Assembler::EmitXmmRegisterOperand(int rm, XmmRegister reg) {
655   EmitRegisterOperand(rm, static_cast<Register>(reg));
656 }
657 
EmitFixup(AssemblerFixup * fixup)658 inline void X86Assembler::EmitFixup(AssemblerFixup* fixup) {
659   buffer_.EmitFixup(fixup);
660 }
661 
EmitOperandSizeOverride()662 inline void X86Assembler::EmitOperandSizeOverride() {
663   EmitUint8(0x66);
664 }
665 
666 // Slowpath entered when Thread::Current()->_exception is non-null
667 class X86ExceptionSlowPath FINAL : public SlowPath {
668  public:
X86ExceptionSlowPath(size_t stack_adjust)669   explicit X86ExceptionSlowPath(size_t stack_adjust) : stack_adjust_(stack_adjust) {}
670   virtual void Emit(Assembler *sp_asm) OVERRIDE;
671  private:
672   const size_t stack_adjust_;
673 };
674 
675 }  // namespace x86
676 }  // namespace art
677 
678 #endif  // ART_COMPILER_UTILS_X86_ASSEMBLER_X86_H_
679