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