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