blob: 389fc2c65acf24cb0ece4b59dd323966270a900d [file] [log] [blame]
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Ian Rogers2c8f6532011-09-02 17:16:34 -07003#include "assembler_x86.h"
4
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07005#include "casts.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07006#include "memory_region.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07007#include "thread.h"
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07008
Carl Shapiro6b6b5f02011-06-21 15:05:09 -07009namespace art {
Ian Rogers2c8f6532011-09-02 17:16:34 -070010namespace x86 {
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
Ian Rogers2c8f6532011-09-02 17:16:34 -070043void X86Assembler::InitializeMemoryWithBreakpoints(byte* data, size_t length) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070044 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length);
45}
46
Ian Rogers2c8f6532011-09-02 17:16:34 -070047void X86Assembler::call(Register reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070048 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
49 EmitUint8(0xFF);
50 EmitRegisterOperand(2, reg);
51}
52
53
Ian Rogers2c8f6532011-09-02 17:16:34 -070054void X86Assembler::call(const Address& address) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070055 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
56 EmitUint8(0xFF);
57 EmitOperand(2, address);
58}
59
60
Ian Rogers2c8f6532011-09-02 17:16:34 -070061void X86Assembler::call(Label* label) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070062 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
63 EmitUint8(0xE8);
64 static const int kSize = 5;
65 EmitLabel(label, kSize);
66}
67
68
Ian Rogers2c8f6532011-09-02 17:16:34 -070069void X86Assembler::pushl(Register reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070070 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
71 EmitUint8(0x50 + reg);
72}
73
74
Ian Rogers2c8f6532011-09-02 17:16:34 -070075void X86Assembler::pushl(const Address& address) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070076 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
77 EmitUint8(0xFF);
78 EmitOperand(6, address);
79}
80
81
Ian Rogers2c8f6532011-09-02 17:16:34 -070082void X86Assembler::pushl(const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070083 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
84 EmitUint8(0x68);
85 EmitImmediate(imm);
86}
87
88
Ian Rogers2c8f6532011-09-02 17:16:34 -070089void X86Assembler::popl(Register reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070090 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
91 EmitUint8(0x58 + reg);
92}
93
94
Ian Rogers2c8f6532011-09-02 17:16:34 -070095void X86Assembler::popl(const Address& address) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070096 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
97 EmitUint8(0x8F);
98 EmitOperand(0, address);
99}
100
101
Ian Rogers2c8f6532011-09-02 17:16:34 -0700102void X86Assembler::movl(Register dst, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700103 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
104 EmitUint8(0xB8 + dst);
105 EmitImmediate(imm);
106}
107
108
Ian Rogers2c8f6532011-09-02 17:16:34 -0700109void X86Assembler::movl(Register dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700110 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
111 EmitUint8(0x89);
112 EmitRegisterOperand(src, dst);
113}
114
115
Ian Rogers2c8f6532011-09-02 17:16:34 -0700116void X86Assembler::movl(Register dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700117 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
118 EmitUint8(0x8B);
119 EmitOperand(dst, src);
120}
121
122
Ian Rogers2c8f6532011-09-02 17:16:34 -0700123void X86Assembler::movl(const Address& dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700124 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
125 EmitUint8(0x89);
126 EmitOperand(src, dst);
127}
128
129
Ian Rogers2c8f6532011-09-02 17:16:34 -0700130void X86Assembler::movl(const Address& dst, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700131 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
132 EmitUint8(0xC7);
133 EmitOperand(0, dst);
134 EmitImmediate(imm);
135}
136
Ian Rogersbdb03912011-09-14 00:55:44 -0700137void X86Assembler::movl(const Address& dst, Label* lbl) {
138 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
139 EmitUint8(0xC7);
140 EmitOperand(0, dst);
141 EmitLabel(lbl, dst.length_ + 5);
142}
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700143
Ian Rogers2c8f6532011-09-02 17:16:34 -0700144void X86Assembler::movzxb(Register dst, ByteRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700145 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
146 EmitUint8(0x0F);
147 EmitUint8(0xB6);
148 EmitRegisterOperand(dst, src);
149}
150
151
Ian Rogers2c8f6532011-09-02 17:16:34 -0700152void X86Assembler::movzxb(Register dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700153 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
154 EmitUint8(0x0F);
155 EmitUint8(0xB6);
156 EmitOperand(dst, src);
157}
158
159
Ian Rogers2c8f6532011-09-02 17:16:34 -0700160void X86Assembler::movsxb(Register dst, ByteRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700161 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
162 EmitUint8(0x0F);
163 EmitUint8(0xBE);
164 EmitRegisterOperand(dst, src);
165}
166
167
Ian Rogers2c8f6532011-09-02 17:16:34 -0700168void X86Assembler::movsxb(Register dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700169 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
170 EmitUint8(0x0F);
171 EmitUint8(0xBE);
172 EmitOperand(dst, src);
173}
174
175
Ian Rogers2c8f6532011-09-02 17:16:34 -0700176void X86Assembler::movb(Register dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700177 LOG(FATAL) << "Use movzxb or movsxb instead.";
178}
179
180
Ian Rogers2c8f6532011-09-02 17:16:34 -0700181void X86Assembler::movb(const Address& dst, ByteRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700182 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
183 EmitUint8(0x88);
184 EmitOperand(src, dst);
185}
186
187
Ian Rogers2c8f6532011-09-02 17:16:34 -0700188void X86Assembler::movb(const Address& dst, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700189 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
190 EmitUint8(0xC6);
191 EmitOperand(EAX, dst);
192 CHECK(imm.is_int8());
193 EmitUint8(imm.value() & 0xFF);
194}
195
196
Ian Rogers2c8f6532011-09-02 17:16:34 -0700197void X86Assembler::movzxw(Register dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700198 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
199 EmitUint8(0x0F);
200 EmitUint8(0xB7);
201 EmitRegisterOperand(dst, src);
202}
203
204
Ian Rogers2c8f6532011-09-02 17:16:34 -0700205void X86Assembler::movzxw(Register dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700206 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
207 EmitUint8(0x0F);
208 EmitUint8(0xB7);
209 EmitOperand(dst, src);
210}
211
212
Ian Rogers2c8f6532011-09-02 17:16:34 -0700213void X86Assembler::movsxw(Register dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700214 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
215 EmitUint8(0x0F);
216 EmitUint8(0xBF);
217 EmitRegisterOperand(dst, src);
218}
219
220
Ian Rogers2c8f6532011-09-02 17:16:34 -0700221void X86Assembler::movsxw(Register dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700222 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
223 EmitUint8(0x0F);
224 EmitUint8(0xBF);
225 EmitOperand(dst, src);
226}
227
228
Ian Rogers2c8f6532011-09-02 17:16:34 -0700229void X86Assembler::movw(Register dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700230 LOG(FATAL) << "Use movzxw or movsxw instead.";
231}
232
233
Ian Rogers2c8f6532011-09-02 17:16:34 -0700234void X86Assembler::movw(const Address& dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700235 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
236 EmitOperandSizeOverride();
237 EmitUint8(0x89);
238 EmitOperand(src, dst);
239}
240
241
Ian Rogers2c8f6532011-09-02 17:16:34 -0700242void X86Assembler::leal(Register dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700243 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
244 EmitUint8(0x8D);
245 EmitOperand(dst, src);
246}
247
248
Ian Rogers2c8f6532011-09-02 17:16:34 -0700249void X86Assembler::cmovl(Condition condition, Register dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700250 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
251 EmitUint8(0x0F);
Ian Rogersb033c752011-07-20 12:22:35 -0700252 EmitUint8(0x40 + condition);
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700253 EmitRegisterOperand(dst, src);
254}
255
256
Ian Rogers2c8f6532011-09-02 17:16:34 -0700257void X86Assembler::setb(Condition condition, Register dst) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700258 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
259 EmitUint8(0x0F);
Ian Rogersb033c752011-07-20 12:22:35 -0700260 EmitUint8(0x90 + condition);
261 EmitOperand(0, Operand(dst));
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700262}
263
264
Ian Rogers2c8f6532011-09-02 17:16:34 -0700265void X86Assembler::movss(XmmRegister dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700266 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
267 EmitUint8(0xF3);
268 EmitUint8(0x0F);
269 EmitUint8(0x10);
270 EmitOperand(dst, src);
271}
272
273
Ian Rogers2c8f6532011-09-02 17:16:34 -0700274void X86Assembler::movss(const Address& dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700275 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
276 EmitUint8(0xF3);
277 EmitUint8(0x0F);
278 EmitUint8(0x11);
279 EmitOperand(src, dst);
280}
281
282
Ian Rogers2c8f6532011-09-02 17:16:34 -0700283void X86Assembler::movss(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700284 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
285 EmitUint8(0xF3);
286 EmitUint8(0x0F);
287 EmitUint8(0x11);
288 EmitXmmRegisterOperand(src, dst);
289}
290
291
Ian Rogers2c8f6532011-09-02 17:16:34 -0700292void X86Assembler::movd(XmmRegister dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700293 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
294 EmitUint8(0x66);
295 EmitUint8(0x0F);
296 EmitUint8(0x6E);
297 EmitOperand(dst, Operand(src));
298}
299
300
Ian Rogers2c8f6532011-09-02 17:16:34 -0700301void X86Assembler::movd(Register dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700302 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
303 EmitUint8(0x66);
304 EmitUint8(0x0F);
305 EmitUint8(0x7E);
306 EmitOperand(src, Operand(dst));
307}
308
309
Ian Rogers2c8f6532011-09-02 17:16:34 -0700310void X86Assembler::addss(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700311 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
312 EmitUint8(0xF3);
313 EmitUint8(0x0F);
314 EmitUint8(0x58);
315 EmitXmmRegisterOperand(dst, src);
316}
317
318
Ian Rogers2c8f6532011-09-02 17:16:34 -0700319void X86Assembler::addss(XmmRegister dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700320 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
321 EmitUint8(0xF3);
322 EmitUint8(0x0F);
323 EmitUint8(0x58);
324 EmitOperand(dst, src);
325}
326
327
Ian Rogers2c8f6532011-09-02 17:16:34 -0700328void X86Assembler::subss(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700329 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
330 EmitUint8(0xF3);
331 EmitUint8(0x0F);
332 EmitUint8(0x5C);
333 EmitXmmRegisterOperand(dst, src);
334}
335
336
Ian Rogers2c8f6532011-09-02 17:16:34 -0700337void X86Assembler::subss(XmmRegister dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700338 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
339 EmitUint8(0xF3);
340 EmitUint8(0x0F);
341 EmitUint8(0x5C);
342 EmitOperand(dst, src);
343}
344
345
Ian Rogers2c8f6532011-09-02 17:16:34 -0700346void X86Assembler::mulss(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700347 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
348 EmitUint8(0xF3);
349 EmitUint8(0x0F);
350 EmitUint8(0x59);
351 EmitXmmRegisterOperand(dst, src);
352}
353
354
Ian Rogers2c8f6532011-09-02 17:16:34 -0700355void X86Assembler::mulss(XmmRegister dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700356 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
357 EmitUint8(0xF3);
358 EmitUint8(0x0F);
359 EmitUint8(0x59);
360 EmitOperand(dst, src);
361}
362
363
Ian Rogers2c8f6532011-09-02 17:16:34 -0700364void X86Assembler::divss(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700365 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
366 EmitUint8(0xF3);
367 EmitUint8(0x0F);
368 EmitUint8(0x5E);
369 EmitXmmRegisterOperand(dst, src);
370}
371
372
Ian Rogers2c8f6532011-09-02 17:16:34 -0700373void X86Assembler::divss(XmmRegister dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700374 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
375 EmitUint8(0xF3);
376 EmitUint8(0x0F);
377 EmitUint8(0x5E);
378 EmitOperand(dst, src);
379}
380
381
Ian Rogers2c8f6532011-09-02 17:16:34 -0700382void X86Assembler::flds(const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700383 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
384 EmitUint8(0xD9);
385 EmitOperand(0, src);
386}
387
388
Ian Rogers2c8f6532011-09-02 17:16:34 -0700389void X86Assembler::fstps(const Address& dst) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700390 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
391 EmitUint8(0xD9);
392 EmitOperand(3, dst);
393}
394
395
Ian Rogers2c8f6532011-09-02 17:16:34 -0700396void X86Assembler::movsd(XmmRegister dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700397 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
398 EmitUint8(0xF2);
399 EmitUint8(0x0F);
400 EmitUint8(0x10);
401 EmitOperand(dst, src);
402}
403
404
Ian Rogers2c8f6532011-09-02 17:16:34 -0700405void X86Assembler::movsd(const Address& dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700406 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
407 EmitUint8(0xF2);
408 EmitUint8(0x0F);
409 EmitUint8(0x11);
410 EmitOperand(src, dst);
411}
412
413
Ian Rogers2c8f6532011-09-02 17:16:34 -0700414void X86Assembler::movsd(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700415 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
416 EmitUint8(0xF2);
417 EmitUint8(0x0F);
418 EmitUint8(0x11);
419 EmitXmmRegisterOperand(src, dst);
420}
421
422
Ian Rogers2c8f6532011-09-02 17:16:34 -0700423void X86Assembler::addsd(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700424 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
425 EmitUint8(0xF2);
426 EmitUint8(0x0F);
427 EmitUint8(0x58);
428 EmitXmmRegisterOperand(dst, src);
429}
430
431
Ian Rogers2c8f6532011-09-02 17:16:34 -0700432void X86Assembler::addsd(XmmRegister dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700433 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
434 EmitUint8(0xF2);
435 EmitUint8(0x0F);
436 EmitUint8(0x58);
437 EmitOperand(dst, src);
438}
439
440
Ian Rogers2c8f6532011-09-02 17:16:34 -0700441void X86Assembler::subsd(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700442 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
443 EmitUint8(0xF2);
444 EmitUint8(0x0F);
445 EmitUint8(0x5C);
446 EmitXmmRegisterOperand(dst, src);
447}
448
449
Ian Rogers2c8f6532011-09-02 17:16:34 -0700450void X86Assembler::subsd(XmmRegister dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700451 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
452 EmitUint8(0xF2);
453 EmitUint8(0x0F);
454 EmitUint8(0x5C);
455 EmitOperand(dst, src);
456}
457
458
Ian Rogers2c8f6532011-09-02 17:16:34 -0700459void X86Assembler::mulsd(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700460 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
461 EmitUint8(0xF2);
462 EmitUint8(0x0F);
463 EmitUint8(0x59);
464 EmitXmmRegisterOperand(dst, src);
465}
466
467
Ian Rogers2c8f6532011-09-02 17:16:34 -0700468void X86Assembler::mulsd(XmmRegister dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700469 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
470 EmitUint8(0xF2);
471 EmitUint8(0x0F);
472 EmitUint8(0x59);
473 EmitOperand(dst, src);
474}
475
476
Ian Rogers2c8f6532011-09-02 17:16:34 -0700477void X86Assembler::divsd(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700478 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
479 EmitUint8(0xF2);
480 EmitUint8(0x0F);
481 EmitUint8(0x5E);
482 EmitXmmRegisterOperand(dst, src);
483}
484
485
Ian Rogers2c8f6532011-09-02 17:16:34 -0700486void X86Assembler::divsd(XmmRegister dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700487 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
488 EmitUint8(0xF2);
489 EmitUint8(0x0F);
490 EmitUint8(0x5E);
491 EmitOperand(dst, src);
492}
493
494
Ian Rogers2c8f6532011-09-02 17:16:34 -0700495void X86Assembler::cvtsi2ss(XmmRegister dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700496 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
497 EmitUint8(0xF3);
498 EmitUint8(0x0F);
499 EmitUint8(0x2A);
500 EmitOperand(dst, Operand(src));
501}
502
503
Ian Rogers2c8f6532011-09-02 17:16:34 -0700504void X86Assembler::cvtsi2sd(XmmRegister dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700505 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
506 EmitUint8(0xF2);
507 EmitUint8(0x0F);
508 EmitUint8(0x2A);
509 EmitOperand(dst, Operand(src));
510}
511
512
Ian Rogers2c8f6532011-09-02 17:16:34 -0700513void X86Assembler::cvtss2si(Register dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700514 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
515 EmitUint8(0xF3);
516 EmitUint8(0x0F);
517 EmitUint8(0x2D);
518 EmitXmmRegisterOperand(dst, src);
519}
520
521
Ian Rogers2c8f6532011-09-02 17:16:34 -0700522void X86Assembler::cvtss2sd(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700523 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
524 EmitUint8(0xF3);
525 EmitUint8(0x0F);
526 EmitUint8(0x5A);
527 EmitXmmRegisterOperand(dst, src);
528}
529
530
Ian Rogers2c8f6532011-09-02 17:16:34 -0700531void X86Assembler::cvtsd2si(Register dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700532 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
533 EmitUint8(0xF2);
534 EmitUint8(0x0F);
535 EmitUint8(0x2D);
536 EmitXmmRegisterOperand(dst, src);
537}
538
539
Ian Rogers2c8f6532011-09-02 17:16:34 -0700540void X86Assembler::cvttss2si(Register dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700541 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
542 EmitUint8(0xF3);
543 EmitUint8(0x0F);
544 EmitUint8(0x2C);
545 EmitXmmRegisterOperand(dst, src);
546}
547
548
Ian Rogers2c8f6532011-09-02 17:16:34 -0700549void X86Assembler::cvttsd2si(Register dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700550 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
551 EmitUint8(0xF2);
552 EmitUint8(0x0F);
553 EmitUint8(0x2C);
554 EmitXmmRegisterOperand(dst, src);
555}
556
557
Ian Rogers2c8f6532011-09-02 17:16:34 -0700558void X86Assembler::cvtsd2ss(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700559 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
560 EmitUint8(0xF2);
561 EmitUint8(0x0F);
562 EmitUint8(0x5A);
563 EmitXmmRegisterOperand(dst, src);
564}
565
566
Ian Rogers2c8f6532011-09-02 17:16:34 -0700567void X86Assembler::cvtdq2pd(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700568 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
569 EmitUint8(0xF3);
570 EmitUint8(0x0F);
571 EmitUint8(0xE6);
572 EmitXmmRegisterOperand(dst, src);
573}
574
575
Ian Rogers2c8f6532011-09-02 17:16:34 -0700576void X86Assembler::comiss(XmmRegister a, XmmRegister b) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700577 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
578 EmitUint8(0x0F);
579 EmitUint8(0x2F);
580 EmitXmmRegisterOperand(a, b);
581}
582
583
Ian Rogers2c8f6532011-09-02 17:16:34 -0700584void X86Assembler::comisd(XmmRegister a, XmmRegister b) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700585 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
586 EmitUint8(0x66);
587 EmitUint8(0x0F);
588 EmitUint8(0x2F);
589 EmitXmmRegisterOperand(a, b);
590}
591
592
Ian Rogers2c8f6532011-09-02 17:16:34 -0700593void X86Assembler::sqrtsd(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700594 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
595 EmitUint8(0xF2);
596 EmitUint8(0x0F);
597 EmitUint8(0x51);
598 EmitXmmRegisterOperand(dst, src);
599}
600
601
Ian Rogers2c8f6532011-09-02 17:16:34 -0700602void X86Assembler::sqrtss(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700603 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
604 EmitUint8(0xF3);
605 EmitUint8(0x0F);
606 EmitUint8(0x51);
607 EmitXmmRegisterOperand(dst, src);
608}
609
610
Ian Rogers2c8f6532011-09-02 17:16:34 -0700611void X86Assembler::xorpd(XmmRegister dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700612 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
613 EmitUint8(0x66);
614 EmitUint8(0x0F);
615 EmitUint8(0x57);
616 EmitOperand(dst, src);
617}
618
619
Ian Rogers2c8f6532011-09-02 17:16:34 -0700620void X86Assembler::xorpd(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700621 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
622 EmitUint8(0x66);
623 EmitUint8(0x0F);
624 EmitUint8(0x57);
625 EmitXmmRegisterOperand(dst, src);
626}
627
628
Ian Rogers2c8f6532011-09-02 17:16:34 -0700629void X86Assembler::xorps(XmmRegister dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700630 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
631 EmitUint8(0x0F);
632 EmitUint8(0x57);
633 EmitOperand(dst, src);
634}
635
636
Ian Rogers2c8f6532011-09-02 17:16:34 -0700637void X86Assembler::xorps(XmmRegister dst, XmmRegister src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700638 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
639 EmitUint8(0x0F);
640 EmitUint8(0x57);
641 EmitXmmRegisterOperand(dst, src);
642}
643
644
Ian Rogers2c8f6532011-09-02 17:16:34 -0700645void X86Assembler::andpd(XmmRegister dst, const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700646 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
647 EmitUint8(0x66);
648 EmitUint8(0x0F);
649 EmitUint8(0x54);
650 EmitOperand(dst, src);
651}
652
653
Ian Rogers2c8f6532011-09-02 17:16:34 -0700654void X86Assembler::fldl(const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700655 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
656 EmitUint8(0xDD);
657 EmitOperand(0, src);
658}
659
660
Ian Rogers2c8f6532011-09-02 17:16:34 -0700661void X86Assembler::fstpl(const Address& dst) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700662 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
663 EmitUint8(0xDD);
664 EmitOperand(3, dst);
665}
666
667
Ian Rogers2c8f6532011-09-02 17:16:34 -0700668void X86Assembler::fnstcw(const Address& dst) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700669 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
670 EmitUint8(0xD9);
671 EmitOperand(7, dst);
672}
673
674
Ian Rogers2c8f6532011-09-02 17:16:34 -0700675void X86Assembler::fldcw(const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700676 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
677 EmitUint8(0xD9);
678 EmitOperand(5, src);
679}
680
681
Ian Rogers2c8f6532011-09-02 17:16:34 -0700682void X86Assembler::fistpl(const Address& dst) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700683 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
684 EmitUint8(0xDF);
685 EmitOperand(7, dst);
686}
687
688
Ian Rogers2c8f6532011-09-02 17:16:34 -0700689void X86Assembler::fistps(const Address& dst) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700690 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
691 EmitUint8(0xDB);
692 EmitOperand(3, dst);
693}
694
695
Ian Rogers2c8f6532011-09-02 17:16:34 -0700696void X86Assembler::fildl(const Address& src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700697 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
698 EmitUint8(0xDF);
699 EmitOperand(5, src);
700}
701
702
Ian Rogers2c8f6532011-09-02 17:16:34 -0700703void X86Assembler::fincstp() {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700704 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
705 EmitUint8(0xD9);
706 EmitUint8(0xF7);
707}
708
709
Ian Rogers2c8f6532011-09-02 17:16:34 -0700710void X86Assembler::ffree(const Immediate& index) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700711 CHECK_LT(index.value(), 7);
712 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
713 EmitUint8(0xDD);
714 EmitUint8(0xC0 + index.value());
715}
716
717
Ian Rogers2c8f6532011-09-02 17:16:34 -0700718void X86Assembler::fsin() {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700719 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
720 EmitUint8(0xD9);
721 EmitUint8(0xFE);
722}
723
724
Ian Rogers2c8f6532011-09-02 17:16:34 -0700725void X86Assembler::fcos() {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700726 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
727 EmitUint8(0xD9);
728 EmitUint8(0xFF);
729}
730
731
Ian Rogers2c8f6532011-09-02 17:16:34 -0700732void X86Assembler::fptan() {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700733 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
734 EmitUint8(0xD9);
735 EmitUint8(0xF2);
736}
737
738
Ian Rogers2c8f6532011-09-02 17:16:34 -0700739void X86Assembler::xchgl(Register dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700740 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
741 EmitUint8(0x87);
742 EmitRegisterOperand(dst, src);
743}
744
745
Ian Rogers2c8f6532011-09-02 17:16:34 -0700746void X86Assembler::cmpl(Register reg, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700747 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
748 EmitComplex(7, Operand(reg), imm);
749}
750
751
Ian Rogers2c8f6532011-09-02 17:16:34 -0700752void X86Assembler::cmpl(Register reg0, Register reg1) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700753 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
754 EmitUint8(0x3B);
755 EmitOperand(reg0, Operand(reg1));
756}
757
758
Ian Rogers2c8f6532011-09-02 17:16:34 -0700759void X86Assembler::cmpl(Register reg, const Address& address) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700760 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
761 EmitUint8(0x3B);
762 EmitOperand(reg, address);
763}
764
765
Ian Rogers2c8f6532011-09-02 17:16:34 -0700766void X86Assembler::addl(Register dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700767 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
768 EmitUint8(0x03);
769 EmitRegisterOperand(dst, src);
770}
771
772
Ian Rogers2c8f6532011-09-02 17:16:34 -0700773void X86Assembler::addl(Register reg, const Address& address) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700774 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
775 EmitUint8(0x03);
776 EmitOperand(reg, address);
777}
778
779
Ian Rogers2c8f6532011-09-02 17:16:34 -0700780void X86Assembler::cmpl(const Address& address, Register reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700781 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
782 EmitUint8(0x39);
783 EmitOperand(reg, address);
784}
785
786
Ian Rogers2c8f6532011-09-02 17:16:34 -0700787void X86Assembler::cmpl(const Address& address, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700788 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
789 EmitComplex(7, address, imm);
790}
791
792
Ian Rogers2c8f6532011-09-02 17:16:34 -0700793void X86Assembler::testl(Register reg1, Register reg2) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700794 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
795 EmitUint8(0x85);
796 EmitRegisterOperand(reg1, reg2);
797}
798
799
Ian Rogers2c8f6532011-09-02 17:16:34 -0700800void X86Assembler::testl(Register reg, const Immediate& immediate) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700801 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
802 // For registers that have a byte variant (EAX, EBX, ECX, and EDX)
803 // we only test the byte register to keep the encoding short.
804 if (immediate.is_uint8() && reg < 4) {
805 // Use zero-extended 8-bit immediate.
806 if (reg == EAX) {
807 EmitUint8(0xA8);
808 } else {
809 EmitUint8(0xF6);
810 EmitUint8(0xC0 + reg);
811 }
812 EmitUint8(immediate.value() & 0xFF);
813 } else if (reg == EAX) {
814 // Use short form if the destination is EAX.
815 EmitUint8(0xA9);
816 EmitImmediate(immediate);
817 } else {
818 EmitUint8(0xF7);
819 EmitOperand(0, Operand(reg));
820 EmitImmediate(immediate);
821 }
822}
823
824
Ian Rogers2c8f6532011-09-02 17:16:34 -0700825void X86Assembler::andl(Register dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700826 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
827 EmitUint8(0x23);
828 EmitOperand(dst, Operand(src));
829}
830
831
Ian Rogers2c8f6532011-09-02 17:16:34 -0700832void X86Assembler::andl(Register dst, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700833 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
834 EmitComplex(4, Operand(dst), imm);
835}
836
837
Ian Rogers2c8f6532011-09-02 17:16:34 -0700838void X86Assembler::orl(Register dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700839 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
840 EmitUint8(0x0B);
841 EmitOperand(dst, Operand(src));
842}
843
844
Ian Rogers2c8f6532011-09-02 17:16:34 -0700845void X86Assembler::orl(Register dst, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700846 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
847 EmitComplex(1, Operand(dst), imm);
848}
849
850
Ian Rogers2c8f6532011-09-02 17:16:34 -0700851void X86Assembler::xorl(Register dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700852 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
853 EmitUint8(0x33);
854 EmitOperand(dst, Operand(src));
855}
856
857
Ian Rogers2c8f6532011-09-02 17:16:34 -0700858void X86Assembler::addl(Register reg, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700859 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
860 EmitComplex(0, Operand(reg), imm);
861}
862
863
Ian Rogers2c8f6532011-09-02 17:16:34 -0700864void X86Assembler::addl(const Address& address, Register reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700865 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
866 EmitUint8(0x01);
867 EmitOperand(reg, address);
868}
869
870
Ian Rogers2c8f6532011-09-02 17:16:34 -0700871void X86Assembler::addl(const Address& address, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700872 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
873 EmitComplex(0, address, imm);
874}
875
876
Ian Rogers2c8f6532011-09-02 17:16:34 -0700877void X86Assembler::adcl(Register reg, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700878 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
879 EmitComplex(2, Operand(reg), imm);
880}
881
882
Ian Rogers2c8f6532011-09-02 17:16:34 -0700883void X86Assembler::adcl(Register dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700884 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
885 EmitUint8(0x13);
886 EmitOperand(dst, Operand(src));
887}
888
889
Ian Rogers2c8f6532011-09-02 17:16:34 -0700890void X86Assembler::adcl(Register dst, const Address& address) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700891 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
892 EmitUint8(0x13);
893 EmitOperand(dst, address);
894}
895
896
Ian Rogers2c8f6532011-09-02 17:16:34 -0700897void X86Assembler::subl(Register dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700898 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
899 EmitUint8(0x2B);
900 EmitOperand(dst, Operand(src));
901}
902
903
Ian Rogers2c8f6532011-09-02 17:16:34 -0700904void X86Assembler::subl(Register reg, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700905 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
906 EmitComplex(5, Operand(reg), imm);
907}
908
909
Ian Rogers2c8f6532011-09-02 17:16:34 -0700910void X86Assembler::subl(Register reg, const Address& address) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700911 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
912 EmitUint8(0x2B);
913 EmitOperand(reg, address);
914}
915
916
Ian Rogers2c8f6532011-09-02 17:16:34 -0700917void X86Assembler::cdq() {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700918 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
919 EmitUint8(0x99);
920}
921
922
Ian Rogers2c8f6532011-09-02 17:16:34 -0700923void X86Assembler::idivl(Register reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700924 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
925 EmitUint8(0xF7);
926 EmitUint8(0xF8 | reg);
927}
928
929
Ian Rogers2c8f6532011-09-02 17:16:34 -0700930void X86Assembler::imull(Register dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700931 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
932 EmitUint8(0x0F);
933 EmitUint8(0xAF);
934 EmitOperand(dst, Operand(src));
935}
936
937
Ian Rogers2c8f6532011-09-02 17:16:34 -0700938void X86Assembler::imull(Register reg, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700939 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
940 EmitUint8(0x69);
941 EmitOperand(reg, Operand(reg));
942 EmitImmediate(imm);
943}
944
945
Ian Rogers2c8f6532011-09-02 17:16:34 -0700946void X86Assembler::imull(Register reg, const Address& address) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700947 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
948 EmitUint8(0x0F);
949 EmitUint8(0xAF);
950 EmitOperand(reg, address);
951}
952
953
Ian Rogers2c8f6532011-09-02 17:16:34 -0700954void X86Assembler::imull(Register reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700955 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
956 EmitUint8(0xF7);
957 EmitOperand(5, Operand(reg));
958}
959
960
Ian Rogers2c8f6532011-09-02 17:16:34 -0700961void X86Assembler::imull(const Address& address) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700962 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
963 EmitUint8(0xF7);
964 EmitOperand(5, address);
965}
966
967
Ian Rogers2c8f6532011-09-02 17:16:34 -0700968void X86Assembler::mull(Register reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700969 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
970 EmitUint8(0xF7);
971 EmitOperand(4, Operand(reg));
972}
973
974
Ian Rogers2c8f6532011-09-02 17:16:34 -0700975void X86Assembler::mull(const Address& address) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700976 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
977 EmitUint8(0xF7);
978 EmitOperand(4, address);
979}
980
981
Ian Rogers2c8f6532011-09-02 17:16:34 -0700982void X86Assembler::sbbl(Register dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700983 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
984 EmitUint8(0x1B);
985 EmitOperand(dst, Operand(src));
986}
987
988
Ian Rogers2c8f6532011-09-02 17:16:34 -0700989void X86Assembler::sbbl(Register reg, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700990 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
991 EmitComplex(3, Operand(reg), imm);
992}
993
994
Ian Rogers2c8f6532011-09-02 17:16:34 -0700995void X86Assembler::sbbl(Register dst, const Address& address) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700996 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
997 EmitUint8(0x1B);
998 EmitOperand(dst, address);
999}
1000
1001
Ian Rogers2c8f6532011-09-02 17:16:34 -07001002void X86Assembler::incl(Register reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001003 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1004 EmitUint8(0x40 + reg);
1005}
1006
1007
Ian Rogers2c8f6532011-09-02 17:16:34 -07001008void X86Assembler::incl(const Address& address) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001009 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1010 EmitUint8(0xFF);
1011 EmitOperand(0, address);
1012}
1013
1014
Ian Rogers2c8f6532011-09-02 17:16:34 -07001015void X86Assembler::decl(Register reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001016 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1017 EmitUint8(0x48 + reg);
1018}
1019
1020
Ian Rogers2c8f6532011-09-02 17:16:34 -07001021void X86Assembler::decl(const Address& address) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001022 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1023 EmitUint8(0xFF);
1024 EmitOperand(1, address);
1025}
1026
1027
Ian Rogers2c8f6532011-09-02 17:16:34 -07001028void X86Assembler::shll(Register reg, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001029 EmitGenericShift(4, reg, imm);
1030}
1031
1032
Ian Rogers2c8f6532011-09-02 17:16:34 -07001033void X86Assembler::shll(Register operand, Register shifter) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001034 EmitGenericShift(4, operand, shifter);
1035}
1036
1037
Ian Rogers2c8f6532011-09-02 17:16:34 -07001038void X86Assembler::shrl(Register reg, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001039 EmitGenericShift(5, reg, imm);
1040}
1041
1042
Ian Rogers2c8f6532011-09-02 17:16:34 -07001043void X86Assembler::shrl(Register operand, Register shifter) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001044 EmitGenericShift(5, operand, shifter);
1045}
1046
1047
Ian Rogers2c8f6532011-09-02 17:16:34 -07001048void X86Assembler::sarl(Register reg, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001049 EmitGenericShift(7, reg, imm);
1050}
1051
1052
Ian Rogers2c8f6532011-09-02 17:16:34 -07001053void X86Assembler::sarl(Register operand, Register shifter) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001054 EmitGenericShift(7, operand, shifter);
1055}
1056
1057
Ian Rogers2c8f6532011-09-02 17:16:34 -07001058void X86Assembler::shld(Register dst, Register src) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001059 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1060 EmitUint8(0x0F);
1061 EmitUint8(0xA5);
1062 EmitRegisterOperand(src, dst);
1063}
1064
1065
Ian Rogers2c8f6532011-09-02 17:16:34 -07001066void X86Assembler::negl(Register reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001067 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1068 EmitUint8(0xF7);
1069 EmitOperand(3, Operand(reg));
1070}
1071
1072
Ian Rogers2c8f6532011-09-02 17:16:34 -07001073void X86Assembler::notl(Register reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001074 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1075 EmitUint8(0xF7);
1076 EmitUint8(0xD0 | reg);
1077}
1078
1079
Ian Rogers2c8f6532011-09-02 17:16:34 -07001080void X86Assembler::enter(const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001081 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1082 EmitUint8(0xC8);
1083 CHECK(imm.is_uint16());
1084 EmitUint8(imm.value() & 0xFF);
1085 EmitUint8((imm.value() >> 8) & 0xFF);
1086 EmitUint8(0x00);
1087}
1088
1089
Ian Rogers2c8f6532011-09-02 17:16:34 -07001090void X86Assembler::leave() {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001091 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1092 EmitUint8(0xC9);
1093}
1094
1095
Ian Rogers2c8f6532011-09-02 17:16:34 -07001096void X86Assembler::ret() {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001097 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1098 EmitUint8(0xC3);
1099}
1100
1101
Ian Rogers2c8f6532011-09-02 17:16:34 -07001102void X86Assembler::ret(const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001103 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1104 EmitUint8(0xC2);
1105 CHECK(imm.is_uint16());
1106 EmitUint8(imm.value() & 0xFF);
1107 EmitUint8((imm.value() >> 8) & 0xFF);
1108}
1109
1110
1111
Ian Rogers2c8f6532011-09-02 17:16:34 -07001112void X86Assembler::nop() {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001113 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1114 EmitUint8(0x90);
1115}
1116
1117
Ian Rogers2c8f6532011-09-02 17:16:34 -07001118void X86Assembler::int3() {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001119 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1120 EmitUint8(0xCC);
1121}
1122
1123
Ian Rogers2c8f6532011-09-02 17:16:34 -07001124void X86Assembler::hlt() {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001125 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1126 EmitUint8(0xF4);
1127}
1128
1129
Ian Rogers2c8f6532011-09-02 17:16:34 -07001130void X86Assembler::j(Condition condition, Label* label) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001131 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1132 if (label->IsBound()) {
1133 static const int kShortSize = 2;
1134 static const int kLongSize = 6;
1135 int offset = label->Position() - buffer_.Size();
1136 CHECK_LE(offset, 0);
1137 if (IsInt(8, offset - kShortSize)) {
1138 EmitUint8(0x70 + condition);
1139 EmitUint8((offset - kShortSize) & 0xFF);
1140 } else {
1141 EmitUint8(0x0F);
1142 EmitUint8(0x80 + condition);
1143 EmitInt32(offset - kLongSize);
1144 }
1145 } else {
1146 EmitUint8(0x0F);
1147 EmitUint8(0x80 + condition);
1148 EmitLabelLink(label);
1149 }
1150}
1151
1152
Ian Rogers2c8f6532011-09-02 17:16:34 -07001153void X86Assembler::jmp(Register reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001154 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1155 EmitUint8(0xFF);
1156 EmitRegisterOperand(4, reg);
1157}
1158
1159
Ian Rogers2c8f6532011-09-02 17:16:34 -07001160void X86Assembler::jmp(Label* label) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001161 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1162 if (label->IsBound()) {
1163 static const int kShortSize = 2;
1164 static const int kLongSize = 5;
1165 int offset = label->Position() - buffer_.Size();
1166 CHECK_LE(offset, 0);
1167 if (IsInt(8, offset - kShortSize)) {
1168 EmitUint8(0xEB);
1169 EmitUint8((offset - kShortSize) & 0xFF);
1170 } else {
1171 EmitUint8(0xE9);
1172 EmitInt32(offset - kLongSize);
1173 }
1174 } else {
1175 EmitUint8(0xE9);
1176 EmitLabelLink(label);
1177 }
1178}
1179
1180
Ian Rogers2c8f6532011-09-02 17:16:34 -07001181X86Assembler* X86Assembler::lock() {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001182 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1183 EmitUint8(0xF0);
Ian Rogers0d666d82011-08-14 16:03:46 -07001184 return this;
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001185}
1186
1187
Ian Rogers2c8f6532011-09-02 17:16:34 -07001188void X86Assembler::cmpxchgl(const Address& address, Register reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001189 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1190 EmitUint8(0x0F);
1191 EmitUint8(0xB1);
1192 EmitOperand(reg, address);
1193}
1194
Ian Rogers2c8f6532011-09-02 17:16:34 -07001195X86Assembler* X86Assembler::fs() {
Ian Rogersb033c752011-07-20 12:22:35 -07001196 // TODO: fs is a prefix and not an instruction
1197 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1198 EmitUint8(0x64);
Ian Rogers0d666d82011-08-14 16:03:46 -07001199 return this;
Ian Rogersb033c752011-07-20 12:22:35 -07001200}
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001201
Ian Rogers2c8f6532011-09-02 17:16:34 -07001202void X86Assembler::AddImmediate(Register reg, const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001203 int value = imm.value();
1204 if (value > 0) {
1205 if (value == 1) {
1206 incl(reg);
1207 } else if (value != 0) {
1208 addl(reg, imm);
1209 }
1210 } else if (value < 0) {
1211 value = -value;
1212 if (value == 1) {
1213 decl(reg);
1214 } else if (value != 0) {
1215 subl(reg, Immediate(value));
1216 }
1217 }
1218}
1219
1220
Ian Rogers2c8f6532011-09-02 17:16:34 -07001221void X86Assembler::LoadDoubleConstant(XmmRegister dst, double value) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001222 // TODO: Need to have a code constants table.
1223 int64_t constant = bit_cast<int64_t, double>(value);
1224 pushl(Immediate(High32Bits(constant)));
1225 pushl(Immediate(Low32Bits(constant)));
1226 movsd(dst, Address(ESP, 0));
1227 addl(ESP, Immediate(2 * kWordSize));
1228}
1229
1230
Ian Rogers2c8f6532011-09-02 17:16:34 -07001231void X86Assembler::FloatNegate(XmmRegister f) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001232 static const struct {
1233 uint32_t a;
1234 uint32_t b;
1235 uint32_t c;
1236 uint32_t d;
1237 } float_negate_constant __attribute__((aligned(16))) =
1238 { 0x80000000, 0x00000000, 0x80000000, 0x00000000 };
1239 xorps(f, Address::Absolute(reinterpret_cast<uword>(&float_negate_constant)));
1240}
1241
1242
Ian Rogers2c8f6532011-09-02 17:16:34 -07001243void X86Assembler::DoubleNegate(XmmRegister d) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001244 static const struct {
1245 uint64_t a;
1246 uint64_t b;
1247 } double_negate_constant __attribute__((aligned(16))) =
1248 {0x8000000000000000LL, 0x8000000000000000LL};
1249 xorpd(d, Address::Absolute(reinterpret_cast<uword>(&double_negate_constant)));
1250}
1251
1252
Ian Rogers2c8f6532011-09-02 17:16:34 -07001253void X86Assembler::DoubleAbs(XmmRegister reg) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001254 static const struct {
1255 uint64_t a;
1256 uint64_t b;
1257 } double_abs_constant __attribute__((aligned(16))) =
1258 {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL};
1259 andpd(reg, Address::Absolute(reinterpret_cast<uword>(&double_abs_constant)));
1260}
1261
1262
Ian Rogers2c8f6532011-09-02 17:16:34 -07001263void X86Assembler::Align(int alignment, int offset) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001264 CHECK(IsPowerOfTwo(alignment));
1265 // Emit nop instruction until the real position is aligned.
1266 while (((offset + buffer_.GetPosition()) & (alignment-1)) != 0) {
1267 nop();
1268 }
1269}
1270
1271
Ian Rogers2c8f6532011-09-02 17:16:34 -07001272void X86Assembler::Bind(Label* label) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001273 int bound = buffer_.Size();
1274 CHECK(!label->IsBound()); // Labels can only be bound once.
1275 while (label->IsLinked()) {
1276 int position = label->LinkPosition();
1277 int next = buffer_.Load<int32_t>(position);
1278 buffer_.Store<int32_t>(position, bound - (position + 4));
1279 label->position_ = next;
1280 }
1281 label->BindTo(bound);
1282}
1283
1284
Ian Rogers2c8f6532011-09-02 17:16:34 -07001285void X86Assembler::Stop(const char* message) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001286 // Emit the message address as immediate operand in the test rax instruction,
1287 // followed by the int3 instruction.
1288 // Execution can be resumed with the 'cont' command in gdb.
1289 testl(EAX, Immediate(reinterpret_cast<int32_t>(message)));
1290 int3();
1291}
1292
1293
Ian Rogers2c8f6532011-09-02 17:16:34 -07001294void X86Assembler::EmitOperand(int rm, const Operand& operand) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001295 CHECK_GE(rm, 0);
1296 CHECK_LT(rm, 8);
1297 const int length = operand.length_;
1298 CHECK_GT(length, 0);
1299 // Emit the ModRM byte updated with the given RM value.
1300 CHECK_EQ(operand.encoding_[0] & 0x38, 0);
1301 EmitUint8(operand.encoding_[0] + (rm << 3));
1302 // Emit the rest of the encoded operand.
1303 for (int i = 1; i < length; i++) {
1304 EmitUint8(operand.encoding_[i]);
1305 }
1306}
1307
1308
Ian Rogers2c8f6532011-09-02 17:16:34 -07001309void X86Assembler::EmitImmediate(const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001310 EmitInt32(imm.value());
1311}
1312
1313
Ian Rogers2c8f6532011-09-02 17:16:34 -07001314void X86Assembler::EmitComplex(int rm,
1315 const Operand& operand,
1316 const Immediate& immediate) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001317 CHECK_GE(rm, 0);
1318 CHECK_LT(rm, 8);
1319 if (immediate.is_int8()) {
1320 // Use sign-extended 8-bit immediate.
1321 EmitUint8(0x83);
1322 EmitOperand(rm, operand);
1323 EmitUint8(immediate.value() & 0xFF);
1324 } else if (operand.IsRegister(EAX)) {
1325 // Use short form if the destination is eax.
1326 EmitUint8(0x05 + (rm << 3));
1327 EmitImmediate(immediate);
1328 } else {
1329 EmitUint8(0x81);
1330 EmitOperand(rm, operand);
1331 EmitImmediate(immediate);
1332 }
1333}
1334
1335
Ian Rogers2c8f6532011-09-02 17:16:34 -07001336void X86Assembler::EmitLabel(Label* label, int instruction_size) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001337 if (label->IsBound()) {
1338 int offset = label->Position() - buffer_.Size();
1339 CHECK_LE(offset, 0);
1340 EmitInt32(offset - instruction_size);
1341 } else {
1342 EmitLabelLink(label);
1343 }
1344}
1345
1346
Ian Rogers2c8f6532011-09-02 17:16:34 -07001347void X86Assembler::EmitLabelLink(Label* label) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001348 CHECK(!label->IsBound());
1349 int position = buffer_.Size();
1350 EmitInt32(label->position_);
1351 label->LinkTo(position);
1352}
1353
1354
Ian Rogers2c8f6532011-09-02 17:16:34 -07001355void X86Assembler::EmitGenericShift(int rm,
1356 Register reg,
1357 const Immediate& imm) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001358 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1359 CHECK(imm.is_int8());
1360 if (imm.value() == 1) {
1361 EmitUint8(0xD1);
1362 EmitOperand(rm, Operand(reg));
1363 } else {
1364 EmitUint8(0xC1);
1365 EmitOperand(rm, Operand(reg));
1366 EmitUint8(imm.value() & 0xFF);
1367 }
1368}
1369
1370
Ian Rogers2c8f6532011-09-02 17:16:34 -07001371void X86Assembler::EmitGenericShift(int rm,
1372 Register operand,
1373 Register shifter) {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001374 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1375 CHECK_EQ(shifter, ECX);
1376 EmitUint8(0xD3);
1377 EmitOperand(rm, Operand(operand));
1378}
1379
Ian Rogers2c8f6532011-09-02 17:16:34 -07001380void X86Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
1381 const std::vector<ManagedRegister>& spill_regs) {
Ian Rogers0d666d82011-08-14 16:03:46 -07001382 CHECK(IsAligned(frame_size, kStackAlignment));
1383 CHECK_EQ(0u, spill_regs.size()); // no spilled regs on x86
Ian Rogersb033c752011-07-20 12:22:35 -07001384 // return address then method on stack
Ian Rogers0d666d82011-08-14 16:03:46 -07001385 addl(ESP, Immediate(-frame_size + kPointerSize /*method*/ +
1386 kPointerSize /*return address*/));
Ian Rogers2c8f6532011-09-02 17:16:34 -07001387 pushl(method_reg.AsX86().AsCpuRegister());
Ian Rogersb033c752011-07-20 12:22:35 -07001388}
1389
Ian Rogers2c8f6532011-09-02 17:16:34 -07001390void X86Assembler::RemoveFrame(size_t frame_size,
Ian Rogers0d666d82011-08-14 16:03:46 -07001391 const std::vector<ManagedRegister>& spill_regs) {
1392 CHECK(IsAligned(frame_size, kStackAlignment));
1393 CHECK_EQ(0u, spill_regs.size()); // no spilled regs on x86
1394 addl(ESP, Immediate(frame_size - kPointerSize));
Ian Rogersb033c752011-07-20 12:22:35 -07001395 ret();
1396}
1397
Ian Rogers2c8f6532011-09-02 17:16:34 -07001398void X86Assembler::IncreaseFrameSize(size_t adjust) {
Ian Rogers0d666d82011-08-14 16:03:46 -07001399 CHECK(IsAligned(adjust, kStackAlignment));
Ian Rogersb033c752011-07-20 12:22:35 -07001400 addl(ESP, Immediate(-adjust));
1401}
1402
Ian Rogers2c8f6532011-09-02 17:16:34 -07001403void X86Assembler::DecreaseFrameSize(size_t adjust) {
Ian Rogers0d666d82011-08-14 16:03:46 -07001404 CHECK(IsAligned(adjust, kStackAlignment));
Ian Rogersb033c752011-07-20 12:22:35 -07001405 addl(ESP, Immediate(adjust));
1406}
1407
Ian Rogers2c8f6532011-09-02 17:16:34 -07001408void X86Assembler::Store(FrameOffset offs, ManagedRegister msrc, size_t size) {
1409 X86ManagedRegister src = msrc.AsX86();
Ian Rogers45a76cb2011-07-21 22:00:15 -07001410 if (src.IsNoRegister()) {
1411 CHECK_EQ(0u, size);
1412 } else if (src.IsCpuRegister()) {
Ian Rogersb033c752011-07-20 12:22:35 -07001413 CHECK_EQ(4u, size);
1414 movl(Address(ESP, offs), src.AsCpuRegister());
Ian Rogers9b269d22011-09-04 14:06:05 -07001415 } else if (src.IsRegisterPair()) {
1416 CHECK_EQ(8u, size);
1417 movl(Address(ESP, offs), src.AsRegisterPairLow());
1418 movl(Address(ESP, FrameOffset(offs.Int32Value()+4)),
1419 src.AsRegisterPairHigh());
Ian Rogers45a76cb2011-07-21 22:00:15 -07001420 } else if (src.IsX87Register()) {
1421 if (size == 4) {
1422 fstps(Address(ESP, offs));
1423 } else {
1424 fstpl(Address(ESP, offs));
1425 }
1426 } else {
1427 CHECK(src.IsXmmRegister());
Ian Rogersb033c752011-07-20 12:22:35 -07001428 if (size == 4) {
1429 movss(Address(ESP, offs), src.AsXmmRegister());
1430 } else {
1431 movsd(Address(ESP, offs), src.AsXmmRegister());
1432 }
1433 }
1434}
1435
Ian Rogers2c8f6532011-09-02 17:16:34 -07001436void X86Assembler::StoreRef(FrameOffset dest, ManagedRegister msrc) {
1437 X86ManagedRegister src = msrc.AsX86();
Ian Rogersb033c752011-07-20 12:22:35 -07001438 CHECK(src.IsCpuRegister());
1439 movl(Address(ESP, dest), src.AsCpuRegister());
1440}
1441
Ian Rogers2c8f6532011-09-02 17:16:34 -07001442void X86Assembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) {
1443 X86ManagedRegister src = msrc.AsX86();
Ian Rogersdf20fe02011-07-20 20:34:16 -07001444 CHECK(src.IsCpuRegister());
1445 movl(Address(ESP, dest), src.AsCpuRegister());
1446}
1447
Ian Rogers2c8f6532011-09-02 17:16:34 -07001448void X86Assembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
1449 ManagedRegister) {
Ian Rogersb033c752011-07-20 12:22:35 -07001450 movl(Address(ESP, dest), Immediate(imm));
1451}
1452
Ian Rogers2c8f6532011-09-02 17:16:34 -07001453void X86Assembler::StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
1454 ManagedRegister) {
Ian Rogers0d666d82011-08-14 16:03:46 -07001455 fs()->movl(Address::Absolute(dest), Immediate(imm));
Ian Rogersb033c752011-07-20 12:22:35 -07001456}
1457
Ian Rogers2c8f6532011-09-02 17:16:34 -07001458void X86Assembler::StoreStackOffsetToThread(ThreadOffset thr_offs,
1459 FrameOffset fr_offs,
1460 ManagedRegister mscratch) {
1461 X86ManagedRegister scratch = mscratch.AsX86();
1462 CHECK(scratch.IsCpuRegister());
1463 leal(scratch.AsCpuRegister(), Address(ESP, fr_offs));
1464 fs()->movl(Address::Absolute(thr_offs), scratch.AsCpuRegister());
1465}
1466
1467void X86Assembler::StoreStackPointerToThread(ThreadOffset thr_offs) {
1468 fs()->movl(Address::Absolute(thr_offs), ESP);
1469}
1470
Ian Rogersbdb03912011-09-14 00:55:44 -07001471void X86Assembler::StoreLabelToThread(ThreadOffset thr_offs, Label* lbl) {
1472 fs()->movl(Address::Absolute(thr_offs), lbl);
1473}
1474
Ian Rogers2c8f6532011-09-02 17:16:34 -07001475void X86Assembler::StoreSpanning(FrameOffset dest, ManagedRegister src,
1476 FrameOffset in_off, ManagedRegister scratch) {
1477 UNIMPLEMENTED(FATAL); // this case only currently exists for ARM
1478}
1479
1480void X86Assembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) {
1481 X86ManagedRegister dest = mdest.AsX86();
Ian Rogers45a76cb2011-07-21 22:00:15 -07001482 if (dest.IsNoRegister()) {
1483 CHECK_EQ(0u, size);
1484 } else if (dest.IsCpuRegister()) {
Ian Rogersb033c752011-07-20 12:22:35 -07001485 CHECK_EQ(4u, size);
1486 movl(dest.AsCpuRegister(), Address(ESP, src));
Ian Rogers9b269d22011-09-04 14:06:05 -07001487 } else if (dest.IsRegisterPair()) {
1488 CHECK_EQ(8u, size);
1489 movl(dest.AsRegisterPairLow(), Address(ESP, src));
1490 movl(dest.AsRegisterPairHigh(), Address(ESP, FrameOffset(src.Int32Value()+4)));
Ian Rogers45a76cb2011-07-21 22:00:15 -07001491 } else if (dest.IsX87Register()) {
1492 if (size == 4) {
1493 flds(Address(ESP, src));
1494 } else {
1495 fldl(Address(ESP, src));
1496 }
Ian Rogersb033c752011-07-20 12:22:35 -07001497 } else {
Ian Rogers45a76cb2011-07-21 22:00:15 -07001498 CHECK(dest.IsXmmRegister());
1499 if (size == 4) {
1500 movss(dest.AsXmmRegister(), Address(ESP, src));
1501 } else {
1502 movsd(dest.AsXmmRegister(), Address(ESP, src));
1503 }
Ian Rogersb033c752011-07-20 12:22:35 -07001504 }
1505}
1506
Ian Rogers2c8f6532011-09-02 17:16:34 -07001507void X86Assembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
1508 X86ManagedRegister dest = mdest.AsX86();
Ian Rogersb033c752011-07-20 12:22:35 -07001509 CHECK(dest.IsCpuRegister());
1510 movl(dest.AsCpuRegister(), Address(ESP, src));
1511}
1512
Ian Rogers2c8f6532011-09-02 17:16:34 -07001513void X86Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base,
1514 MemberOffset offs) {
1515 X86ManagedRegister dest = mdest.AsX86();
Ian Rogersb033c752011-07-20 12:22:35 -07001516 CHECK(dest.IsCpuRegister() && dest.IsCpuRegister());
Ian Rogers2c8f6532011-09-02 17:16:34 -07001517 movl(dest.AsCpuRegister(), Address(base.AsX86().AsCpuRegister(), offs));
Ian Rogersb033c752011-07-20 12:22:35 -07001518}
1519
Ian Rogers2c8f6532011-09-02 17:16:34 -07001520void X86Assembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base,
1521 Offset offs) {
1522 X86ManagedRegister dest = mdest.AsX86();
Ian Rogersa04d3972011-08-17 11:33:44 -07001523 CHECK(dest.IsCpuRegister() && dest.IsCpuRegister());
Ian Rogers2c8f6532011-09-02 17:16:34 -07001524 movl(dest.AsCpuRegister(), Address(base.AsX86().AsCpuRegister(), offs));
Ian Rogersa04d3972011-08-17 11:33:44 -07001525}
1526
Ian Rogers2c8f6532011-09-02 17:16:34 -07001527void X86Assembler::LoadRawPtrFromThread(ManagedRegister mdest,
1528 ThreadOffset offs) {
1529 X86ManagedRegister dest = mdest.AsX86();
Ian Rogersb033c752011-07-20 12:22:35 -07001530 CHECK(dest.IsCpuRegister());
Ian Rogers0d666d82011-08-14 16:03:46 -07001531 fs()->movl(dest.AsCpuRegister(), Address::Absolute(offs));
Ian Rogersb033c752011-07-20 12:22:35 -07001532}
1533
Ian Rogers2c8f6532011-09-02 17:16:34 -07001534void X86Assembler::Move(ManagedRegister mdest, ManagedRegister msrc) {
1535 X86ManagedRegister dest = mdest.AsX86();
1536 X86ManagedRegister src = msrc.AsX86();
Ian Rogersb033c752011-07-20 12:22:35 -07001537 if (!dest.Equals(src)) {
1538 if (dest.IsCpuRegister() && src.IsCpuRegister()) {
1539 movl(dest.AsCpuRegister(), src.AsCpuRegister());
1540 } else {
1541 // TODO: x87, SSE
Ian Rogers2c8f6532011-09-02 17:16:34 -07001542 UNIMPLEMENTED(FATAL) << ": Move " << dest << ", " << src;
Ian Rogersb033c752011-07-20 12:22:35 -07001543 }
1544 }
1545}
1546
Ian Rogers2c8f6532011-09-02 17:16:34 -07001547void X86Assembler::CopyRef(FrameOffset dest, FrameOffset src,
1548 ManagedRegister mscratch) {
1549 X86ManagedRegister scratch = mscratch.AsX86();
1550 CHECK(scratch.IsCpuRegister());
1551 movl(scratch.AsCpuRegister(), Address(ESP, src));
1552 movl(Address(ESP, dest), scratch.AsCpuRegister());
1553}
1554
1555void X86Assembler::CopyRawPtrFromThread(FrameOffset fr_offs,
1556 ThreadOffset thr_offs,
1557 ManagedRegister mscratch) {
1558 X86ManagedRegister scratch = mscratch.AsX86();
1559 CHECK(scratch.IsCpuRegister());
1560 fs()->movl(scratch.AsCpuRegister(), Address::Absolute(thr_offs));
1561 Store(fr_offs, scratch, 4);
1562}
1563
1564void X86Assembler::CopyRawPtrToThread(ThreadOffset thr_offs,
1565 FrameOffset fr_offs,
1566 ManagedRegister mscratch) {
1567 X86ManagedRegister scratch = mscratch.AsX86();
1568 CHECK(scratch.IsCpuRegister());
1569 Load(scratch, fr_offs, 4);
1570 fs()->movl(Address::Absolute(thr_offs), scratch.AsCpuRegister());
1571}
1572
1573void X86Assembler::Copy(FrameOffset dest, FrameOffset src,
1574 ManagedRegister mscratch,
1575 size_t size) {
1576 X86ManagedRegister scratch = mscratch.AsX86();
Ian Rogersb033c752011-07-20 12:22:35 -07001577 if (scratch.IsCpuRegister() && size == 8) {
1578 Load(scratch, src, 4);
1579 Store(dest, scratch, 4);
1580 Load(scratch, FrameOffset(src.Int32Value() + 4), 4);
1581 Store(FrameOffset(dest.Int32Value() + 4), scratch, 4);
1582 } else {
1583 Load(scratch, src, size);
1584 Store(dest, scratch, size);
1585 }
1586}
1587
Ian Rogerse5de95b2011-09-18 20:31:38 -07001588void X86Assembler::MemoryBarrier(ManagedRegister) {
1589#if ANDROID_SMP != 0
1590 EmitUint8(0x0F); // mfence
1591 EmitUint8(0xAE);
Ian Rogerse007b102011-09-19 09:47:09 -07001592 EmitUint8(0xF0);
Ian Rogerse5de95b2011-09-18 20:31:38 -07001593#endif
1594}
1595
Ian Rogers2c8f6532011-09-02 17:16:34 -07001596void X86Assembler::CreateSirtEntry(ManagedRegister mout_reg,
1597 FrameOffset sirt_offset,
1598 ManagedRegister min_reg, bool null_allowed) {
1599 X86ManagedRegister out_reg = mout_reg.AsX86();
1600 X86ManagedRegister in_reg = min_reg.AsX86();
Ian Rogersb033c752011-07-20 12:22:35 -07001601 CHECK(in_reg.IsCpuRegister());
1602 CHECK(out_reg.IsCpuRegister());
Ian Rogers408f79a2011-08-23 18:22:33 -07001603 VerifyObject(in_reg, null_allowed);
Ian Rogersb033c752011-07-20 12:22:35 -07001604 if (null_allowed) {
1605 Label null_arg;
1606 if (!out_reg.Equals(in_reg)) {
1607 xorl(out_reg.AsCpuRegister(), out_reg.AsCpuRegister());
1608 }
1609 testl(in_reg.AsCpuRegister(), in_reg.AsCpuRegister());
Elliott Hughes18c07532011-08-18 15:50:51 -07001610 j(kZero, &null_arg);
Ian Rogers408f79a2011-08-23 18:22:33 -07001611 leal(out_reg.AsCpuRegister(), Address(ESP, sirt_offset));
Ian Rogersb033c752011-07-20 12:22:35 -07001612 Bind(&null_arg);
1613 } else {
Ian Rogers408f79a2011-08-23 18:22:33 -07001614 leal(out_reg.AsCpuRegister(), Address(ESP, sirt_offset));
Ian Rogersb033c752011-07-20 12:22:35 -07001615 }
1616}
1617
Ian Rogers2c8f6532011-09-02 17:16:34 -07001618void X86Assembler::CreateSirtEntry(FrameOffset out_off,
1619 FrameOffset sirt_offset,
1620 ManagedRegister mscratch,
1621 bool null_allowed) {
1622 X86ManagedRegister scratch = mscratch.AsX86();
Ian Rogersb033c752011-07-20 12:22:35 -07001623 CHECK(scratch.IsCpuRegister());
1624 if (null_allowed) {
1625 Label null_arg;
Ian Rogers408f79a2011-08-23 18:22:33 -07001626 movl(scratch.AsCpuRegister(), Address(ESP, sirt_offset));
Ian Rogersb033c752011-07-20 12:22:35 -07001627 testl(scratch.AsCpuRegister(), scratch.AsCpuRegister());
Elliott Hughes18c07532011-08-18 15:50:51 -07001628 j(kZero, &null_arg);
Ian Rogers408f79a2011-08-23 18:22:33 -07001629 leal(scratch.AsCpuRegister(), Address(ESP, sirt_offset));
Ian Rogersb033c752011-07-20 12:22:35 -07001630 Bind(&null_arg);
1631 } else {
Ian Rogers408f79a2011-08-23 18:22:33 -07001632 leal(scratch.AsCpuRegister(), Address(ESP, sirt_offset));
Ian Rogersb033c752011-07-20 12:22:35 -07001633 }
1634 Store(out_off, scratch, 4);
1635}
1636
Ian Rogers408f79a2011-08-23 18:22:33 -07001637// Given a SIRT entry, load the associated reference.
Ian Rogers2c8f6532011-09-02 17:16:34 -07001638void X86Assembler::LoadReferenceFromSirt(ManagedRegister mout_reg,
1639 ManagedRegister min_reg) {
1640 X86ManagedRegister out_reg = mout_reg.AsX86();
1641 X86ManagedRegister in_reg = min_reg.AsX86();
Ian Rogersb033c752011-07-20 12:22:35 -07001642 CHECK(out_reg.IsCpuRegister());
1643 CHECK(in_reg.IsCpuRegister());
1644 Label null_arg;
1645 if (!out_reg.Equals(in_reg)) {
1646 xorl(out_reg.AsCpuRegister(), out_reg.AsCpuRegister());
1647 }
1648 testl(in_reg.AsCpuRegister(), in_reg.AsCpuRegister());
Elliott Hughes18c07532011-08-18 15:50:51 -07001649 j(kZero, &null_arg);
Ian Rogersb033c752011-07-20 12:22:35 -07001650 movl(out_reg.AsCpuRegister(), Address(in_reg.AsCpuRegister(), 0));
1651 Bind(&null_arg);
1652}
1653
Ian Rogers2c8f6532011-09-02 17:16:34 -07001654void X86Assembler::VerifyObject(ManagedRegister src, bool could_be_null) {
Ian Rogersb033c752011-07-20 12:22:35 -07001655 // TODO: not validating references
1656}
1657
Ian Rogers2c8f6532011-09-02 17:16:34 -07001658void X86Assembler::VerifyObject(FrameOffset src, bool could_be_null) {
Ian Rogersb033c752011-07-20 12:22:35 -07001659 // TODO: not validating references
1660}
1661
Ian Rogers2c8f6532011-09-02 17:16:34 -07001662void X86Assembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister) {
1663 X86ManagedRegister base = mbase.AsX86();
Ian Rogersb033c752011-07-20 12:22:35 -07001664 CHECK(base.IsCpuRegister());
Ian Rogersdf20fe02011-07-20 20:34:16 -07001665 call(Address(base.AsCpuRegister(), offset.Int32Value()));
Ian Rogersb033c752011-07-20 12:22:35 -07001666 // TODO: place reference map on call
1667}
1668
Ian Rogers67375ac2011-09-14 00:55:44 -07001669void X86Assembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
1670 Register scratch = mscratch.AsX86().AsCpuRegister();
1671 movl(scratch, Address(ESP, base));
1672 call(Address(scratch, offset));
Carl Shapiroe2d373e2011-07-25 15:20:06 -07001673}
1674
Ian Rogersbdb03912011-09-14 00:55:44 -07001675void X86Assembler::Call(ThreadOffset offset, ManagedRegister mscratch) {
1676 fs()->call(Address::Absolute(offset));
Shih-wei Liao668512a2011-09-01 14:18:34 -07001677}
1678
Ian Rogers2c8f6532011-09-02 17:16:34 -07001679void X86Assembler::GetCurrentThread(ManagedRegister tr) {
1680 fs()->movl(tr.AsX86().AsCpuRegister(),
1681 Address::Absolute(Thread::SelfOffset()));
Shih-wei Liao668512a2011-09-01 14:18:34 -07001682}
1683
Ian Rogers2c8f6532011-09-02 17:16:34 -07001684void X86Assembler::GetCurrentThread(FrameOffset offset,
1685 ManagedRegister mscratch) {
1686 X86ManagedRegister scratch = mscratch.AsX86();
Shih-wei Liao668512a2011-09-01 14:18:34 -07001687 fs()->movl(scratch.AsCpuRegister(), Address::Absolute(Thread::SelfOffset()));
1688 movl(Address(ESP, offset), scratch.AsCpuRegister());
1689}
1690
Ian Rogers2c8f6532011-09-02 17:16:34 -07001691void X86Assembler::SuspendPoll(ManagedRegister scratch,
1692 ManagedRegister return_reg,
1693 FrameOffset return_save_location,
1694 size_t return_size) {
1695 X86SuspendCountSlowPath* slow =
1696 new X86SuspendCountSlowPath(return_reg.AsX86(), return_save_location,
1697 return_size);
Ian Rogers45a76cb2011-07-21 22:00:15 -07001698 buffer_.EnqueueSlowPath(slow);
Ian Rogers0d666d82011-08-14 16:03:46 -07001699 fs()->cmpl(Address::Absolute(Thread::SuspendCountOffset()), Immediate(0));
Elliott Hughes18c07532011-08-18 15:50:51 -07001700 j(kNotEqual, slow->Entry());
Ian Rogers45a76cb2011-07-21 22:00:15 -07001701 Bind(slow->Continuation());
1702}
Ian Rogers0d666d82011-08-14 16:03:46 -07001703
Ian Rogers2c8f6532011-09-02 17:16:34 -07001704void X86SuspendCountSlowPath::Emit(Assembler *sasm) {
1705 X86Assembler* sp_asm = down_cast<X86Assembler*>(sasm);
Ian Rogers0d666d82011-08-14 16:03:46 -07001706#define __ sp_asm->
1707 __ Bind(&entry_);
Ian Rogers45a76cb2011-07-21 22:00:15 -07001708 // Save return value
Ian Rogers0d666d82011-08-14 16:03:46 -07001709 __ Store(return_save_location_, return_register_, return_size_);
Ian Rogerse5de95b2011-09-18 20:31:38 -07001710 // Pass Thread::Current as argument
1711 __ fs()->pushl(Address::Absolute(Thread::SelfOffset()));
1712 __ fs()->call(Address::Absolute(OFFSETOF_MEMBER(Thread, pCheckSuspendFromCode)));
Ian Rogers45a76cb2011-07-21 22:00:15 -07001713 // Release argument
Ian Rogers0d666d82011-08-14 16:03:46 -07001714 __ addl(ESP, Immediate(kPointerSize));
Ian Rogers45a76cb2011-07-21 22:00:15 -07001715 // Reload return value
Ian Rogers0d666d82011-08-14 16:03:46 -07001716 __ Load(return_register_, return_save_location_, return_size_);
1717 __ jmp(&continuation_);
1718#undef __
Ian Rogers45a76cb2011-07-21 22:00:15 -07001719}
1720
Ian Rogers2c8f6532011-09-02 17:16:34 -07001721void X86Assembler::ExceptionPoll(ManagedRegister scratch) {
1722 X86ExceptionSlowPath* slow = new X86ExceptionSlowPath();
Ian Rogers45a76cb2011-07-21 22:00:15 -07001723 buffer_.EnqueueSlowPath(slow);
Ian Rogers0d666d82011-08-14 16:03:46 -07001724 fs()->cmpl(Address::Absolute(Thread::ExceptionOffset()), Immediate(0));
Elliott Hughes18c07532011-08-18 15:50:51 -07001725 j(kNotEqual, slow->Entry());
Ian Rogers45a76cb2011-07-21 22:00:15 -07001726}
Ian Rogers0d666d82011-08-14 16:03:46 -07001727
Ian Rogers2c8f6532011-09-02 17:16:34 -07001728void X86ExceptionSlowPath::Emit(Assembler *sasm) {
1729 X86Assembler* sp_asm = down_cast<X86Assembler*>(sasm);
Ian Rogers0d666d82011-08-14 16:03:46 -07001730#define __ sp_asm->
1731 __ Bind(&entry_);
Ian Rogers45a76cb2011-07-21 22:00:15 -07001732 // NB the return value is dead
Ian Rogers67375ac2011-09-14 00:55:44 -07001733 // Pass exception as argument in EAX
1734 __ fs()->movl(EAX, Address::Absolute(Thread::ExceptionOffset()));
1735 __ fs()->call(Address::Absolute(OFFSETOF_MEMBER(Thread, pDeliverException)));
1736 // this call should never return
1737 __ int3();
Ian Rogers0d666d82011-08-14 16:03:46 -07001738#undef __
Ian Rogers45a76cb2011-07-21 22:00:15 -07001739}
1740
Ian Rogers2c8f6532011-09-02 17:16:34 -07001741} // namespace x86
Ian Rogersb033c752011-07-20 12:22:35 -07001742} // namespace art