blob: e3779169ed7867bfaacaabb290c2688cf4b489c7 [file] [log] [blame]
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07003#include "assembler.h"
4#include "casts.h"
5#include "globals.h"
6#include "memory_region.h"
7#include "offsets.h"
8#include "thread.h"
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07009
Carl Shapiro6b6b5f02011-06-21 15:05:09 -070010namespace art {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070011
12class DirectCallRelocation : public AssemblerFixup {
13 public:
14 void Process(const MemoryRegion& region, int position) {
15 // Direct calls are relative to the following instruction on x86.
16 int32_t pointer = region.Load<int32_t>(position);
17 int32_t start = reinterpret_cast<int32_t>(region.start());
18 int32_t delta = start + position + sizeof(int32_t);
19 region.Store<int32_t>(position, pointer - delta);
20 }
21};
22
Elliott Hughes1f359b02011-07-17 14:27:17 -070023static const char* kRegisterNames[] = {
24 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
25};
26std::ostream& operator<<(std::ostream& os, const Register& rhs) {
27 if (rhs >= EAX && rhs <= EDI) {
28 os << kRegisterNames[rhs];
29 } else {
Ian Rogersb033c752011-07-20 12:22:35 -070030 os << "Register[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -070031 }
32 return os;
33}
34
Ian Rogersb033c752011-07-20 12:22:35 -070035std::ostream& operator<<(std::ostream& os, const XmmRegister& reg) {
36 return os << "XMM" << static_cast<int>(reg);
37}
38
39std::ostream& operator<<(std::ostream& os, const X87Register& reg) {
40 return os << "ST" << static_cast<int>(reg);
41}
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070042
43void Assembler::InitializeMemoryWithBreakpoints(byte* data, size_t length) {
44 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length);
45}
46
47
48void Assembler::call(Register reg) {
49 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
50 EmitUint8(0xFF);
51 EmitRegisterOperand(2, reg);
52}
53
54
55void Assembler::call(const Address& address) {
56 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
57 EmitUint8(0xFF);
58 EmitOperand(2, address);
59}
60
61
62void Assembler::call(Label* label) {
63 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
64 EmitUint8(0xE8);
65 static const int kSize = 5;
66 EmitLabel(label, kSize);
67}
68
69
70void Assembler::pushl(Register reg) {
71 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
72 EmitUint8(0x50 + reg);
73}
74
75
76void Assembler::pushl(const Address& address) {
77 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
78 EmitUint8(0xFF);
79 EmitOperand(6, address);
80}
81
82
83void Assembler::pushl(const Immediate& imm) {
84 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
85 EmitUint8(0x68);
86 EmitImmediate(imm);
87}
88
89
90void Assembler::popl(Register reg) {
91 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
92 EmitUint8(0x58 + reg);
93}
94
95
96void Assembler::popl(const Address& address) {
97 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
98 EmitUint8(0x8F);
99 EmitOperand(0, address);
100}
101
102
103void Assembler::movl(Register dst, const Immediate& imm) {
104 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
105 EmitUint8(0xB8 + dst);
106 EmitImmediate(imm);
107}
108
109
110void Assembler::movl(Register dst, Register src) {
111 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
112 EmitUint8(0x89);
113 EmitRegisterOperand(src, dst);
114}
115
116
117void Assembler::movl(Register dst, const Address& src) {
118 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
119 EmitUint8(0x8B);
120 EmitOperand(dst, src);
121}
122
123
124void Assembler::movl(const Address& dst, Register src) {
125 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
126 EmitUint8(0x89);
127 EmitOperand(src, dst);
128}
129
130
131void Assembler::movl(const Address& dst, const Immediate& imm) {
132 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
133 EmitUint8(0xC7);
134 EmitOperand(0, dst);
135 EmitImmediate(imm);
136}
137
138
139void Assembler::movzxb(Register dst, ByteRegister src) {
140 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
141 EmitUint8(0x0F);
142 EmitUint8(0xB6);
143 EmitRegisterOperand(dst, src);
144}
145
146
147void Assembler::movzxb(Register dst, const Address& src) {
148 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
149 EmitUint8(0x0F);
150 EmitUint8(0xB6);
151 EmitOperand(dst, src);
152}
153
154
155void Assembler::movsxb(Register dst, ByteRegister src) {
156 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
157 EmitUint8(0x0F);
158 EmitUint8(0xBE);
159 EmitRegisterOperand(dst, src);
160}
161
162
163void Assembler::movsxb(Register dst, const Address& src) {
164 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
165 EmitUint8(0x0F);
166 EmitUint8(0xBE);
167 EmitOperand(dst, src);
168}
169
170
171void Assembler::movb(Register dst, const Address& src) {
172 LOG(FATAL) << "Use movzxb or movsxb instead.";
173}
174
175
176void Assembler::movb(const Address& dst, ByteRegister src) {
177 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
178 EmitUint8(0x88);
179 EmitOperand(src, dst);
180}
181
182
183void Assembler::movb(const Address& dst, const Immediate& imm) {
184 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
185 EmitUint8(0xC6);
186 EmitOperand(EAX, dst);
187 CHECK(imm.is_int8());
188 EmitUint8(imm.value() & 0xFF);
189}
190
191
192void Assembler::movzxw(Register dst, Register src) {
193 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
194 EmitUint8(0x0F);
195 EmitUint8(0xB7);
196 EmitRegisterOperand(dst, src);
197}
198
199
200void Assembler::movzxw(Register dst, const Address& src) {
201 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
202 EmitUint8(0x0F);
203 EmitUint8(0xB7);
204 EmitOperand(dst, src);
205}
206
207
208void Assembler::movsxw(Register dst, Register src) {
209 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
210 EmitUint8(0x0F);
211 EmitUint8(0xBF);
212 EmitRegisterOperand(dst, src);
213}
214
215
216void Assembler::movsxw(Register dst, const Address& src) {
217 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
218 EmitUint8(0x0F);
219 EmitUint8(0xBF);
220 EmitOperand(dst, src);
221}
222
223
224void Assembler::movw(Register dst, const Address& src) {
225 LOG(FATAL) << "Use movzxw or movsxw instead.";
226}
227
228
229void Assembler::movw(const Address& dst, Register src) {
230 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
231 EmitOperandSizeOverride();
232 EmitUint8(0x89);
233 EmitOperand(src, dst);
234}
235
236
237void Assembler::leal(Register dst, const Address& src) {
238 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
239 EmitUint8(0x8D);
240 EmitOperand(dst, src);
241}
242
243
Ian Rogersb033c752011-07-20 12:22:35 -0700244void Assembler::cmovl(Condition condition, Register dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700245 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
246 EmitUint8(0x0F);
Ian Rogersb033c752011-07-20 12:22:35 -0700247 EmitUint8(0x40 + condition);
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700248 EmitRegisterOperand(dst, src);
249}
250
251
Ian Rogersb033c752011-07-20 12:22:35 -0700252void Assembler::setb(Condition condition, Register dst) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700253 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
254 EmitUint8(0x0F);
Ian Rogersb033c752011-07-20 12:22:35 -0700255 EmitUint8(0x90 + condition);
256 EmitOperand(0, Operand(dst));
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700257}
258
259
260void Assembler::movss(XmmRegister dst, const Address& src) {
261 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
262 EmitUint8(0xF3);
263 EmitUint8(0x0F);
264 EmitUint8(0x10);
265 EmitOperand(dst, src);
266}
267
268
269void Assembler::movss(const Address& dst, XmmRegister src) {
270 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
271 EmitUint8(0xF3);
272 EmitUint8(0x0F);
273 EmitUint8(0x11);
274 EmitOperand(src, dst);
275}
276
277
278void Assembler::movss(XmmRegister dst, XmmRegister src) {
279 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
280 EmitUint8(0xF3);
281 EmitUint8(0x0F);
282 EmitUint8(0x11);
283 EmitXmmRegisterOperand(src, dst);
284}
285
286
287void Assembler::movd(XmmRegister dst, Register src) {
288 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
289 EmitUint8(0x66);
290 EmitUint8(0x0F);
291 EmitUint8(0x6E);
292 EmitOperand(dst, Operand(src));
293}
294
295
296void Assembler::movd(Register dst, XmmRegister src) {
297 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
298 EmitUint8(0x66);
299 EmitUint8(0x0F);
300 EmitUint8(0x7E);
301 EmitOperand(src, Operand(dst));
302}
303
304
305void Assembler::addss(XmmRegister dst, XmmRegister src) {
306 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
307 EmitUint8(0xF3);
308 EmitUint8(0x0F);
309 EmitUint8(0x58);
310 EmitXmmRegisterOperand(dst, src);
311}
312
313
314void Assembler::addss(XmmRegister dst, const Address& src) {
315 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
316 EmitUint8(0xF3);
317 EmitUint8(0x0F);
318 EmitUint8(0x58);
319 EmitOperand(dst, src);
320}
321
322
323void Assembler::subss(XmmRegister dst, XmmRegister src) {
324 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
325 EmitUint8(0xF3);
326 EmitUint8(0x0F);
327 EmitUint8(0x5C);
328 EmitXmmRegisterOperand(dst, src);
329}
330
331
332void Assembler::subss(XmmRegister dst, const Address& src) {
333 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
334 EmitUint8(0xF3);
335 EmitUint8(0x0F);
336 EmitUint8(0x5C);
337 EmitOperand(dst, src);
338}
339
340
341void Assembler::mulss(XmmRegister dst, XmmRegister src) {
342 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
343 EmitUint8(0xF3);
344 EmitUint8(0x0F);
345 EmitUint8(0x59);
346 EmitXmmRegisterOperand(dst, src);
347}
348
349
350void Assembler::mulss(XmmRegister dst, const Address& src) {
351 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
352 EmitUint8(0xF3);
353 EmitUint8(0x0F);
354 EmitUint8(0x59);
355 EmitOperand(dst, src);
356}
357
358
359void Assembler::divss(XmmRegister dst, XmmRegister src) {
360 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
361 EmitUint8(0xF3);
362 EmitUint8(0x0F);
363 EmitUint8(0x5E);
364 EmitXmmRegisterOperand(dst, src);
365}
366
367
368void Assembler::divss(XmmRegister dst, const Address& src) {
369 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
370 EmitUint8(0xF3);
371 EmitUint8(0x0F);
372 EmitUint8(0x5E);
373 EmitOperand(dst, src);
374}
375
376
377void Assembler::flds(const Address& src) {
378 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
379 EmitUint8(0xD9);
380 EmitOperand(0, src);
381}
382
383
384void Assembler::fstps(const Address& dst) {
385 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
386 EmitUint8(0xD9);
387 EmitOperand(3, dst);
388}
389
390
391void Assembler::movsd(XmmRegister dst, const Address& src) {
392 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
393 EmitUint8(0xF2);
394 EmitUint8(0x0F);
395 EmitUint8(0x10);
396 EmitOperand(dst, src);
397}
398
399
400void Assembler::movsd(const Address& dst, XmmRegister src) {
401 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
402 EmitUint8(0xF2);
403 EmitUint8(0x0F);
404 EmitUint8(0x11);
405 EmitOperand(src, dst);
406}
407
408
409void Assembler::movsd(XmmRegister dst, XmmRegister src) {
410 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
411 EmitUint8(0xF2);
412 EmitUint8(0x0F);
413 EmitUint8(0x11);
414 EmitXmmRegisterOperand(src, dst);
415}
416
417
418void Assembler::addsd(XmmRegister dst, XmmRegister src) {
419 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
420 EmitUint8(0xF2);
421 EmitUint8(0x0F);
422 EmitUint8(0x58);
423 EmitXmmRegisterOperand(dst, src);
424}
425
426
427void Assembler::addsd(XmmRegister dst, const Address& src) {
428 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
429 EmitUint8(0xF2);
430 EmitUint8(0x0F);
431 EmitUint8(0x58);
432 EmitOperand(dst, src);
433}
434
435
436void Assembler::subsd(XmmRegister dst, XmmRegister src) {
437 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
438 EmitUint8(0xF2);
439 EmitUint8(0x0F);
440 EmitUint8(0x5C);
441 EmitXmmRegisterOperand(dst, src);
442}
443
444
445void Assembler::subsd(XmmRegister dst, const Address& src) {
446 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
447 EmitUint8(0xF2);
448 EmitUint8(0x0F);
449 EmitUint8(0x5C);
450 EmitOperand(dst, src);
451}
452
453
454void Assembler::mulsd(XmmRegister dst, XmmRegister src) {
455 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
456 EmitUint8(0xF2);
457 EmitUint8(0x0F);
458 EmitUint8(0x59);
459 EmitXmmRegisterOperand(dst, src);
460}
461
462
463void Assembler::mulsd(XmmRegister dst, const Address& src) {
464 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
465 EmitUint8(0xF2);
466 EmitUint8(0x0F);
467 EmitUint8(0x59);
468 EmitOperand(dst, src);
469}
470
471
472void Assembler::divsd(XmmRegister dst, XmmRegister src) {
473 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
474 EmitUint8(0xF2);
475 EmitUint8(0x0F);
476 EmitUint8(0x5E);
477 EmitXmmRegisterOperand(dst, src);
478}
479
480
481void Assembler::divsd(XmmRegister dst, const Address& src) {
482 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
483 EmitUint8(0xF2);
484 EmitUint8(0x0F);
485 EmitUint8(0x5E);
486 EmitOperand(dst, src);
487}
488
489
490void Assembler::cvtsi2ss(XmmRegister dst, Register src) {
491 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
492 EmitUint8(0xF3);
493 EmitUint8(0x0F);
494 EmitUint8(0x2A);
495 EmitOperand(dst, Operand(src));
496}
497
498
499void Assembler::cvtsi2sd(XmmRegister dst, Register src) {
500 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
501 EmitUint8(0xF2);
502 EmitUint8(0x0F);
503 EmitUint8(0x2A);
504 EmitOperand(dst, Operand(src));
505}
506
507
508void Assembler::cvtss2si(Register dst, XmmRegister src) {
509 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
510 EmitUint8(0xF3);
511 EmitUint8(0x0F);
512 EmitUint8(0x2D);
513 EmitXmmRegisterOperand(dst, src);
514}
515
516
517void Assembler::cvtss2sd(XmmRegister dst, XmmRegister src) {
518 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
519 EmitUint8(0xF3);
520 EmitUint8(0x0F);
521 EmitUint8(0x5A);
522 EmitXmmRegisterOperand(dst, src);
523}
524
525
526void Assembler::cvtsd2si(Register dst, XmmRegister src) {
527 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
528 EmitUint8(0xF2);
529 EmitUint8(0x0F);
530 EmitUint8(0x2D);
531 EmitXmmRegisterOperand(dst, src);
532}
533
534
535void Assembler::cvttss2si(Register dst, XmmRegister src) {
536 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
537 EmitUint8(0xF3);
538 EmitUint8(0x0F);
539 EmitUint8(0x2C);
540 EmitXmmRegisterOperand(dst, src);
541}
542
543
544void Assembler::cvttsd2si(Register dst, XmmRegister src) {
545 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
546 EmitUint8(0xF2);
547 EmitUint8(0x0F);
548 EmitUint8(0x2C);
549 EmitXmmRegisterOperand(dst, src);
550}
551
552
553void Assembler::cvtsd2ss(XmmRegister dst, XmmRegister src) {
554 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
555 EmitUint8(0xF2);
556 EmitUint8(0x0F);
557 EmitUint8(0x5A);
558 EmitXmmRegisterOperand(dst, src);
559}
560
561
562void Assembler::cvtdq2pd(XmmRegister dst, XmmRegister src) {
563 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
564 EmitUint8(0xF3);
565 EmitUint8(0x0F);
566 EmitUint8(0xE6);
567 EmitXmmRegisterOperand(dst, src);
568}
569
570
571void Assembler::comiss(XmmRegister a, XmmRegister b) {
572 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
573 EmitUint8(0x0F);
574 EmitUint8(0x2F);
575 EmitXmmRegisterOperand(a, b);
576}
577
578
579void Assembler::comisd(XmmRegister a, XmmRegister b) {
580 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
581 EmitUint8(0x66);
582 EmitUint8(0x0F);
583 EmitUint8(0x2F);
584 EmitXmmRegisterOperand(a, b);
585}
586
587
588void Assembler::sqrtsd(XmmRegister dst, XmmRegister src) {
589 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
590 EmitUint8(0xF2);
591 EmitUint8(0x0F);
592 EmitUint8(0x51);
593 EmitXmmRegisterOperand(dst, src);
594}
595
596
597void Assembler::sqrtss(XmmRegister dst, XmmRegister src) {
598 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
599 EmitUint8(0xF3);
600 EmitUint8(0x0F);
601 EmitUint8(0x51);
602 EmitXmmRegisterOperand(dst, src);
603}
604
605
606void Assembler::xorpd(XmmRegister dst, const Address& src) {
607 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
608 EmitUint8(0x66);
609 EmitUint8(0x0F);
610 EmitUint8(0x57);
611 EmitOperand(dst, src);
612}
613
614
615void Assembler::xorpd(XmmRegister dst, XmmRegister src) {
616 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
617 EmitUint8(0x66);
618 EmitUint8(0x0F);
619 EmitUint8(0x57);
620 EmitXmmRegisterOperand(dst, src);
621}
622
623
624void Assembler::xorps(XmmRegister dst, const Address& src) {
625 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
626 EmitUint8(0x0F);
627 EmitUint8(0x57);
628 EmitOperand(dst, src);
629}
630
631
632void Assembler::xorps(XmmRegister dst, XmmRegister src) {
633 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
634 EmitUint8(0x0F);
635 EmitUint8(0x57);
636 EmitXmmRegisterOperand(dst, src);
637}
638
639
640void Assembler::andpd(XmmRegister dst, const Address& src) {
641 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
642 EmitUint8(0x66);
643 EmitUint8(0x0F);
644 EmitUint8(0x54);
645 EmitOperand(dst, src);
646}
647
648
649void Assembler::fldl(const Address& src) {
650 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
651 EmitUint8(0xDD);
652 EmitOperand(0, src);
653}
654
655
656void Assembler::fstpl(const Address& dst) {
657 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
658 EmitUint8(0xDD);
659 EmitOperand(3, dst);
660}
661
662
663void Assembler::fnstcw(const Address& dst) {
664 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
665 EmitUint8(0xD9);
666 EmitOperand(7, dst);
667}
668
669
670void Assembler::fldcw(const Address& src) {
671 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
672 EmitUint8(0xD9);
673 EmitOperand(5, src);
674}
675
676
677void Assembler::fistpl(const Address& dst) {
678 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
679 EmitUint8(0xDF);
680 EmitOperand(7, dst);
681}
682
683
684void Assembler::fistps(const Address& dst) {
685 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
686 EmitUint8(0xDB);
687 EmitOperand(3, dst);
688}
689
690
691void Assembler::fildl(const Address& src) {
692 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
693 EmitUint8(0xDF);
694 EmitOperand(5, src);
695}
696
697
698void Assembler::fincstp() {
699 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
700 EmitUint8(0xD9);
701 EmitUint8(0xF7);
702}
703
704
705void Assembler::ffree(const Immediate& index) {
706 CHECK_LT(index.value(), 7);
707 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
708 EmitUint8(0xDD);
709 EmitUint8(0xC0 + index.value());
710}
711
712
713void Assembler::fsin() {
714 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
715 EmitUint8(0xD9);
716 EmitUint8(0xFE);
717}
718
719
720void Assembler::fcos() {
721 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
722 EmitUint8(0xD9);
723 EmitUint8(0xFF);
724}
725
726
727void Assembler::fptan() {
728 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
729 EmitUint8(0xD9);
730 EmitUint8(0xF2);
731}
732
733
734void Assembler::xchgl(Register dst, Register src) {
735 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
736 EmitUint8(0x87);
737 EmitRegisterOperand(dst, src);
738}
739
740
741void Assembler::cmpl(Register reg, const Immediate& imm) {
742 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
743 EmitComplex(7, Operand(reg), imm);
744}
745
746
747void Assembler::cmpl(Register reg0, Register reg1) {
748 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
749 EmitUint8(0x3B);
750 EmitOperand(reg0, Operand(reg1));
751}
752
753
754void Assembler::cmpl(Register reg, const Address& address) {
755 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
756 EmitUint8(0x3B);
757 EmitOperand(reg, address);
758}
759
760
761void Assembler::addl(Register dst, Register src) {
762 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
763 EmitUint8(0x03);
764 EmitRegisterOperand(dst, src);
765}
766
767
768void Assembler::addl(Register reg, const Address& address) {
769 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
770 EmitUint8(0x03);
771 EmitOperand(reg, address);
772}
773
774
775void Assembler::cmpl(const Address& address, Register reg) {
776 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
777 EmitUint8(0x39);
778 EmitOperand(reg, address);
779}
780
781
782void Assembler::cmpl(const Address& address, const Immediate& imm) {
783 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
784 EmitComplex(7, address, imm);
785}
786
787
788void Assembler::testl(Register reg1, Register reg2) {
789 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
790 EmitUint8(0x85);
791 EmitRegisterOperand(reg1, reg2);
792}
793
794
795void Assembler::testl(Register reg, const Immediate& immediate) {
796 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
797 // For registers that have a byte variant (EAX, EBX, ECX, and EDX)
798 // we only test the byte register to keep the encoding short.
799 if (immediate.is_uint8() && reg < 4) {
800 // Use zero-extended 8-bit immediate.
801 if (reg == EAX) {
802 EmitUint8(0xA8);
803 } else {
804 EmitUint8(0xF6);
805 EmitUint8(0xC0 + reg);
806 }
807 EmitUint8(immediate.value() & 0xFF);
808 } else if (reg == EAX) {
809 // Use short form if the destination is EAX.
810 EmitUint8(0xA9);
811 EmitImmediate(immediate);
812 } else {
813 EmitUint8(0xF7);
814 EmitOperand(0, Operand(reg));
815 EmitImmediate(immediate);
816 }
817}
818
819
820void Assembler::andl(Register dst, Register src) {
821 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
822 EmitUint8(0x23);
823 EmitOperand(dst, Operand(src));
824}
825
826
827void Assembler::andl(Register dst, const Immediate& imm) {
828 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
829 EmitComplex(4, Operand(dst), imm);
830}
831
832
833void Assembler::orl(Register dst, Register src) {
834 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
835 EmitUint8(0x0B);
836 EmitOperand(dst, Operand(src));
837}
838
839
840void Assembler::orl(Register dst, const Immediate& imm) {
841 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
842 EmitComplex(1, Operand(dst), imm);
843}
844
845
846void Assembler::xorl(Register dst, Register src) {
847 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
848 EmitUint8(0x33);
849 EmitOperand(dst, Operand(src));
850}
851
852
853void Assembler::addl(Register reg, const Immediate& imm) {
854 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
855 EmitComplex(0, Operand(reg), imm);
856}
857
858
859void Assembler::addl(const Address& address, Register reg) {
860 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
861 EmitUint8(0x01);
862 EmitOperand(reg, address);
863}
864
865
866void Assembler::addl(const Address& address, const Immediate& imm) {
867 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
868 EmitComplex(0, address, imm);
869}
870
871
872void Assembler::adcl(Register reg, const Immediate& imm) {
873 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
874 EmitComplex(2, Operand(reg), imm);
875}
876
877
878void Assembler::adcl(Register dst, Register src) {
879 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
880 EmitUint8(0x13);
881 EmitOperand(dst, Operand(src));
882}
883
884
885void Assembler::adcl(Register dst, const Address& address) {
886 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
887 EmitUint8(0x13);
888 EmitOperand(dst, address);
889}
890
891
892void Assembler::subl(Register dst, Register src) {
893 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
894 EmitUint8(0x2B);
895 EmitOperand(dst, Operand(src));
896}
897
898
899void Assembler::subl(Register reg, const Immediate& imm) {
900 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
901 EmitComplex(5, Operand(reg), imm);
902}
903
904
905void Assembler::subl(Register reg, const Address& address) {
906 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
907 EmitUint8(0x2B);
908 EmitOperand(reg, address);
909}
910
911
912void Assembler::cdq() {
913 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
914 EmitUint8(0x99);
915}
916
917
918void Assembler::idivl(Register reg) {
919 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
920 EmitUint8(0xF7);
921 EmitUint8(0xF8 | reg);
922}
923
924
925void Assembler::imull(Register dst, Register src) {
926 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
927 EmitUint8(0x0F);
928 EmitUint8(0xAF);
929 EmitOperand(dst, Operand(src));
930}
931
932
933void Assembler::imull(Register reg, const Immediate& imm) {
934 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
935 EmitUint8(0x69);
936 EmitOperand(reg, Operand(reg));
937 EmitImmediate(imm);
938}
939
940
941void Assembler::imull(Register reg, const Address& address) {
942 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
943 EmitUint8(0x0F);
944 EmitUint8(0xAF);
945 EmitOperand(reg, address);
946}
947
948
949void Assembler::imull(Register reg) {
950 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
951 EmitUint8(0xF7);
952 EmitOperand(5, Operand(reg));
953}
954
955
956void Assembler::imull(const Address& address) {
957 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
958 EmitUint8(0xF7);
959 EmitOperand(5, address);
960}
961
962
963void Assembler::mull(Register reg) {
964 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
965 EmitUint8(0xF7);
966 EmitOperand(4, Operand(reg));
967}
968
969
970void Assembler::mull(const Address& address) {
971 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
972 EmitUint8(0xF7);
973 EmitOperand(4, address);
974}
975
976
977void Assembler::sbbl(Register dst, Register src) {
978 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
979 EmitUint8(0x1B);
980 EmitOperand(dst, Operand(src));
981}
982
983
984void Assembler::sbbl(Register reg, const Immediate& imm) {
985 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
986 EmitComplex(3, Operand(reg), imm);
987}
988
989
990void Assembler::sbbl(Register dst, const Address& address) {
991 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
992 EmitUint8(0x1B);
993 EmitOperand(dst, address);
994}
995
996
997void Assembler::incl(Register reg) {
998 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
999 EmitUint8(0x40 + reg);
1000}
1001
1002
1003void Assembler::incl(const Address& address) {
1004 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1005 EmitUint8(0xFF);
1006 EmitOperand(0, address);
1007}
1008
1009
1010void Assembler::decl(Register reg) {
1011 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1012 EmitUint8(0x48 + reg);
1013}
1014
1015
1016void Assembler::decl(const Address& address) {
1017 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1018 EmitUint8(0xFF);
1019 EmitOperand(1, address);
1020}
1021
1022
1023void Assembler::shll(Register reg, const Immediate& imm) {
1024 EmitGenericShift(4, reg, imm);
1025}
1026
1027
1028void Assembler::shll(Register operand, Register shifter) {
1029 EmitGenericShift(4, operand, shifter);
1030}
1031
1032
1033void Assembler::shrl(Register reg, const Immediate& imm) {
1034 EmitGenericShift(5, reg, imm);
1035}
1036
1037
1038void Assembler::shrl(Register operand, Register shifter) {
1039 EmitGenericShift(5, operand, shifter);
1040}
1041
1042
1043void Assembler::sarl(Register reg, const Immediate& imm) {
1044 EmitGenericShift(7, reg, imm);
1045}
1046
1047
1048void Assembler::sarl(Register operand, Register shifter) {
1049 EmitGenericShift(7, operand, shifter);
1050}
1051
1052
1053void Assembler::shld(Register dst, Register src) {
1054 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1055 EmitUint8(0x0F);
1056 EmitUint8(0xA5);
1057 EmitRegisterOperand(src, dst);
1058}
1059
1060
1061void Assembler::negl(Register reg) {
1062 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1063 EmitUint8(0xF7);
1064 EmitOperand(3, Operand(reg));
1065}
1066
1067
1068void Assembler::notl(Register reg) {
1069 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1070 EmitUint8(0xF7);
1071 EmitUint8(0xD0 | reg);
1072}
1073
1074
1075void Assembler::enter(const Immediate& imm) {
1076 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1077 EmitUint8(0xC8);
1078 CHECK(imm.is_uint16());
1079 EmitUint8(imm.value() & 0xFF);
1080 EmitUint8((imm.value() >> 8) & 0xFF);
1081 EmitUint8(0x00);
1082}
1083
1084
1085void Assembler::leave() {
1086 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1087 EmitUint8(0xC9);
1088}
1089
1090
1091void Assembler::ret() {
1092 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1093 EmitUint8(0xC3);
1094}
1095
1096
1097void Assembler::ret(const Immediate& imm) {
1098 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1099 EmitUint8(0xC2);
1100 CHECK(imm.is_uint16());
1101 EmitUint8(imm.value() & 0xFF);
1102 EmitUint8((imm.value() >> 8) & 0xFF);
1103}
1104
1105
1106
1107void Assembler::nop() {
1108 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1109 EmitUint8(0x90);
1110}
1111
1112
1113void Assembler::int3() {
1114 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1115 EmitUint8(0xCC);
1116}
1117
1118
1119void Assembler::hlt() {
1120 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1121 EmitUint8(0xF4);
1122}
1123
1124
1125void Assembler::j(Condition condition, Label* label) {
1126 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1127 if (label->IsBound()) {
1128 static const int kShortSize = 2;
1129 static const int kLongSize = 6;
1130 int offset = label->Position() - buffer_.Size();
1131 CHECK_LE(offset, 0);
1132 if (IsInt(8, offset - kShortSize)) {
1133 EmitUint8(0x70 + condition);
1134 EmitUint8((offset - kShortSize) & 0xFF);
1135 } else {
1136 EmitUint8(0x0F);
1137 EmitUint8(0x80 + condition);
1138 EmitInt32(offset - kLongSize);
1139 }
1140 } else {
1141 EmitUint8(0x0F);
1142 EmitUint8(0x80 + condition);
1143 EmitLabelLink(label);
1144 }
1145}
1146
1147
1148void Assembler::jmp(Register reg) {
1149 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1150 EmitUint8(0xFF);
1151 EmitRegisterOperand(4, reg);
1152}
1153
1154
1155void Assembler::jmp(Label* label) {
1156 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1157 if (label->IsBound()) {
1158 static const int kShortSize = 2;
1159 static const int kLongSize = 5;
1160 int offset = label->Position() - buffer_.Size();
1161 CHECK_LE(offset, 0);
1162 if (IsInt(8, offset - kShortSize)) {
1163 EmitUint8(0xEB);
1164 EmitUint8((offset - kShortSize) & 0xFF);
1165 } else {
1166 EmitUint8(0xE9);
1167 EmitInt32(offset - kLongSize);
1168 }
1169 } else {
1170 EmitUint8(0xE9);
1171 EmitLabelLink(label);
1172 }
1173}
1174
1175
1176void Assembler::lock() {
1177 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1178 EmitUint8(0xF0);
1179}
1180
1181
1182void Assembler::cmpxchgl(const Address& address, Register reg) {
1183 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1184 EmitUint8(0x0F);
1185 EmitUint8(0xB1);
1186 EmitOperand(reg, address);
1187}
1188
Ian Rogersb033c752011-07-20 12:22:35 -07001189void Assembler::fs() {
1190 // TODO: fs is a prefix and not an instruction
1191 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1192 EmitUint8(0x64);
1193}
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001194
1195void Assembler::AddImmediate(Register reg, const Immediate& imm) {
1196 int value = imm.value();
1197 if (value > 0) {
1198 if (value == 1) {
1199 incl(reg);
1200 } else if (value != 0) {
1201 addl(reg, imm);
1202 }
1203 } else if (value < 0) {
1204 value = -value;
1205 if (value == 1) {
1206 decl(reg);
1207 } else if (value != 0) {
1208 subl(reg, Immediate(value));
1209 }
1210 }
1211}
1212
1213
1214void Assembler::LoadDoubleConstant(XmmRegister dst, double value) {
1215 // TODO: Need to have a code constants table.
1216 int64_t constant = bit_cast<int64_t, double>(value);
1217 pushl(Immediate(High32Bits(constant)));
1218 pushl(Immediate(Low32Bits(constant)));
1219 movsd(dst, Address(ESP, 0));
1220 addl(ESP, Immediate(2 * kWordSize));
1221}
1222
1223
1224void Assembler::FloatNegate(XmmRegister f) {
1225 static const struct {
1226 uint32_t a;
1227 uint32_t b;
1228 uint32_t c;
1229 uint32_t d;
1230 } float_negate_constant __attribute__((aligned(16))) =
1231 { 0x80000000, 0x00000000, 0x80000000, 0x00000000 };
1232 xorps(f, Address::Absolute(reinterpret_cast<uword>(&float_negate_constant)));
1233}
1234
1235
1236void Assembler::DoubleNegate(XmmRegister d) {
1237 static const struct {
1238 uint64_t a;
1239 uint64_t b;
1240 } double_negate_constant __attribute__((aligned(16))) =
1241 {0x8000000000000000LL, 0x8000000000000000LL};
1242 xorpd(d, Address::Absolute(reinterpret_cast<uword>(&double_negate_constant)));
1243}
1244
1245
1246void Assembler::DoubleAbs(XmmRegister reg) {
1247 static const struct {
1248 uint64_t a;
1249 uint64_t b;
1250 } double_abs_constant __attribute__((aligned(16))) =
1251 {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL};
1252 andpd(reg, Address::Absolute(reinterpret_cast<uword>(&double_abs_constant)));
1253}
1254
1255
1256void Assembler::Align(int alignment, int offset) {
1257 CHECK(IsPowerOfTwo(alignment));
1258 // Emit nop instruction until the real position is aligned.
1259 while (((offset + buffer_.GetPosition()) & (alignment-1)) != 0) {
1260 nop();
1261 }
1262}
1263
1264
1265void Assembler::Bind(Label* label) {
1266 int bound = buffer_.Size();
1267 CHECK(!label->IsBound()); // Labels can only be bound once.
1268 while (label->IsLinked()) {
1269 int position = label->LinkPosition();
1270 int next = buffer_.Load<int32_t>(position);
1271 buffer_.Store<int32_t>(position, bound - (position + 4));
1272 label->position_ = next;
1273 }
1274 label->BindTo(bound);
1275}
1276
1277
1278void Assembler::Stop(const char* message) {
1279 // Emit the message address as immediate operand in the test rax instruction,
1280 // followed by the int3 instruction.
1281 // Execution can be resumed with the 'cont' command in gdb.
1282 testl(EAX, Immediate(reinterpret_cast<int32_t>(message)));
1283 int3();
1284}
1285
1286
1287void Assembler::EmitOperand(int rm, const Operand& operand) {
1288 CHECK_GE(rm, 0);
1289 CHECK_LT(rm, 8);
1290 const int length = operand.length_;
1291 CHECK_GT(length, 0);
1292 // Emit the ModRM byte updated with the given RM value.
1293 CHECK_EQ(operand.encoding_[0] & 0x38, 0);
1294 EmitUint8(operand.encoding_[0] + (rm << 3));
1295 // Emit the rest of the encoded operand.
1296 for (int i = 1; i < length; i++) {
1297 EmitUint8(operand.encoding_[i]);
1298 }
1299}
1300
1301
1302void Assembler::EmitImmediate(const Immediate& imm) {
1303 EmitInt32(imm.value());
1304}
1305
1306
1307void Assembler::EmitComplex(int rm,
1308 const Operand& operand,
1309 const Immediate& immediate) {
1310 CHECK_GE(rm, 0);
1311 CHECK_LT(rm, 8);
1312 if (immediate.is_int8()) {
1313 // Use sign-extended 8-bit immediate.
1314 EmitUint8(0x83);
1315 EmitOperand(rm, operand);
1316 EmitUint8(immediate.value() & 0xFF);
1317 } else if (operand.IsRegister(EAX)) {
1318 // Use short form if the destination is eax.
1319 EmitUint8(0x05 + (rm << 3));
1320 EmitImmediate(immediate);
1321 } else {
1322 EmitUint8(0x81);
1323 EmitOperand(rm, operand);
1324 EmitImmediate(immediate);
1325 }
1326}
1327
1328
1329void Assembler::EmitLabel(Label* label, int instruction_size) {
1330 if (label->IsBound()) {
1331 int offset = label->Position() - buffer_.Size();
1332 CHECK_LE(offset, 0);
1333 EmitInt32(offset - instruction_size);
1334 } else {
1335 EmitLabelLink(label);
1336 }
1337}
1338
1339
1340void Assembler::EmitLabelLink(Label* label) {
1341 CHECK(!label->IsBound());
1342 int position = buffer_.Size();
1343 EmitInt32(label->position_);
1344 label->LinkTo(position);
1345}
1346
1347
1348void Assembler::EmitGenericShift(int rm,
1349 Register reg,
1350 const Immediate& imm) {
1351 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1352 CHECK(imm.is_int8());
1353 if (imm.value() == 1) {
1354 EmitUint8(0xD1);
1355 EmitOperand(rm, Operand(reg));
1356 } else {
1357 EmitUint8(0xC1);
1358 EmitOperand(rm, Operand(reg));
1359 EmitUint8(imm.value() & 0xFF);
1360 }
1361}
1362
1363
1364void Assembler::EmitGenericShift(int rm,
1365 Register operand,
1366 Register shifter) {
1367 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1368 CHECK_EQ(shifter, ECX);
1369 EmitUint8(0xD3);
1370 EmitOperand(rm, Operand(operand));
1371}
1372
Ian Rogersb033c752011-07-20 12:22:35 -07001373// Emit code that will create an activation on the stack
1374void Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg) {
1375 CHECK(IsAligned(frame_size, 16));
1376 // return address then method on stack
1377 addl(ESP, Immediate(-frame_size + 4 /*method*/ + 4 /*return address*/));
1378 pushl(method_reg.AsCpuRegister());
1379}
1380
1381// Emit code that will remove an activation from the stack
1382void Assembler::RemoveFrame(size_t frame_size) {
1383 CHECK(IsAligned(frame_size, 16));
1384 addl(ESP, Immediate(frame_size - 4));
1385 ret();
1386}
1387
1388void Assembler::IncreaseFrameSize(size_t adjust) {
1389 CHECK(IsAligned(adjust, 16));
1390 addl(ESP, Immediate(-adjust));
1391}
1392
1393void Assembler::DecreaseFrameSize(size_t adjust) {
1394 CHECK(IsAligned(adjust, 16));
1395 addl(ESP, Immediate(adjust));
1396}
1397
1398// Store bytes from the given register onto the stack
1399void Assembler::Store(FrameOffset offs, ManagedRegister src, size_t size) {
Ian Rogers45a76cb2011-07-21 22:00:15 -07001400 if (src.IsNoRegister()) {
1401 CHECK_EQ(0u, size);
1402 } else if (src.IsCpuRegister()) {
Ian Rogersb033c752011-07-20 12:22:35 -07001403 CHECK_EQ(4u, size);
1404 movl(Address(ESP, offs), src.AsCpuRegister());
Ian Rogers45a76cb2011-07-21 22:00:15 -07001405 } else if (src.IsX87Register()) {
1406 if (size == 4) {
1407 fstps(Address(ESP, offs));
1408 } else {
1409 fstpl(Address(ESP, offs));
1410 }
1411 } else {
1412 CHECK(src.IsXmmRegister());
Ian Rogersb033c752011-07-20 12:22:35 -07001413 if (size == 4) {
1414 movss(Address(ESP, offs), src.AsXmmRegister());
1415 } else {
1416 movsd(Address(ESP, offs), src.AsXmmRegister());
1417 }
1418 }
1419}
1420
1421void Assembler::StoreRef(FrameOffset dest, ManagedRegister src) {
1422 CHECK(src.IsCpuRegister());
1423 movl(Address(ESP, dest), src.AsCpuRegister());
1424}
1425
Ian Rogersdf20fe02011-07-20 20:34:16 -07001426void Assembler::StoreRawPtr(FrameOffset dest, ManagedRegister src) {
1427 CHECK(src.IsCpuRegister());
1428 movl(Address(ESP, dest), src.AsCpuRegister());
1429}
1430
Ian Rogersb033c752011-07-20 12:22:35 -07001431void Assembler::CopyRef(FrameOffset dest, FrameOffset src,
1432 ManagedRegister scratch) {
1433 CHECK(scratch.IsCpuRegister());
1434 movl(scratch.AsCpuRegister(), Address(ESP, src));
1435 movl(Address(ESP, dest), scratch.AsCpuRegister());
1436}
1437
1438void Assembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
1439 ManagedRegister) {
1440 movl(Address(ESP, dest), Immediate(imm));
1441}
1442
1443void Assembler::StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
1444 ManagedRegister) {
1445 fs();
1446 movl(Address::Absolute(dest), Immediate(imm));
1447}
1448
1449void Assembler::Load(ManagedRegister dest, FrameOffset src, size_t size) {
Ian Rogers45a76cb2011-07-21 22:00:15 -07001450 if (dest.IsNoRegister()) {
1451 CHECK_EQ(0u, size);
1452 } else if (dest.IsCpuRegister()) {
Ian Rogersb033c752011-07-20 12:22:35 -07001453 CHECK_EQ(4u, size);
1454 movl(dest.AsCpuRegister(), Address(ESP, src));
Ian Rogers45a76cb2011-07-21 22:00:15 -07001455 } else if (dest.IsX87Register()) {
1456 if (size == 4) {
1457 flds(Address(ESP, src));
1458 } else {
1459 fldl(Address(ESP, src));
1460 }
Ian Rogersb033c752011-07-20 12:22:35 -07001461 } else {
Ian Rogers45a76cb2011-07-21 22:00:15 -07001462 CHECK(dest.IsXmmRegister());
1463 if (size == 4) {
1464 movss(dest.AsXmmRegister(), Address(ESP, src));
1465 } else {
1466 movsd(dest.AsXmmRegister(), Address(ESP, src));
1467 }
Ian Rogersb033c752011-07-20 12:22:35 -07001468 }
1469}
1470
1471void Assembler::LoadRef(ManagedRegister dest, FrameOffset src) {
1472 CHECK(dest.IsCpuRegister());
1473 movl(dest.AsCpuRegister(), Address(ESP, src));
1474}
1475
1476void Assembler::LoadRef(ManagedRegister dest, ManagedRegister base,
1477 MemberOffset offs) {
1478 CHECK(dest.IsCpuRegister() && dest.IsCpuRegister());
1479 movl(dest.AsCpuRegister(), Address(base.AsCpuRegister(), offs));
1480}
1481
1482void Assembler::LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset offs) {
1483 CHECK(dest.IsCpuRegister());
1484 fs();
1485 movl(dest.AsCpuRegister(), Address::Absolute(offs));
1486}
1487
1488void Assembler::CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset thr_offs,
1489 ManagedRegister scratch) {
1490 CHECK(scratch.IsCpuRegister());
1491 fs();
1492 movl(scratch.AsCpuRegister(), Address::Absolute(thr_offs));
1493 Store(fr_offs, scratch, 4);
1494}
1495
1496void Assembler::CopyRawPtrToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
1497 ManagedRegister scratch) {
1498 CHECK(scratch.IsCpuRegister());
1499 Load(scratch, fr_offs, 4);
1500 fs();
1501 movl(Address::Absolute(thr_offs), scratch.AsCpuRegister());
1502}
1503
1504void Assembler::StoreStackOffsetToThread(ThreadOffset thr_offs,
1505 FrameOffset fr_offs,
1506 ManagedRegister scratch) {
1507 CHECK(scratch.IsCpuRegister());
1508 leal(scratch.AsCpuRegister(), Address(ESP, fr_offs));
1509 fs();
1510 movl(Address::Absolute(thr_offs), scratch.AsCpuRegister());
1511}
1512
Ian Rogers45a76cb2011-07-21 22:00:15 -07001513void Assembler::StoreStackPointerToThread(ThreadOffset thr_offs) {
1514 fs();
1515 movl(Address::Absolute(thr_offs), ESP);
1516}
1517
Ian Rogersb033c752011-07-20 12:22:35 -07001518void Assembler::Move(ManagedRegister dest, ManagedRegister src) {
1519 if (!dest.Equals(src)) {
1520 if (dest.IsCpuRegister() && src.IsCpuRegister()) {
1521 movl(dest.AsCpuRegister(), src.AsCpuRegister());
1522 } else {
1523 // TODO: x87, SSE
1524 LOG(FATAL) << "Unimplemented";
1525 }
1526 }
1527}
1528
1529void Assembler::Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch,
1530 size_t size) {
1531 if (scratch.IsCpuRegister() && size == 8) {
1532 Load(scratch, src, 4);
1533 Store(dest, scratch, 4);
1534 Load(scratch, FrameOffset(src.Int32Value() + 4), 4);
1535 Store(FrameOffset(dest.Int32Value() + 4), scratch, 4);
1536 } else {
1537 Load(scratch, src, size);
1538 Store(dest, scratch, size);
1539 }
1540}
1541
1542void Assembler::CreateStackHandle(ManagedRegister out_reg,
1543 FrameOffset handle_offset,
1544 ManagedRegister in_reg, bool null_allowed) {
1545 CHECK(in_reg.IsCpuRegister());
1546 CHECK(out_reg.IsCpuRegister());
1547 ValidateRef(in_reg, null_allowed);
1548 if (null_allowed) {
1549 Label null_arg;
1550 if (!out_reg.Equals(in_reg)) {
1551 xorl(out_reg.AsCpuRegister(), out_reg.AsCpuRegister());
1552 }
1553 testl(in_reg.AsCpuRegister(), in_reg.AsCpuRegister());
1554 j(ZERO, &null_arg);
1555 leal(out_reg.AsCpuRegister(), Address(ESP, handle_offset));
1556 Bind(&null_arg);
1557 } else {
1558 leal(out_reg.AsCpuRegister(), Address(ESP, handle_offset));
1559 }
1560}
1561
1562void Assembler::CreateStackHandle(FrameOffset out_off,
1563 FrameOffset handle_offset,
1564 ManagedRegister scratch, bool null_allowed) {
1565 CHECK(scratch.IsCpuRegister());
1566 if (null_allowed) {
1567 Label null_arg;
1568 movl(scratch.AsCpuRegister(), Address(ESP, handle_offset));
1569 testl(scratch.AsCpuRegister(), scratch.AsCpuRegister());
1570 j(ZERO, &null_arg);
1571 leal(scratch.AsCpuRegister(), Address(ESP, handle_offset));
1572 Bind(&null_arg);
1573 } else {
1574 leal(scratch.AsCpuRegister(), Address(ESP, handle_offset));
1575 }
1576 Store(out_off, scratch, 4);
1577}
1578
1579// Given a stack handle, load the associated reference.
1580void Assembler::LoadReferenceFromStackHandle(ManagedRegister out_reg,
Ian Rogersdf20fe02011-07-20 20:34:16 -07001581 ManagedRegister in_reg) {
Ian Rogersb033c752011-07-20 12:22:35 -07001582 CHECK(out_reg.IsCpuRegister());
1583 CHECK(in_reg.IsCpuRegister());
1584 Label null_arg;
1585 if (!out_reg.Equals(in_reg)) {
1586 xorl(out_reg.AsCpuRegister(), out_reg.AsCpuRegister());
1587 }
1588 testl(in_reg.AsCpuRegister(), in_reg.AsCpuRegister());
1589 j(ZERO, &null_arg);
1590 movl(out_reg.AsCpuRegister(), Address(in_reg.AsCpuRegister(), 0));
1591 Bind(&null_arg);
1592}
1593
1594void Assembler::ValidateRef(ManagedRegister src, bool could_be_null) {
1595 // TODO: not validating references
1596}
1597
1598void Assembler::ValidateRef(FrameOffset src, bool could_be_null) {
1599 // TODO: not validating references
1600}
1601
Ian Rogersdf20fe02011-07-20 20:34:16 -07001602void Assembler::Call(ManagedRegister base, Offset offset,
Ian Rogersb033c752011-07-20 12:22:35 -07001603 ManagedRegister) {
1604 CHECK(base.IsCpuRegister());
Ian Rogersdf20fe02011-07-20 20:34:16 -07001605 call(Address(base.AsCpuRegister(), offset.Int32Value()));
Ian Rogersb033c752011-07-20 12:22:35 -07001606 // TODO: place reference map on call
1607}
1608
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001609void Assembler::Call(FrameOffset base, Offset offset,
1610 ManagedRegister) {
1611 LOG(FATAL) << "Unimplemented";
1612}
1613
Ian Rogers45a76cb2011-07-21 22:00:15 -07001614// Generate code to check if Thread::Current()->suspend_count_ is non-zero
1615// and branch to a SuspendSlowPath if it is. The SuspendSlowPath will continue
1616// at the next instruction.
1617void Assembler::SuspendPoll(ManagedRegister scratch, ManagedRegister return_reg,
1618 FrameOffset return_save_location,
1619 size_t return_size) {
1620 SuspendCountSlowPath* slow =
1621 new SuspendCountSlowPath(return_reg, return_save_location, return_size);
1622 buffer_.EnqueueSlowPath(slow);
1623 fs();
1624 cmpl(Address::Absolute(Thread::SuspendCountOffset()), Immediate(0));
1625 j(NOT_EQUAL, slow->Entry());
1626 Bind(slow->Continuation());
1627}
1628void SuspendCountSlowPath::Emit(Assembler *sp_asm) {
1629 sp_asm->Bind(&entry_);
1630 // Save return value
1631 sp_asm->Store(return_save_location_, return_register_, return_size_);
1632 // Pass top of stack as argument
1633 sp_asm->pushl(ESP);
1634 sp_asm->fs();
1635 sp_asm->call(Address::Absolute(Thread::SuspendCountEntryPointOffset()));
1636 // Release argument
1637 sp_asm->addl(ESP, Immediate(kPointerSize));
1638 // Reload return value
1639 sp_asm->Load(return_register_, return_save_location_, return_size_);
1640 sp_asm->jmp(&continuation_);
1641}
1642
1643// Generate code to check if Thread::Current()->exception_ is non-null
1644// and branch to a ExceptionSlowPath if it is.
1645void Assembler::ExceptionPoll(ManagedRegister scratch) {
1646 ExceptionSlowPath* slow = new ExceptionSlowPath();
1647 buffer_.EnqueueSlowPath(slow);
1648 fs();
1649 cmpl(Address::Absolute(Thread::ExceptionOffset()), Immediate(0));
1650 j(NOT_EQUAL, slow->Entry());
1651 Bind(slow->Continuation());
1652}
1653void ExceptionSlowPath::Emit(Assembler *sp_asm) {
1654 sp_asm->Bind(&entry_);
1655 // NB the return value is dead
1656 // Pass top of stack as argument
1657 sp_asm->pushl(ESP);
1658 sp_asm->fs();
1659 sp_asm->call(Address::Absolute(Thread::ExceptionEntryPointOffset()));
1660 // TODO: this call should never return as it should make a long jump to
1661 // the appropriate catch block
1662 // Release argument
1663 sp_asm->addl(ESP, Immediate(kPointerSize));
1664 sp_asm->jmp(&continuation_);
1665}
1666
Ian Rogersb033c752011-07-20 12:22:35 -07001667} // namespace art