blob: 2f293e4a3916b424666565e10741ff5625ce032f [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
Ian Rogers0d666d82011-08-14 16:03:46 -07006#include <vector>
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07007#include "assembler.h"
8#include "constants.h"
9#include "globals.h"
Ian Rogers2c8f6532011-09-02 17:16:34 -070010#include "managed_register_x86.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070011#include "macros.h"
12#include "offsets.h"
13#include "utils.h"
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070014
Carl Shapiro6b6b5f02011-06-21 15:05:09 -070015namespace art {
Ian Rogers2c8f6532011-09-02 17:16:34 -070016namespace x86 {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070017
18class Immediate {
19 public:
20 explicit Immediate(int32_t value) : value_(value) {}
21
22 int32_t value() const { return value_; }
23
24 bool is_int8() const { return IsInt(8, value_); }
25 bool is_uint8() const { return IsUint(8, value_); }
26 bool is_uint16() const { return IsUint(16, value_); }
27
28 private:
29 const int32_t value_;
30
Shih-wei Liao24782c62012-01-08 12:46:11 -080031 // TODO: Remove the #if when Mac OS build server no longer uses GCC 4.2.*.
32#if GCC_VERSION >= 40300
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070033 DISALLOW_COPY_AND_ASSIGN(Immediate);
Shih-wei Liao24782c62012-01-08 12:46:11 -080034#endif
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070035};
36
37
38class Operand {
39 public:
40 uint8_t mod() const {
41 return (encoding_at(0) >> 6) & 3;
42 }
43
44 Register rm() const {
45 return static_cast<Register>(encoding_at(0) & 7);
46 }
47
48 ScaleFactor scale() const {
49 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
50 }
51
52 Register index() const {
53 return static_cast<Register>((encoding_at(1) >> 3) & 7);
54 }
55
56 Register base() const {
57 return static_cast<Register>(encoding_at(1) & 7);
58 }
59
60 int8_t disp8() const {
61 CHECK_GE(length_, 2);
62 return static_cast<int8_t>(encoding_[length_ - 1]);
63 }
64
65 int32_t disp32() const {
66 CHECK_GE(length_, 5);
67 int32_t value;
68 memcpy(&value, &encoding_[length_ - 4], sizeof(value));
69 return value;
70 }
71
72 bool IsRegister(Register reg) const {
73 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only.
74 && ((encoding_[0] & 0x07) == reg); // Register codes match.
75 }
76
77 protected:
78 // Operand can be sub classed (e.g: Address).
79 Operand() : length_(0) { }
80
81 void SetModRM(int mod, Register rm) {
82 CHECK_EQ(mod & ~3, 0);
83 encoding_[0] = (mod << 6) | rm;
84 length_ = 1;
85 }
86
87 void SetSIB(ScaleFactor scale, Register index, Register base) {
88 CHECK_EQ(length_, 1);
89 CHECK_EQ(scale & ~3, 0);
90 encoding_[1] = (scale << 6) | (index << 3) | base;
91 length_ = 2;
92 }
93
94 void SetDisp8(int8_t disp) {
95 CHECK(length_ == 1 || length_ == 2);
96 encoding_[length_++] = static_cast<uint8_t>(disp);
97 }
98
99 void SetDisp32(int32_t disp) {
100 CHECK(length_ == 1 || length_ == 2);
101 int disp_size = sizeof(disp);
102 memmove(&encoding_[length_], &disp, disp_size);
103 length_ += disp_size;
104 }
105
106 private:
107 byte length_;
108 byte encoding_[6];
109 byte padding_;
110
111 explicit Operand(Register reg) { SetModRM(3, reg); }
112
113 // Get the operand encoding byte at the given index.
114 uint8_t encoding_at(int index) const {
115 CHECK_GE(index, 0);
116 CHECK_LT(index, length_);
117 return encoding_[index];
118 }
119
Ian Rogers2c8f6532011-09-02 17:16:34 -0700120 friend class X86Assembler;
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700121
Shih-wei Liao24782c62012-01-08 12:46:11 -0800122 // TODO: Remove the #if when Mac OS build server no longer uses GCC 4.2.*.
123#if GCC_VERSION >= 40300
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700124 DISALLOW_COPY_AND_ASSIGN(Operand);
Shih-wei Liao24782c62012-01-08 12:46:11 -0800125#endif
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700126};
127
128
129class Address : public Operand {
130 public:
131 Address(Register base, int32_t disp) {
Ian Rogersb033c752011-07-20 12:22:35 -0700132 Init(base, disp);
133 }
134
Ian Rogersa04d3972011-08-17 11:33:44 -0700135 Address(Register base, Offset disp) {
136 Init(base, disp.Int32Value());
137 }
138
Ian Rogersb033c752011-07-20 12:22:35 -0700139 Address(Register base, FrameOffset disp) {
140 CHECK_EQ(base, ESP);
141 Init(ESP, disp.Int32Value());
142 }
143
144 Address(Register base, MemberOffset disp) {
145 Init(base, disp.Int32Value());
146 }
147
148 void Init(Register base, int32_t disp) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700149 if (disp == 0 && base != EBP) {
150 SetModRM(0, base);
151 if (base == ESP) SetSIB(TIMES_1, ESP, base);
152 } else if (disp >= -128 && disp <= 127) {
153 SetModRM(1, base);
154 if (base == ESP) SetSIB(TIMES_1, ESP, base);
155 SetDisp8(disp);
156 } else {
157 SetModRM(2, base);
158 if (base == ESP) SetSIB(TIMES_1, ESP, base);
159 SetDisp32(disp);
160 }
161 }
162
Ian Rogersb033c752011-07-20 12:22:35 -0700163
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700164 Address(Register index, ScaleFactor scale, int32_t disp) {
165 CHECK_NE(index, ESP); // Illegal addressing mode.
166 SetModRM(0, ESP);
167 SetSIB(scale, index, EBP);
168 SetDisp32(disp);
169 }
170
171 Address(Register base, Register index, ScaleFactor scale, int32_t disp) {
172 CHECK_NE(index, ESP); // Illegal addressing mode.
173 if (disp == 0 && base != EBP) {
174 SetModRM(0, ESP);
175 SetSIB(scale, index, base);
176 } else if (disp >= -128 && disp <= 127) {
177 SetModRM(1, ESP);
178 SetSIB(scale, index, base);
179 SetDisp8(disp);
180 } else {
181 SetModRM(2, ESP);
182 SetSIB(scale, index, base);
183 SetDisp32(disp);
184 }
185 }
186
Carl Shapiro69759ea2011-07-21 18:13:35 -0700187 static Address Absolute(uword addr) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700188 Address result;
189 result.SetModRM(0, EBP);
190 result.SetDisp32(addr);
191 return result;
192 }
193
Ian Rogersb033c752011-07-20 12:22:35 -0700194 static Address Absolute(ThreadOffset addr) {
195 return Absolute(addr.Int32Value());
196 }
197
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700198 private:
199 Address() {}
200
Shih-wei Liao24782c62012-01-08 12:46:11 -0800201 // TODO: Remove the #if when Mac OS build server no longer uses GCC 4.2.*.
202#if GCC_VERSION >= 40300
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700203 DISALLOW_COPY_AND_ASSIGN(Address);
Shih-wei Liao24782c62012-01-08 12:46:11 -0800204#endif
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700205};
206
207
Ian Rogers2c8f6532011-09-02 17:16:34 -0700208class X86Assembler : public Assembler {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700209 public:
Ian Rogers2c8f6532011-09-02 17:16:34 -0700210 X86Assembler() {}
211 virtual ~X86Assembler() {}
buzbeec143c552011-08-20 17:38:58 -0700212
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700213 /*
214 * Emit Machine Instructions.
215 */
216 void call(Register reg);
217 void call(const Address& address);
218 void call(Label* label);
219
220 void pushl(Register reg);
221 void pushl(const Address& address);
222 void pushl(const Immediate& imm);
223
224 void popl(Register reg);
225 void popl(const Address& address);
226
227 void movl(Register dst, const Immediate& src);
228 void movl(Register dst, Register src);
229
230 void movl(Register dst, const Address& src);
231 void movl(const Address& dst, Register src);
232 void movl(const Address& dst, const Immediate& imm);
Ian Rogersbdb03912011-09-14 00:55:44 -0700233 void movl(const Address& dst, Label* lbl);
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700234
235 void movzxb(Register dst, ByteRegister src);
236 void movzxb(Register dst, const Address& src);
237 void movsxb(Register dst, ByteRegister src);
238 void movsxb(Register dst, const Address& src);
239 void movb(Register dst, const Address& src);
240 void movb(const Address& dst, ByteRegister src);
241 void movb(const Address& dst, const Immediate& imm);
242
243 void movzxw(Register dst, Register src);
244 void movzxw(Register dst, const Address& src);
245 void movsxw(Register dst, Register src);
246 void movsxw(Register dst, const Address& src);
247 void movw(Register dst, const Address& src);
248 void movw(const Address& dst, Register src);
249
250 void leal(Register dst, const Address& src);
251
Ian Rogersb033c752011-07-20 12:22:35 -0700252 void cmovl(Condition condition, Register dst, Register src);
253
254 void setb(Condition condition, Register dst);
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700255
256 void movss(XmmRegister dst, const Address& src);
257 void movss(const Address& dst, XmmRegister src);
258 void movss(XmmRegister dst, XmmRegister src);
259
260 void movd(XmmRegister dst, Register src);
261 void movd(Register dst, XmmRegister src);
262
263 void addss(XmmRegister dst, XmmRegister src);
264 void addss(XmmRegister dst, const Address& src);
265 void subss(XmmRegister dst, XmmRegister src);
266 void subss(XmmRegister dst, const Address& src);
267 void mulss(XmmRegister dst, XmmRegister src);
268 void mulss(XmmRegister dst, const Address& src);
269 void divss(XmmRegister dst, XmmRegister src);
270 void divss(XmmRegister dst, const Address& src);
271
272 void movsd(XmmRegister dst, const Address& src);
273 void movsd(const Address& dst, XmmRegister src);
274 void movsd(XmmRegister dst, XmmRegister src);
275
276 void addsd(XmmRegister dst, XmmRegister src);
277 void addsd(XmmRegister dst, const Address& src);
278 void subsd(XmmRegister dst, XmmRegister src);
279 void subsd(XmmRegister dst, const Address& src);
280 void mulsd(XmmRegister dst, XmmRegister src);
281 void mulsd(XmmRegister dst, const Address& src);
282 void divsd(XmmRegister dst, XmmRegister src);
283 void divsd(XmmRegister dst, const Address& src);
284
285 void cvtsi2ss(XmmRegister dst, Register src);
286 void cvtsi2sd(XmmRegister dst, Register src);
287
288 void cvtss2si(Register dst, XmmRegister src);
289 void cvtss2sd(XmmRegister dst, XmmRegister src);
290
291 void cvtsd2si(Register dst, XmmRegister src);
292 void cvtsd2ss(XmmRegister dst, XmmRegister src);
293
294 void cvttss2si(Register dst, XmmRegister src);
295 void cvttsd2si(Register dst, XmmRegister src);
296
297 void cvtdq2pd(XmmRegister dst, XmmRegister src);
298
299 void comiss(XmmRegister a, XmmRegister b);
300 void comisd(XmmRegister a, XmmRegister b);
301
302 void sqrtsd(XmmRegister dst, XmmRegister src);
303 void sqrtss(XmmRegister dst, XmmRegister src);
304
305 void xorpd(XmmRegister dst, const Address& src);
306 void xorpd(XmmRegister dst, XmmRegister src);
307 void xorps(XmmRegister dst, const Address& src);
308 void xorps(XmmRegister dst, XmmRegister src);
309
310 void andpd(XmmRegister dst, const Address& src);
311
312 void flds(const Address& src);
313 void fstps(const Address& dst);
314
315 void fldl(const Address& src);
316 void fstpl(const Address& dst);
317
318 void fnstcw(const Address& dst);
319 void fldcw(const Address& src);
320
321 void fistpl(const Address& dst);
322 void fistps(const Address& dst);
323 void fildl(const Address& src);
324
325 void fincstp();
326 void ffree(const Immediate& index);
327
328 void fsin();
329 void fcos();
330 void fptan();
331
332 void xchgl(Register dst, Register src);
333
334 void cmpl(Register reg, const Immediate& imm);
335 void cmpl(Register reg0, Register reg1);
336 void cmpl(Register reg, const Address& address);
337
338 void cmpl(const Address& address, Register reg);
339 void cmpl(const Address& address, const Immediate& imm);
340
341 void testl(Register reg1, Register reg2);
342 void testl(Register reg, const Immediate& imm);
343
344 void andl(Register dst, const Immediate& imm);
345 void andl(Register dst, Register src);
346
347 void orl(Register dst, const Immediate& imm);
348 void orl(Register dst, Register src);
349
350 void xorl(Register dst, Register src);
351
352 void addl(Register dst, Register src);
353 void addl(Register reg, const Immediate& imm);
354 void addl(Register reg, const Address& address);
355
356 void addl(const Address& address, Register reg);
357 void addl(const Address& address, const Immediate& imm);
358
359 void adcl(Register dst, Register src);
360 void adcl(Register reg, const Immediate& imm);
361 void adcl(Register dst, const Address& address);
362
363 void subl(Register dst, Register src);
364 void subl(Register reg, const Immediate& imm);
365 void subl(Register reg, const Address& address);
366
367 void cdq();
368
369 void idivl(Register reg);
370
371 void imull(Register dst, Register src);
372 void imull(Register reg, const Immediate& imm);
373 void imull(Register reg, const Address& address);
374
375 void imull(Register reg);
376 void imull(const Address& address);
377
378 void mull(Register reg);
379 void mull(const Address& address);
380
381 void sbbl(Register dst, Register src);
382 void sbbl(Register reg, const Immediate& imm);
383 void sbbl(Register reg, const Address& address);
384
385 void incl(Register reg);
386 void incl(const Address& address);
387
388 void decl(Register reg);
389 void decl(const Address& address);
390
391 void shll(Register reg, const Immediate& imm);
392 void shll(Register operand, Register shifter);
393 void shrl(Register reg, const Immediate& imm);
394 void shrl(Register operand, Register shifter);
395 void sarl(Register reg, const Immediate& imm);
396 void sarl(Register operand, Register shifter);
397 void shld(Register dst, Register src);
398
399 void negl(Register reg);
400 void notl(Register reg);
401
402 void enter(const Immediate& imm);
403 void leave();
404
405 void ret();
406 void ret(const Immediate& imm);
407
408 void nop();
409 void int3();
410 void hlt();
411
412 void j(Condition condition, Label* label);
413
414 void jmp(Register reg);
415 void jmp(Label* label);
416
Ian Rogers2c8f6532011-09-02 17:16:34 -0700417 X86Assembler* lock();
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700418 void cmpxchgl(const Address& address, Register reg);
419
Ian Rogers2c8f6532011-09-02 17:16:34 -0700420 X86Assembler* fs();
Ian Rogersb033c752011-07-20 12:22:35 -0700421
422 //
423 // Macros for High-level operations.
424 //
425
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700426 void AddImmediate(Register reg, const Immediate& imm);
427
428 void LoadDoubleConstant(XmmRegister dst, double value);
429
430 void DoubleNegate(XmmRegister d);
431 void FloatNegate(XmmRegister f);
432
433 void DoubleAbs(XmmRegister reg);
434
435 void LockCmpxchgl(const Address& address, Register reg) {
Ian Rogers0d666d82011-08-14 16:03:46 -0700436 lock()->cmpxchgl(address, reg);
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700437 }
438
Ian Rogersb033c752011-07-20 12:22:35 -0700439 //
440 // Misc. functionality
441 //
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700442 int PreferredLoopAlignment() { return 16; }
443 void Align(int alignment, int offset);
444 void Bind(Label* label);
445
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700446 // Debugging and bringup support.
447 void Stop(const char* message);
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700448
449 static void InitializeMemoryWithBreakpoints(byte* data, size_t length);
450
Ian Rogers2c8f6532011-09-02 17:16:34 -0700451 //
452 // Overridden common assembler high-level functionality
453 //
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700454
Ian Rogers2c8f6532011-09-02 17:16:34 -0700455 // Emit code that will create an activation on the stack
456 virtual void BuildFrame(size_t frame_size, ManagedRegister method_reg,
Ian Rogersbdb03912011-09-14 00:55:44 -0700457 const std::vector<ManagedRegister>& callee_save_regs);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700458
459 // Emit code that will remove an activation from the stack
460 virtual void RemoveFrame(size_t frame_size,
Ian Rogersbdb03912011-09-14 00:55:44 -0700461 const std::vector<ManagedRegister>& callee_save_regs);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700462
463 virtual void IncreaseFrameSize(size_t adjust);
464 virtual void DecreaseFrameSize(size_t adjust);
465
466 // Store routines
467 virtual void Store(FrameOffset offs, ManagedRegister src, size_t size);
468 virtual void StoreRef(FrameOffset dest, ManagedRegister src);
469 virtual void StoreRawPtr(FrameOffset dest, ManagedRegister src);
470
471 virtual void StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
472 ManagedRegister scratch);
473
474 virtual void StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
475 ManagedRegister scratch);
476
477 virtual void StoreStackOffsetToThread(ThreadOffset thr_offs,
478 FrameOffset fr_offs,
479 ManagedRegister scratch);
480
481 virtual void StoreStackPointerToThread(ThreadOffset thr_offs);
482
Ian Rogersbdb03912011-09-14 00:55:44 -0700483 void StoreLabelToThread(ThreadOffset thr_offs, Label* lbl);
484
Ian Rogers2c8f6532011-09-02 17:16:34 -0700485 virtual void StoreSpanning(FrameOffset dest, ManagedRegister src,
486 FrameOffset in_off, ManagedRegister scratch);
487
488 // Load routines
489 virtual void Load(ManagedRegister dest, FrameOffset src, size_t size);
490
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700491 virtual void Load(ManagedRegister dest, ThreadOffset src, size_t size);
492
Ian Rogers2c8f6532011-09-02 17:16:34 -0700493 virtual void LoadRef(ManagedRegister dest, FrameOffset src);
494
495 virtual void LoadRef(ManagedRegister dest, ManagedRegister base,
496 MemberOffset offs);
497
498 virtual void LoadRawPtr(ManagedRegister dest, ManagedRegister base,
499 Offset offs);
500
501 virtual void LoadRawPtrFromThread(ManagedRegister dest,
502 ThreadOffset offs);
503
504 // Copying routines
505 virtual void Move(ManagedRegister dest, ManagedRegister src);
506
507 virtual void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset thr_offs,
508 ManagedRegister scratch);
509
510 virtual void CopyRawPtrToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
511 ManagedRegister scratch);
512
513 virtual void CopyRef(FrameOffset dest, FrameOffset src,
514 ManagedRegister scratch);
515
Elliott Hughesa09aea22012-01-06 18:58:27 -0800516 virtual void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700517
Ian Rogersdc51b792011-09-22 20:41:37 -0700518 virtual void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
519 ManagedRegister scratch, size_t size);
520
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700521 virtual void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
522 ManagedRegister scratch, size_t size);
523
Ian Rogersdc51b792011-09-22 20:41:37 -0700524 virtual void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset,
525 ManagedRegister scratch, size_t size);
526
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700527 virtual void Copy(ManagedRegister dest, Offset dest_offset,
528 ManagedRegister src, Offset src_offset,
529 ManagedRegister scratch, size_t size);
530
531 virtual void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
532 ManagedRegister scratch, size_t size);
Ian Rogersdc51b792011-09-22 20:41:37 -0700533
Ian Rogerse5de95b2011-09-18 20:31:38 -0700534 virtual void MemoryBarrier(ManagedRegister);
535
Ian Rogers2c8f6532011-09-02 17:16:34 -0700536 // Exploit fast access in managed code to Thread::Current()
537 virtual void GetCurrentThread(ManagedRegister tr);
538 virtual void GetCurrentThread(FrameOffset dest_offset,
539 ManagedRegister scratch);
540
541 // Set up out_reg to hold a Object** into the SIRT, or to be NULL if the
542 // value is null and null_allowed. in_reg holds a possibly stale reference
543 // that can be used to avoid loading the SIRT entry to see if the value is
544 // NULL.
545 virtual void CreateSirtEntry(ManagedRegister out_reg, FrameOffset sirt_offset,
546 ManagedRegister in_reg, bool null_allowed);
547
548 // Set up out_off to hold a Object** into the SIRT, or to be NULL if the
549 // value is null and null_allowed.
550 virtual void CreateSirtEntry(FrameOffset out_off, FrameOffset sirt_offset,
551 ManagedRegister scratch, bool null_allowed);
552
553 // src holds a SIRT entry (Object**) load this into dst
554 virtual void LoadReferenceFromSirt(ManagedRegister dst,
555 ManagedRegister src);
556
557 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
558 // know that src may not be null.
559 virtual void VerifyObject(ManagedRegister src, bool could_be_null);
560 virtual void VerifyObject(FrameOffset src, bool could_be_null);
561
562 // Call to address held at [base+offset]
563 virtual void Call(ManagedRegister base, Offset offset,
564 ManagedRegister scratch);
565 virtual void Call(FrameOffset base, Offset offset,
566 ManagedRegister scratch);
Ian Rogersbdb03912011-09-14 00:55:44 -0700567 virtual void Call(ThreadOffset offset, ManagedRegister scratch);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700568
569 // Generate code to check if Thread::Current()->suspend_count_ is non-zero
570 // and branch to a SuspendSlowPath if it is. The SuspendSlowPath will continue
571 // at the next instruction.
572 virtual void SuspendPoll(ManagedRegister scratch, ManagedRegister return_reg,
573 FrameOffset return_save_location,
574 size_t return_size);
575
576 // Generate code to check if Thread::Current()->exception_ is non-null
577 // and branch to a ExceptionSlowPath if it is.
578 virtual void ExceptionPoll(ManagedRegister scratch);
579
580 private:
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700581 inline void EmitUint8(uint8_t value);
582 inline void EmitInt32(int32_t value);
583 inline void EmitRegisterOperand(int rm, int reg);
584 inline void EmitXmmRegisterOperand(int rm, XmmRegister reg);
585 inline void EmitFixup(AssemblerFixup* fixup);
586 inline void EmitOperandSizeOverride();
587
588 void EmitOperand(int rm, const Operand& operand);
589 void EmitImmediate(const Immediate& imm);
590 void EmitComplex(int rm, const Operand& operand, const Immediate& immediate);
591 void EmitLabel(Label* label, int instruction_size);
592 void EmitLabelLink(Label* label);
593 void EmitNearLabelLink(Label* label);
594
595 void EmitGenericShift(int rm, Register reg, const Immediate& imm);
596 void EmitGenericShift(int rm, Register operand, Register shifter);
597
Ian Rogers2c8f6532011-09-02 17:16:34 -0700598 DISALLOW_COPY_AND_ASSIGN(X86Assembler);
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700599};
600
Ian Rogers2c8f6532011-09-02 17:16:34 -0700601inline void X86Assembler::EmitUint8(uint8_t value) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700602 buffer_.Emit<uint8_t>(value);
603}
604
Ian Rogers2c8f6532011-09-02 17:16:34 -0700605inline void X86Assembler::EmitInt32(int32_t value) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700606 buffer_.Emit<int32_t>(value);
607}
608
Ian Rogers2c8f6532011-09-02 17:16:34 -0700609inline void X86Assembler::EmitRegisterOperand(int rm, int reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700610 CHECK_GE(rm, 0);
611 CHECK_LT(rm, 8);
612 buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg);
613}
614
Ian Rogers2c8f6532011-09-02 17:16:34 -0700615inline void X86Assembler::EmitXmmRegisterOperand(int rm, XmmRegister reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700616 EmitRegisterOperand(rm, static_cast<Register>(reg));
617}
618
Ian Rogers2c8f6532011-09-02 17:16:34 -0700619inline void X86Assembler::EmitFixup(AssemblerFixup* fixup) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700620 buffer_.EmitFixup(fixup);
621}
622
Ian Rogers2c8f6532011-09-02 17:16:34 -0700623inline void X86Assembler::EmitOperandSizeOverride() {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700624 EmitUint8(0x66);
625}
626
Ian Rogers2c8f6532011-09-02 17:16:34 -0700627// Slowpath entered when Thread::Current()->_exception is non-null
628class X86ExceptionSlowPath : public SlowPath {
629 public:
630 X86ExceptionSlowPath() {}
631 virtual void Emit(Assembler *sp_asm);
632};
633
634// Slowpath entered when Thread::Current()->_suspend_count is non-zero
635class X86SuspendCountSlowPath : public SlowPath {
636 public:
637 X86SuspendCountSlowPath(X86ManagedRegister return_reg,
638 FrameOffset return_save_location,
639 size_t return_size) :
640 return_register_(return_reg), return_save_location_(return_save_location),
641 return_size_(return_size) {}
642 virtual void Emit(Assembler *sp_asm);
643
644 private:
645 // Remember how to save the return value
646 const X86ManagedRegister return_register_;
647 const FrameOffset return_save_location_;
648 const size_t return_size_;
649};
650
651} // namespace x86
Carl Shapiro6b6b5f02011-06-21 15:05:09 -0700652} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700653
654#endif // ART_SRC_ASSEMBLER_X86_H_