assembler_x86.h revision 6b6b5f0e67ce03f38223a525612955663bc1799b
1// Copyright 2011 Google Inc. All Rights Reserved.
2
3#ifndef ART_SRC_ASSEMBLER_X86_H_
4#define ART_SRC_ASSEMBLER_X86_H_
5
6#include <stdint.h>
7#include <string.h>
8#include "src/constants_x86.h"
9#include "src/macros.h"
10#include "src/utils.h"
11
12namespace art {
13
14class Immediate {
15 public:
16  explicit Immediate(int32_t value) : value_(value) {}
17
18  int32_t value() const { return value_; }
19
20  bool is_int8() const { return IsInt(8, value_); }
21  bool is_uint8() const { return IsUint(8, value_); }
22  bool is_uint16() const { return IsUint(16, value_); }
23
24 private:
25  const int32_t value_;
26
27  DISALLOW_COPY_AND_ASSIGN(Immediate);
28};
29
30
31class Operand {
32 public:
33  uint8_t mod() const {
34    return (encoding_at(0) >> 6) & 3;
35  }
36
37  Register rm() const {
38    return static_cast<Register>(encoding_at(0) & 7);
39  }
40
41  ScaleFactor scale() const {
42    return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
43  }
44
45  Register index() const {
46    return static_cast<Register>((encoding_at(1) >> 3) & 7);
47  }
48
49  Register base() const {
50    return static_cast<Register>(encoding_at(1) & 7);
51  }
52
53  int8_t disp8() const {
54    CHECK_GE(length_, 2);
55    return static_cast<int8_t>(encoding_[length_ - 1]);
56  }
57
58  int32_t disp32() const {
59    CHECK_GE(length_, 5);
60    int32_t value;
61    memcpy(&value, &encoding_[length_ - 4], sizeof(value));
62    return value;
63  }
64
65  bool IsRegister(Register reg) const {
66    return ((encoding_[0] & 0xF8) == 0xC0)  // Addressing mode is register only.
67        && ((encoding_[0] & 0x07) == reg);  // Register codes match.
68  }
69
70 protected:
71  // Operand can be sub classed (e.g: Address).
72  Operand() : length_(0) { }
73
74  void SetModRM(int mod, Register rm) {
75    CHECK_EQ(mod & ~3, 0);
76    encoding_[0] = (mod << 6) | rm;
77    length_ = 1;
78  }
79
80  void SetSIB(ScaleFactor scale, Register index, Register base) {
81    CHECK_EQ(length_, 1);
82    CHECK_EQ(scale & ~3, 0);
83    encoding_[1] = (scale << 6) | (index << 3) | base;
84    length_ = 2;
85  }
86
87  void SetDisp8(int8_t disp) {
88    CHECK(length_ == 1 || length_ == 2);
89    encoding_[length_++] = static_cast<uint8_t>(disp);
90  }
91
92  void SetDisp32(int32_t disp) {
93    CHECK(length_ == 1 || length_ == 2);
94    int disp_size = sizeof(disp);
95    memmove(&encoding_[length_], &disp, disp_size);
96    length_ += disp_size;
97  }
98
99 private:
100  byte length_;
101  byte encoding_[6];
102  byte padding_;
103
104  explicit Operand(Register reg) { SetModRM(3, reg); }
105
106  // Get the operand encoding byte at the given index.
107  uint8_t encoding_at(int index) const {
108    CHECK_GE(index, 0);
109    CHECK_LT(index, length_);
110    return encoding_[index];
111  }
112
113  friend class Assembler;
114
115  DISALLOW_COPY_AND_ASSIGN(Operand);
116};
117
118
119class Address : public Operand {
120 public:
121  Address(Register base, int32_t disp) {
122    if (disp == 0 && base != EBP) {
123      SetModRM(0, base);
124      if (base == ESP) SetSIB(TIMES_1, ESP, base);
125    } else if (disp >= -128 && disp <= 127) {
126      SetModRM(1, base);
127      if (base == ESP) SetSIB(TIMES_1, ESP, base);
128      SetDisp8(disp);
129    } else {
130      SetModRM(2, base);
131      if (base == ESP) SetSIB(TIMES_1, ESP, base);
132      SetDisp32(disp);
133    }
134  }
135
136  Address(Register index, ScaleFactor scale, int32_t disp) {
137    CHECK_NE(index, ESP);  // Illegal addressing mode.
138    SetModRM(0, ESP);
139    SetSIB(scale, index, EBP);
140    SetDisp32(disp);
141  }
142
143  Address(Register base, Register index, ScaleFactor scale, int32_t disp) {
144    CHECK_NE(index, ESP);  // Illegal addressing mode.
145    if (disp == 0 && base != EBP) {
146      SetModRM(0, ESP);
147      SetSIB(scale, index, base);
148    } else if (disp >= -128 && disp <= 127) {
149      SetModRM(1, ESP);
150      SetSIB(scale, index, base);
151      SetDisp8(disp);
152    } else {
153      SetModRM(2, ESP);
154      SetSIB(scale, index, base);
155      SetDisp32(disp);
156    }
157  }
158
159  static Address Absolute(const uword addr) {
160    Address result;
161    result.SetModRM(0, EBP);
162    result.SetDisp32(addr);
163    return result;
164  }
165
166 private:
167  Address() {}
168
169  DISALLOW_COPY_AND_ASSIGN(Address);
170};
171
172
173class Assembler {
174 public:
175  Assembler() : buffer_() {}
176  ~Assembler() {}
177
178  /*
179   * Emit Machine Instructions.
180   */
181  void call(Register reg);
182  void call(const Address& address);
183  void call(Label* label);
184
185  void pushl(Register reg);
186  void pushl(const Address& address);
187  void pushl(const Immediate& imm);
188
189  void popl(Register reg);
190  void popl(const Address& address);
191
192  void movl(Register dst, const Immediate& src);
193  void movl(Register dst, Register src);
194
195  void movl(Register dst, const Address& src);
196  void movl(const Address& dst, Register src);
197  void movl(const Address& dst, const Immediate& imm);
198
199  void movzxb(Register dst, ByteRegister src);
200  void movzxb(Register dst, const Address& src);
201  void movsxb(Register dst, ByteRegister src);
202  void movsxb(Register dst, const Address& src);
203  void movb(Register dst, const Address& src);
204  void movb(const Address& dst, ByteRegister src);
205  void movb(const Address& dst, const Immediate& imm);
206
207  void movzxw(Register dst, Register src);
208  void movzxw(Register dst, const Address& src);
209  void movsxw(Register dst, Register src);
210  void movsxw(Register dst, const Address& src);
211  void movw(Register dst, const Address& src);
212  void movw(const Address& dst, Register src);
213
214  void leal(Register dst, const Address& src);
215
216  void cmovs(Register dst, Register src);
217  void cmovns(Register dst, Register src);
218
219  void movss(XmmRegister dst, const Address& src);
220  void movss(const Address& dst, XmmRegister src);
221  void movss(XmmRegister dst, XmmRegister src);
222
223  void movd(XmmRegister dst, Register src);
224  void movd(Register dst, XmmRegister src);
225
226  void addss(XmmRegister dst, XmmRegister src);
227  void addss(XmmRegister dst, const Address& src);
228  void subss(XmmRegister dst, XmmRegister src);
229  void subss(XmmRegister dst, const Address& src);
230  void mulss(XmmRegister dst, XmmRegister src);
231  void mulss(XmmRegister dst, const Address& src);
232  void divss(XmmRegister dst, XmmRegister src);
233  void divss(XmmRegister dst, const Address& src);
234
235  void movsd(XmmRegister dst, const Address& src);
236  void movsd(const Address& dst, XmmRegister src);
237  void movsd(XmmRegister dst, XmmRegister src);
238
239  void addsd(XmmRegister dst, XmmRegister src);
240  void addsd(XmmRegister dst, const Address& src);
241  void subsd(XmmRegister dst, XmmRegister src);
242  void subsd(XmmRegister dst, const Address& src);
243  void mulsd(XmmRegister dst, XmmRegister src);
244  void mulsd(XmmRegister dst, const Address& src);
245  void divsd(XmmRegister dst, XmmRegister src);
246  void divsd(XmmRegister dst, const Address& src);
247
248  void cvtsi2ss(XmmRegister dst, Register src);
249  void cvtsi2sd(XmmRegister dst, Register src);
250
251  void cvtss2si(Register dst, XmmRegister src);
252  void cvtss2sd(XmmRegister dst, XmmRegister src);
253
254  void cvtsd2si(Register dst, XmmRegister src);
255  void cvtsd2ss(XmmRegister dst, XmmRegister src);
256
257  void cvttss2si(Register dst, XmmRegister src);
258  void cvttsd2si(Register dst, XmmRegister src);
259
260  void cvtdq2pd(XmmRegister dst, XmmRegister src);
261
262  void comiss(XmmRegister a, XmmRegister b);
263  void comisd(XmmRegister a, XmmRegister b);
264
265  void sqrtsd(XmmRegister dst, XmmRegister src);
266  void sqrtss(XmmRegister dst, XmmRegister src);
267
268  void xorpd(XmmRegister dst, const Address& src);
269  void xorpd(XmmRegister dst, XmmRegister src);
270  void xorps(XmmRegister dst, const Address& src);
271  void xorps(XmmRegister dst, XmmRegister src);
272
273  void andpd(XmmRegister dst, const Address& src);
274
275  void flds(const Address& src);
276  void fstps(const Address& dst);
277
278  void fldl(const Address& src);
279  void fstpl(const Address& dst);
280
281  void fnstcw(const Address& dst);
282  void fldcw(const Address& src);
283
284  void fistpl(const Address& dst);
285  void fistps(const Address& dst);
286  void fildl(const Address& src);
287
288  void fincstp();
289  void ffree(const Immediate& index);
290
291  void fsin();
292  void fcos();
293  void fptan();
294
295  void xchgl(Register dst, Register src);
296
297  void cmpl(Register reg, const Immediate& imm);
298  void cmpl(Register reg0, Register reg1);
299  void cmpl(Register reg, const Address& address);
300
301  void cmpl(const Address& address, Register reg);
302  void cmpl(const Address& address, const Immediate& imm);
303
304  void testl(Register reg1, Register reg2);
305  void testl(Register reg, const Immediate& imm);
306
307  void andl(Register dst, const Immediate& imm);
308  void andl(Register dst, Register src);
309
310  void orl(Register dst, const Immediate& imm);
311  void orl(Register dst, Register src);
312
313  void xorl(Register dst, Register src);
314
315  void addl(Register dst, Register src);
316  void addl(Register reg, const Immediate& imm);
317  void addl(Register reg, const Address& address);
318
319  void addl(const Address& address, Register reg);
320  void addl(const Address& address, const Immediate& imm);
321
322  void adcl(Register dst, Register src);
323  void adcl(Register reg, const Immediate& imm);
324  void adcl(Register dst, const Address& address);
325
326  void subl(Register dst, Register src);
327  void subl(Register reg, const Immediate& imm);
328  void subl(Register reg, const Address& address);
329
330  void cdq();
331
332  void idivl(Register reg);
333
334  void imull(Register dst, Register src);
335  void imull(Register reg, const Immediate& imm);
336  void imull(Register reg, const Address& address);
337
338  void imull(Register reg);
339  void imull(const Address& address);
340
341  void mull(Register reg);
342  void mull(const Address& address);
343
344  void sbbl(Register dst, Register src);
345  void sbbl(Register reg, const Immediate& imm);
346  void sbbl(Register reg, const Address& address);
347
348  void incl(Register reg);
349  void incl(const Address& address);
350
351  void decl(Register reg);
352  void decl(const Address& address);
353
354  void shll(Register reg, const Immediate& imm);
355  void shll(Register operand, Register shifter);
356  void shrl(Register reg, const Immediate& imm);
357  void shrl(Register operand, Register shifter);
358  void sarl(Register reg, const Immediate& imm);
359  void sarl(Register operand, Register shifter);
360  void shld(Register dst, Register src);
361
362  void negl(Register reg);
363  void notl(Register reg);
364
365  void enter(const Immediate& imm);
366  void leave();
367
368  void ret();
369  void ret(const Immediate& imm);
370
371  void nop();
372  void int3();
373  void hlt();
374
375  void j(Condition condition, Label* label);
376
377  void jmp(Register reg);
378  void jmp(Label* label);
379
380  void lock();
381  void cmpxchgl(const Address& address, Register reg);
382
383  /*
384   * Macros for High-level operations.
385   */
386  void AddImmediate(Register reg, const Immediate& imm);
387
388  void LoadDoubleConstant(XmmRegister dst, double value);
389
390  void DoubleNegate(XmmRegister d);
391  void FloatNegate(XmmRegister f);
392
393  void DoubleAbs(XmmRegister reg);
394
395  void LockCmpxchgl(const Address& address, Register reg) {
396    lock();
397    cmpxchgl(address, reg);
398  }
399
400  /*
401   * Misc. functionality
402   */
403  int PreferredLoopAlignment() { return 16; }
404  void Align(int alignment, int offset);
405  void Bind(Label* label);
406
407  int CodeSize() const { return buffer_.Size(); }
408
409  void FinalizeInstructions(const MemoryRegion& region) {
410    buffer_.FinalizeInstructions(region);
411  }
412
413  // Debugging and bringup support.
414  void Stop(const char* message);
415  void Unimplemented(const char* message);
416  void Untested(const char* message);
417  void Unreachable(const char* message);
418
419  static void InitializeMemoryWithBreakpoints(byte* data, size_t length);
420
421 private:
422  AssemblerBuffer buffer_;
423
424  inline void EmitUint8(uint8_t value);
425  inline void EmitInt32(int32_t value);
426  inline void EmitRegisterOperand(int rm, int reg);
427  inline void EmitXmmRegisterOperand(int rm, XmmRegister reg);
428  inline void EmitFixup(AssemblerFixup* fixup);
429  inline void EmitOperandSizeOverride();
430
431  void EmitOperand(int rm, const Operand& operand);
432  void EmitImmediate(const Immediate& imm);
433  void EmitComplex(int rm, const Operand& operand, const Immediate& immediate);
434  void EmitLabel(Label* label, int instruction_size);
435  void EmitLabelLink(Label* label);
436  void EmitNearLabelLink(Label* label);
437
438  void EmitGenericShift(int rm, Register reg, const Immediate& imm);
439  void EmitGenericShift(int rm, Register operand, Register shifter);
440
441  DISALLOW_COPY_AND_ASSIGN(Assembler);
442};
443
444
445inline void Assembler::EmitUint8(uint8_t value) {
446  buffer_.Emit<uint8_t>(value);
447}
448
449
450inline void Assembler::EmitInt32(int32_t value) {
451  buffer_.Emit<int32_t>(value);
452}
453
454
455inline void Assembler::EmitRegisterOperand(int rm, int reg) {
456  CHECK_GE(rm, 0);
457  CHECK_LT(rm, 8);
458  buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg);
459}
460
461
462inline void Assembler::EmitXmmRegisterOperand(int rm, XmmRegister reg) {
463  EmitRegisterOperand(rm, static_cast<Register>(reg));
464}
465
466
467inline void Assembler::EmitFixup(AssemblerFixup* fixup) {
468  buffer_.EmitFixup(fixup);
469}
470
471
472inline void Assembler::EmitOperandSizeOverride() {
473  EmitUint8(0x66);
474}
475
476}  // namespace art
477
478#endif  // ART_SRC_ASSEMBLER_X86_H_
479