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