blob: c1c16c7e70b9313ae10ae6c9007de480db786207 [file] [log] [blame]
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001// 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
Carl Shapiro6b6b5f02011-06-21 15:05:09 -070012namespace art {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070013
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
Carl Shapiro6b6b5f02011-06-21 15:05:09 -0700476} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700477
478#endif // ART_SRC_ASSEMBLER_X86_H_